mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
API: login and out when using x-api theme
This commit is contained in:
parent
a7e2175a55
commit
111d726de7
11 changed files with 269 additions and 133 deletions
|
@ -404,5 +404,62 @@ def alpha_emoji():
|
|||
return jsonify({"error": "not_yet_implemented"}), 400
|
||||
|
||||
|
||||
# HTML routes
|
||||
from flask import abort, render_template
|
||||
from app.utils import current_theme
|
||||
import os
|
||||
|
||||
@bp.route('/api/alpha/', methods=['GET'])
|
||||
def get_alpha():
|
||||
if not current_app.debug:
|
||||
abort(404)
|
||||
|
||||
template_name = "index.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}')
|
||||
else:
|
||||
return render_template(template_name)
|
||||
|
||||
|
||||
@bp.route('/api/alpha/auth/login', methods=['GET'])
|
||||
def get_alpha_auth_login():
|
||||
if not current_app.debug:
|
||||
abort(404)
|
||||
|
||||
template_name = "auth/login.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}')
|
||||
else:
|
||||
return render_template(template_name)
|
||||
|
||||
|
||||
@bp.route('/api/alpha/auth/logout', methods=['GET'])
|
||||
def get_alpha_auth_logout():
|
||||
if not current_app.debug:
|
||||
abort(404)
|
||||
|
||||
template_name = "auth/logout.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}')
|
||||
else:
|
||||
return render_template(template_name)
|
||||
|
||||
|
||||
@bp.route('/api/alpha/communities', methods=['GET'])
|
||||
def get_alpha_communities():
|
||||
if not current_app.debug:
|
||||
abort(404)
|
||||
|
||||
template_name = "list_communities.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}')
|
||||
else:
|
||||
return render_template(template_name)
|
||||
|
|
38
app/templates/themes/x_api/auth/login.html
Normal file
38
app/templates/themes/x_api/auth/login.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<p class="mb-0">GET <code>/api/alpha/site</code></p>
|
||||
<details><summary>JSON</summary><pre id="site_json"></pre></details>
|
||||
|
||||
<p class="mb-0">POST <code>/api/alpha/user/login</code></p>
|
||||
<details><summary>JSON</summary><pre id="login_json"></pre></details>
|
||||
|
||||
<hr />
|
||||
|
||||
<form id="login_form">
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" id="username" placeholder="Username">
|
||||
<label for="username">Username</label>
|
||||
</div>
|
||||
|
||||
<div class="form-floating my-2">
|
||||
<input type="password" class="form-control" id="password" placeholder="Password">
|
||||
<label for="password">Password</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check text-start my-3">
|
||||
<input class="form-check-input" type="checkbox" id="remember_me">
|
||||
<label class="form-check-label" for="remember_me">Remember me</label>
|
||||
</div>
|
||||
<button class="btn btn-primary w-100 py-2" type="submit">Sign in</button>
|
||||
</form>
|
||||
|
||||
<p class="mt-3">
|
||||
{{ _('New User?') }} <a href="{{ url_for('auth.register') }}">{{ _('Register new account') }}</a>
|
||||
</p>
|
||||
<p class="mt-0">
|
||||
{{ _('Forgot Your Password?') }} <a href="{{ url_for('auth.reset_password_request') }}">{{ _('Reset it') }}</a>
|
||||
</p>
|
||||
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/login.js' }}"></script>
|
||||
{% endblock %}
|
5
app/templates/themes/x_api/auth/logout.html
Normal file
5
app/templates/themes/x_api/auth/logout.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/logout.js' }}"></script>
|
||||
{% endblock %}
|
|
@ -1,9 +1,46 @@
|
|||
{% macro render_username(user, add_domain=True) -%}
|
||||
<span class="render_username">
|
||||
{% if user.deleted -%}
|
||||
[deleted]
|
||||
{% else -%}
|
||||
<a href="/u/{{ user.link() }}" title="{{ user.ap_id if user.ap_id != none else user.user_name }}" aria-label="{{ _('Author') }}">
|
||||
{{ user.display_name() }}{% if not user.is_local() %}<span class="text-muted">@{{ user.ap_domain }}</span>{% endif %}
|
||||
</a>
|
||||
{% if user.bot -%}
|
||||
<span class="fe fe-bot-account" title="Bot account"> </span>
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
</span>
|
||||
{% endmacro -%}
|
||||
|
||||
{% macro render_communityname(community, add_domain=True) -%}
|
||||
<span class="render_community">
|
||||
<a href="/c/{{ community.link() }}" aria-label="{{ _('Go to community %(name)s', name=community.name) }}">
|
||||
{{ community.title }}{% if not community.is_local() %}<span class="text-muted">@{{ community.ap_domain }}</span>{% endif %}
|
||||
</a>
|
||||
</span>
|
||||
{% endmacro -%}
|
||||
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" data-bs-theme="auto">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title id="head-title">{% if not debug_mode %}{{ g.site.name }}{% endif %}</title>
|
||||
<title id="head_title"></title>
|
||||
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta name="MobileOptimized" content="320">
|
||||
<link rel="manifest" href="/static/manifest.json">
|
||||
|
||||
<link id="icon_152" rel="apple-touch-icon" sizes="152x152" href="">
|
||||
<link id="icon_32" rel="icon" type="image/png" sizes="32x32" href="">
|
||||
<link id="icon_16" rel="icon" type="image/png" sizes="16x16" href="">
|
||||
<link id="icon_shortcut" rel="shortcut icon" type="image/png" href="">
|
||||
|
||||
{{ bootstrap.load_css() }}
|
||||
<link href="{{ '/static/themes/' + theme() + '/css/navbars.css' }}" rel="stylesheet">
|
||||
<link href="{{ '/static/themes/' + theme() + '/css/color-modes.css' }}" rel="stylesheet">
|
||||
|
@ -44,99 +81,12 @@
|
|||
|
||||
<nav class="navbar navbar-expand-lg sticky-top bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/" id="navbar-title">{% if not debug_mode %}{{ g.site.name }}{% endif %}</a>
|
||||
<a class="navbar-brand" href="/api/alpha" id="navbar_title"></a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
{% if current_user.is_anonymous %}
|
||||
<li class="nav-item"><a class="nav-link" href="/auth/login">{{ _('Log in') }}</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/auth/register">{{ _('Register') }}</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/donate">{{ _('Donate') }}</a></li>
|
||||
{% else %}
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ _('Communities') }}
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="/communities">{{ _('All communities') }}</a></li>
|
||||
{% if moderating_communities %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><h6 class="dropdown-header">{{ _('Moderating') }}</h6></li>
|
||||
{% for mc in moderating_communities %}
|
||||
<li>
|
||||
<a class="dropdown-item" href="/c/{{ mc.link() }}">{{ mc.title }}<span class="text-body-secondary"> ({{ mc.ap_domain }})</span></a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if joined_communities %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><h6 class="dropdown-header">{{ _('Joined communities') }}</h6></li>
|
||||
{% for jc in joined_communities %}
|
||||
<li>
|
||||
<a class="dropdown-item" href="/c/{{ jc.link() }}">{{ jc.title }}<span class="text-body-secondary"> ({{ jc.ap_domain }})</span></a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ _('Account') }}
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="/u/{{ current_user.link() }}">{{ _('View profile') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/user/settings">{{ _('Edit profile & settings') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/chat">{{ _('Chats') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/bookmarks">{{ _('Bookmarks') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/alerts">{{ _('Activity Alerts') }}</a></li>
|
||||
{% if current_user.hide_read_posts %}
|
||||
<li><a class="dropdown-item" href="/read-posts">{{ _('Read Posts') }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="/donate">{{ _('Donate') }}</a></li>
|
||||
|
||||
{% if user_access('change instance settings', current_user.id) %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ _('Admin') }}
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="/admin/site") }}">{{ _('Site profile') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/misc">{{ _('Misc settings') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/communities">{{ _('Communities') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/topics">{{ _('Topics') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/users?local_remote=local">{{ _('Users') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/users/trash?local_remote=local">{{ _('Monitoring - users') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/content/trash">{{ _('Monitoring - content') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/content/spam">{{ _('Monitoring - spammy content') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/content/deleted">{{ _('Deleted content') }}</a></li>
|
||||
{% if g.site.registration_mode == 'RequireApplication' %}
|
||||
<li><a class="dropdown-item" href="/admin/approve_registrations">{{ _('Registration applications') }}</a></li>
|
||||
{% endif %}
|
||||
<li><a class="dropdown-item" href="/admin/reports">{{ _('Moderation') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/federation">{{ _('Federation') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/instances">{{ _('Instances') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/newsletter">{{ _('Newsletter') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/activities">{{ _('Activities') }}</a></li>
|
||||
<li><a class="dropdown-item" href="/admin/permissions">{{ _('Permissions') }}</a></li>
|
||||
{% if debug_mode %}
|
||||
<li><a class="dropdown-item" href="/dev/tools">{{ _('Dev Tools') }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="/notifications">{{ _('Inbox') }}</a></li>
|
||||
|
||||
<li class="nav-item"><a class="nav-link" href="/auth/logout">{{ _('Log out') }}</a></li>
|
||||
|
||||
{% endif %}
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0" id="navbar_items">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -152,14 +102,12 @@
|
|||
<a href="/donate">{{ _('Donate') }}</a><br />
|
||||
<a href="/about">{{ _('About') }}</a><br />
|
||||
<a href="/keyboard_shortcuts">{{ _('Keyboard shortcuts') }}</a><br/>
|
||||
<a href="https://codeberg.org/rimu/pyfedi">PieFed</a> is free and open source. Please <a href="https://codeberg.org/rimu/pyfedi/issues">report bugs</a> or <a href="https://join.piefed.social/get-involved/">get involved</a>.<br />
|
||||
<a href="https://codeberg.org/rimu/pyfedi">PieFed</a> is free and open source.<br />Please <a href="https://codeberg.org/rimu/pyfedi/issues">report bugs</a> or <a href="https://join.piefed.social/get-involved/">get involved</a>.<br />
|
||||
<a href="/privacy">Privacy policy</a>
|
||||
</small>
|
||||
</footer>
|
||||
|
||||
{{ bootstrap.load_js() }}
|
||||
{% if debug_mode %}
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/site.js' }}"></script>
|
||||
{% endif %}
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/site.js' }}" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
12
app/templates/themes/x_api/donate.html
Normal file
12
app/templates/themes/x_api/donate.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<h1>{{ _('Donate') }}</h1>
|
||||
<p>PieFed is free and open-source software while operating without any advertising, monetization, or reliance on
|
||||
venture capital. Your contributions are vital in supporting the PieFed development effort,
|
||||
allowing us to expand and enhance PieFed with new features.</p>
|
||||
|
||||
<div class="btn-group btn-group-lg" role="group" aria-label="Donation options">
|
||||
<a type="button" class="btn btn-outline-primary" href="https://www.patreon.com/PieFed">Donate using Patreon</a>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,21 +1,6 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<h3>Site Info from API</h3>
|
||||
|
||||
{% if not debug_mode %}
|
||||
<p>(API only available in debug mode)</p>
|
||||
{% else %}
|
||||
<ul>
|
||||
<li><span class="text-body-secondary">version: </span><span id="site_version"></span></li>
|
||||
<li><span class="text-body-secondary">actor_id: </span><span id="site_actor_id"></span></li>
|
||||
<li><span class="text-body-secondary">description: </span><span id="site_description"></span></li>
|
||||
<li><span class="text-body-secondary">enable_downvotes: </span><span id="site_enable_downvotes"></span></li>
|
||||
<li><span class="text-body-secondary">icon: </span><span id="site_icon"></span></li>
|
||||
<li><span class="text-body-secondary">name: </span><span id="site_name"></span></li>
|
||||
<li><span class="text-body-secondary">sidebar: </span><span id="site_sidebar"></span></li>
|
||||
<li><span class="text-body-secondary">user_count: </span><span id="site_user_count"></span></li>
|
||||
<li><span class="text-body-secondary">all languages: </span><span id="site_all_languages"></span></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
<p class="mb-0">GET <code>/api/alpha/site</code></p>
|
||||
<details><summary>JSON</summary><pre id="site_json"></pre></details>
|
||||
{% endblock%}
|
||||
|
|
15
app/templates/themes/x_api/js/list_communities.js
Normal file
15
app/templates/themes/x_api/js/list_communities.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { baseUrl } from './site.js';
|
||||
const api = baseUrl + '/api/alpha/community/list';
|
||||
|
||||
import { jwt } from './site.js';
|
||||
if (jwt != null) {
|
||||
var request = {method: "GET", headers: {Authorization: `Bearer ${jwt}`}};
|
||||
} else {
|
||||
var request = {method: "GET"};
|
||||
}
|
||||
|
||||
fetch(api, request)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.querySelector('#community_list_json').textContent = JSON.stringify(data, null, 2);
|
||||
})
|
38
app/templates/themes/x_api/js/login.js
Normal file
38
app/templates/themes/x_api/js/login.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
document.querySelector('#login_json').textContent = '{"username_or_email": "", "password": ""}'
|
||||
|
||||
const login_form = document.getElementById('login_form');
|
||||
const username = document.getElementById('username');
|
||||
const password = document.getElementById('password');
|
||||
const remember_me = document.getElementById('remember_me');
|
||||
|
||||
login_form.addEventListener('submit', async event => {
|
||||
event.preventDefault();
|
||||
|
||||
json_string = JSON.stringify({ username_or_email: username.value, password: password.value })
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
const baseUrl = `${url.protocol}//${url.host}`;
|
||||
const api = baseUrl + '/api/alpha/user/login';
|
||||
|
||||
try {
|
||||
const response = await fetch(api, {method: 'POST', body: json_string});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
}
|
||||
|
||||
const response_json = await response.json();
|
||||
|
||||
if (remember_me.checked == true) {
|
||||
localStorage.setItem('jwt', response_json['jwt']);
|
||||
} else {
|
||||
sessionStorage.setItem('jwt', response_json['jwt']);
|
||||
}
|
||||
|
||||
window.location.href = baseUrl;
|
||||
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
}
|
||||
});
|
||||
|
||||
|
6
app/templates/themes/x_api/js/logout.js
Normal file
6
app/templates/themes/x_api/js/logout.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
localStorage.removeItem('jwt');
|
||||
sessionStorage.removeItem('jwt');
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
const baseUrl = `${url.protocol}//${url.host}`;
|
||||
window.location.href = baseUrl;
|
|
@ -1,30 +1,52 @@
|
|||
const url = new URL(window.location.href);
|
||||
const baseUrl = `${url.protocol}//${url.host}`;
|
||||
const api = baseUrl + '/api/alpha/site'
|
||||
export const baseUrl = `${url.protocol}//${url.host}`;
|
||||
const api = baseUrl + '/api/alpha/site';
|
||||
|
||||
fetch(api)
|
||||
let jwt = null;
|
||||
let session_jwt = sessionStorage.getItem('jwt');
|
||||
if (session_jwt != null) {
|
||||
jwt = session_jwt;
|
||||
} else {
|
||||
let local_jwt = localStorage.getItem('jwt');
|
||||
if (local_jwt != null) {
|
||||
jwt = local_jwt;
|
||||
}
|
||||
}
|
||||
export { jwt };
|
||||
|
||||
const ul = document.getElementById('navbar_items');
|
||||
if (jwt != null) {
|
||||
var request = {method: "GET", headers: {Authorization: `Bearer ${jwt}`}};
|
||||
ul.innerHTML = '<li class="nav-item dropdown">' +
|
||||
'<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">' +
|
||||
'Communities' +
|
||||
'</a>' +
|
||||
'<ul class="dropdown-menu">' +
|
||||
'<li><a class="dropdown-item" href="/api/alpha/communities">All communities</a></li>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
|
||||
'<li class="nav-item"><a class="nav-link" href="/api/alpha/auth/logout">Logout</a></li>';
|
||||
} else {
|
||||
var request = {method: "GET"};
|
||||
ul.innerHTML = '<li class="nav-item"><a class="nav-link" href="/api/alpha/auth/login">Log in</a></li>' +
|
||||
'<li class="nav-item"><a class="nav-link" href="/donate">Donate</a></li>';
|
||||
}
|
||||
|
||||
fetch(api, request)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// head
|
||||
document.querySelector('#head_title').textContent = data.site.name;
|
||||
document.querySelector('#icon_152').href = data.site.icon_152;
|
||||
document.querySelector('#icon_32').href = data.site.icon_32;
|
||||
document.querySelector('#icon_16').href = data.site.icon_16;
|
||||
document.querySelector('#icon_shortcut').href = data.site.icon_32;
|
||||
|
||||
// navbar
|
||||
document.querySelector('#head-title').textContent = data.site.name
|
||||
document.querySelector('#navbar-title').innerHTML = '<img src="' + data.site.icon + '" alt="Logo" width="36" height="36" />' + ' ' + data.site.name
|
||||
document.querySelector('#navbar_title').innerHTML = '<img src="' + data.site.icon + '" alt="Logo" width="36" height="36" />' + ' ' + data.site.name;
|
||||
|
||||
// site info
|
||||
document.querySelector('#site_version').textContent = data.version
|
||||
document.querySelector('#site_actor_id').textContent = data.site.actor_id
|
||||
document.querySelector('#site_description').textContent = data.site.description
|
||||
document.querySelector('#site_enable_downvotes').textContent = data.site.enable_downvotes
|
||||
document.querySelector('#site_icon').textContent = data.site.icon
|
||||
document.querySelector('#site_name').textContent = data.site.name
|
||||
document.querySelector('#site_sidebar').textContent = data.site.sidebar
|
||||
document.querySelector('#site_user_count').textContent = data.site.user_count
|
||||
|
||||
let lang_names = data.site.all_languages[0].name;
|
||||
let lang_count = data.site.all_languages.length;
|
||||
|
||||
for (let i = 1; i < lang_count; i++) {
|
||||
lang_names += ", " + data.site.all_languages[i].name;
|
||||
}
|
||||
|
||||
document.querySelector('#site_all_languages').textContent = lang_names
|
||||
document.querySelector('#site_json').textContent = JSON.stringify(data, null, 2);
|
||||
})
|
||||
|
||||
|
|
10
app/templates/themes/x_api/list_communities.html
Normal file
10
app/templates/themes/x_api/list_communities.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<p class="mb-0">GET <code>/api/alpha/site</code></p>
|
||||
<details><summary>JSON</summary><pre id="site_json"></pre></details>
|
||||
<p class="mb-0">GET <code>/api/alpha/community/list</code></p>
|
||||
<details><summary>JSON</summary><pre id="community_list_json"></pre></details>
|
||||
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/list_communities.js' }}" type="module"></script>
|
||||
{% endblock %}
|
Loading…
Reference in a new issue