Import pwic as source, add overrides
This commit imports the latest source of the pwic module directly and modifies it just enough for it to be an importable module. Source: https://github.com/gitbra/pwic
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<ul>
|
||||
{% if pwic.env.support_email %}
|
||||
<li>{% trans %}By email:{% endtrans %} <a href="mailto:{{pwic.env.support_email.value|urlencode}}">{{pwic.env.support_email.value|escape}}</a></li>
|
||||
{% endif %}
|
||||
{% if pwic.env.support_phone %}
|
||||
<li>{% trans %}By phone:{% endtrans %} <a href="tel:{{pwic.env.support_phone.value|replace(' ','')|urlencode}}">{{pwic.env.support_phone.value|escape}}</a></li>
|
||||
{% endif %}
|
||||
{% if pwic.env.support_url %}
|
||||
<li>{% trans %}On a portal:{% endtrans %} <a href="{{pwic.env.support_url.value|escape}}">{{pwic.env.support_url.value|escape}}</a></li>
|
||||
{% endif %}
|
||||
{% if pwic.env.support_text %}
|
||||
<li>{{pwic.env.support_text.value|escape|replace('\\n','<br>')}}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
<p id="page_topofpage" class="pwic_hidden">
|
||||
<a href="#top">{{pwic.emojis.top}} {% trans %}Top of the page{% endtrans %} {{pwic.emojis.top}}</a>
|
||||
</p>
|
||||
|
||||
<footer>
|
||||
<div>
|
||||
{% trans %}Powered by{% endtrans %} <a href="https://pwic.wiki">Pwic.wiki</a> v{{pwic.constants.version|escape}} © {% if pwic.env.copyright_years %}{{pwic.env.copyright_years.value|escape}}{% else %}2020-2025{% endif %}
|
||||
{% if not pwic.env.no_help %}
|
||||
— {{pwic.emojis.help}} <a href="/special/help">{% trans %}Help{% endtrans %}</a>
|
||||
{% endif %}
|
||||
—
|
||||
{% if not pwic.user|reserved_user_name %}
|
||||
{{pwic.emojis.laptop}} <a href="/special/user/{{pwic.user|urlencode}}" title="{% trans %}Your profile{% endtrans %}" rel="nofollow">{{pwic.user|escape}}</a> (<a class="pwic_bold" href="/special/logout" onclick="return confirm({% trans %}'Are you sure to disconnect from Pwic.wiki?'{% endtrans %})">{% trans %}Log out{% endtrans %}</a>)
|
||||
{% else %}
|
||||
<a class="pwic_bold" href="/special/login">{% trans %}Log in{% endtrans %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
$('H1,H2,H3,H4,H5,H6,TH,TD,P,DIV,SPAN,A,LI').removeClass('pwic_js');
|
||||
pwic_url_status({% trans %}'The operation is a success.'{% endtrans %}, {% trans %}'The operation failed.'{% endtrans %});
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Connect to Pwic.wiki{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/">{{pwic.emojis.finger_up}} {% trans %}Connect to Pwic.wiki{% endtrans %}</a></div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
{% if pwic.env.no_login %}
|
||||
<p class="pwic_warning">{{pwic.emojis.pin}} {% trans %}This instance is accessible anonymously.{% endtrans %}</p>
|
||||
{% endif %}
|
||||
<p class="pwic_error" id="login_js">{{pwic.emojis.red_check}} {% trans %}Your browser is incompatible or enable JavaScript.{% endtrans %}</p>
|
||||
|
||||
<form id="login_form" action="/api/login?redirect" method="post">
|
||||
<p><strong>{% trans %}User:{% endtrans %}</strong> <input class="pwic_fill" type="text" id="login_user" name="user" autofocus autocomplete="username" required="true" spellcheck="false"></p>
|
||||
<p><strong>{% trans %}Password:{% endtrans %}</strong> <input class="pwic_fill" type="password" id="login_password" name="password" autocomplete="current-password"></p>
|
||||
{% if pwic.env.totp %}
|
||||
<p><strong>{% trans %}Optional PIN code for 2FA:{% endtrans %}</strong>
|
||||
<br><input type="number" id="login_pin" name="pin" min="0" max="999999"></p>
|
||||
{% endif %}
|
||||
<p {% if pwic.constants.languages|count == 1 %} class="pwic_hidden" {% endif %}>
|
||||
<strong>{% trans %}Language:{% endtrans %}</strong>
|
||||
<br><select id="login_language" name="language">
|
||||
{% for lang in pwic.constants.languages %}
|
||||
<option value="{{lang|escape}}"
|
||||
{% if lang == pwic.language %}
|
||||
selected="selected"
|
||||
{% endif %}
|
||||
>{{lang|escape}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<input type="submit" value="{{pwic.emojis.plug}} {% trans %}Log in{% endtrans %}">
|
||||
<input type="button" value="{{pwic.emojis.alien}} {% trans %}Anonymous login{% endtrans %}" onclick="login_anonymous()">
|
||||
{% if pwic.env.oauth_provider %}
|
||||
<input type="button" value="{{pwic.emojis.id}} {% trans %}Federated login{% endtrans %}" onclick="login_oauth()">
|
||||
{% endif %}
|
||||
{% if pwic.env.registration_link %}
|
||||
<input type="button" value="{{pwic.emojis.users}} {% trans %}Register{% endtrans %}" onclick="login_register()">
|
||||
{% endif %}
|
||||
</p>
|
||||
</form>
|
||||
</article>
|
||||
|
||||
{% include 'js/login.js' %}
|
||||
<script>
|
||||
login_translate_langs({ 'de': 'Deutsch',
|
||||
'en': 'English',
|
||||
'fr': 'Français'
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,21 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Disconnected from Pwic.wiki{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/">{% trans %}You are disconnected{% endtrans %}</a></div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p class="pwic_information">{{pwic.emojis.globe}} {% trans %}You successfully logged out.{% endtrans %}</p>
|
||||
|
||||
<p>{% trans %}You can go back to:{% endtrans %}</p>
|
||||
<ol>
|
||||
<li><a href="/">{% trans %}the selection of a new project{% endtrans %}</a></li>
|
||||
<li><a href="/special/login">{% trans %}the login page{% endtrans %}</a></li>
|
||||
</ol>
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,190 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{% if pwic.env.language %}{{pwic.env.language.value|escape}}{% else %}{{pwic.language|escape}}{% endif %}"
|
||||
dir="{% if pwic.env.language and (pwic.env.language.value in pwic.constants.rtl) %}rtl{% else %}ltr{% endif %}">
|
||||
<head>
|
||||
<!-- General headers -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="generator" content="Pwic.wiki version {{pwic.constants.version|escape}}">
|
||||
{% if pwic.env.robots %}
|
||||
<meta name="robots" content="{{pwic.env.robots.value|replace(' ',', ')|escape}}">
|
||||
{% endif %}
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="{{(pwic.description or gettext('No description'))|escape}}">
|
||||
{% if pwic.keywords %}
|
||||
<meta name="keywords" content="{{pwic.keywords|escape}}">
|
||||
{% endif %}
|
||||
<title>{% block title %}{{pwic.title|escape}}{% endblock %}{% if pwic.env.title %} - {{pwic.env.title.value|escape}}{% endif %}</title>
|
||||
{% if pwic.canonical %}
|
||||
<link rel="canonical" href="{{pwic.canonical|escape}}">
|
||||
{% endif %}
|
||||
<link rel="icon" type="image/png" href="/static/favicon.png">
|
||||
{% if pwic.project and (pwic.project not in pwic.constants.not_project) %}
|
||||
{% if not pwic.env.no_sitemap %}
|
||||
<link rel="sitemap" type="application/xml" href="/{{pwic.project|urlencode}}/special/sitemap">
|
||||
{% endif %}
|
||||
{% if not pwic.env.no_search %}
|
||||
<link rel="search" type="application/opensearchdescription+xml" href="/{{pwic.project|urlencode}}/special/searchlink" title="{{ gettext('Search in project %(project)s')|format(project=pwic.project|escape) }}">
|
||||
{% endif %}
|
||||
{% if pwic.env.manifest %}
|
||||
<link rel="manifest" href="/{{pwic.project|urlencode}}/special/manifest">
|
||||
{% endif %}
|
||||
{% if not pwic.env.no_feed and (not pwic.pure_reader or not pwic.env.no_history) %}
|
||||
<link rel="alternate" type="application/atom+xml" href="/{{pwic.project|urlencode}}/special/feed/atom" title="{{ gettext('Recent changes for %(project)s (%(format)s)')|format(project=pwic.project|escape, format='ATOM') }}">
|
||||
<link rel="alternate" type="application/rss+xml" href="/{{pwic.project|urlencode}}/special/feed/rss" title="{{ gettext('Recent changes for %(project)s (%(format)s)')|format(project=pwic.project|escape, format='RSS') }}">
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="/static/styles.css" media="all">
|
||||
{% if pwic.env.css %}
|
||||
{% set list = pwic.env.css.value.split(';') %}
|
||||
{% for css in list %}
|
||||
<link rel="stylesheet" type="text/css" href="{{css|trim|urlencode}}" media="all">
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.env.dark_theme %}
|
||||
<link rel="stylesheet" type="text/css" href="/static/styles_dark.css" media="screen">
|
||||
{% if pwic.env.css_dark %}
|
||||
{% set list = pwic.env.css_dark.value.split(';') %}
|
||||
{% for css in list %}
|
||||
<link rel="stylesheet" type="text/css" href="{{css|trim|urlencode}}" media="screen">
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/static/styles-print.css" media="print">
|
||||
{% if pwic.env.css_printing %}
|
||||
{% set list = pwic.env.css_printing.value.split(';') %}
|
||||
{% for css in list %}
|
||||
<link rel="stylesheet" type="text/css" href="{{css|trim|urlencode}}" media="print">
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.env.no_printing %}
|
||||
<style media="print">
|
||||
BODY { display: none }
|
||||
</style>
|
||||
{% endif %}
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="/static/cash.min.js"></script>
|
||||
{% block header_scripts %}{% endblock %}
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function pwic_entities(value) {
|
||||
return value.replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"');
|
||||
}
|
||||
|
||||
function pwic_is_safe(name) {
|
||||
if (name == '')
|
||||
return false;
|
||||
var chars = '{{pwic.constants.unsafe_chars|replace("\\", "\\\\")|replace("'", "\\'")}}';
|
||||
for (var i=0 ; i<chars.length ; i++)
|
||||
if (name.indexOf(chars[i]) !== -1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function pwic_kick(value, chars) {
|
||||
while (true) {
|
||||
var curlen = value.length;
|
||||
for (var i=0 ; i<chars.length ; i++)
|
||||
value = value.replaceAll(chars[i], '');
|
||||
if (value.length == curlen)
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function pwic_slash(value) {
|
||||
{# sof/18251399 #}
|
||||
return value.split("'").join("\\'").split('"').join('\\"');
|
||||
}
|
||||
|
||||
function pwic_unimoji(value) {
|
||||
return value.replace(/&#x([0-9a-f]+);/gi, (match, v) => {
|
||||
return String.fromCodePoint(parseInt(v, 16));
|
||||
});
|
||||
}
|
||||
|
||||
function pwic_url_status(success, failed) {
|
||||
var url = window.location.toString();
|
||||
if ((url.indexOf('?success') !== -1) || (url.indexOf('&success') !== -1))
|
||||
alert(success);
|
||||
else
|
||||
if ((url.indexOf('?failed') !== -1) || (url.indexOf('&failed') !== -1))
|
||||
alert(failed);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body id="top">
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
{% include 'html/footer.html' %}
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
{% if not pwic.env.no_sort_table %}
|
||||
function pwic_table_sort(that, column) {
|
||||
function _get_sort_key(obj) {
|
||||
var v, list = $(obj).find('INPUT[type=checkbox]');
|
||||
if (list.length > 0)
|
||||
return (!list.prop('checked')).toString();
|
||||
v = (obj.dataset.sort || obj.innerText).trim();
|
||||
if (v == '')
|
||||
return '';
|
||||
if (/^-?\d+( *%)?$/.test(v))
|
||||
return parseInt(v.replace('%', '').trim());
|
||||
v = v.replaceAll(',', '.');
|
||||
if ((/^-?\d+(\.\d*)?(e-?\d+)?$/.test(v)) || (/^-?\.\d+(e-?\d+)?$/.test(v)))
|
||||
return parseFloat(v);
|
||||
return v.trim().toLowerCase();
|
||||
}
|
||||
|
||||
var e = $(that),
|
||||
table = e.parents('TABLE')[0],
|
||||
i, j, op, data, src;
|
||||
|
||||
// Sort order
|
||||
op = parseInt(e.data('sort') || '1');
|
||||
e.data('sort', -op);
|
||||
|
||||
// Cache and sort the data
|
||||
data = [];
|
||||
for (i=1 ; i<table.rows.length ; i++)
|
||||
data.push([i, _get_sort_key($(table.rows[i]).find('TD')[column])]);
|
||||
data.sort(function(a, b) {
|
||||
if (a[1] == b[1])
|
||||
return 0;
|
||||
return (a[1] < b[1] ? -1 : 1) * op;
|
||||
});
|
||||
|
||||
// Update DOM
|
||||
for (i=0 ; i<data.length ; i++) {
|
||||
src = data[i][0];
|
||||
if (src != i + 1) {
|
||||
table.rows[src].parentNode.insertBefore(table.rows[src], table.rows[i+1]);
|
||||
for (j=0; j<data.length; j++)
|
||||
if (data[j][0] < src)
|
||||
data[j][0]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$('TABLE').each(function(i, e) {
|
||||
$(e).find('TR TH').each(function(i, e) {
|
||||
e.innerHTML = '<span class="pwic_cursor" title="{% trans %}Sort{% endtrans %}" onclick="pwic_table_sort(this, '+i+')">' + (e.innerHTML||'...') + '<\/span>';
|
||||
});
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.env.link_new_tab %}
|
||||
$('A[href^="http"]').attr('target','_blank');
|
||||
{% endif %}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,32 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Page not found{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}">{{pwic.project_description|escape}}</a></div>
|
||||
{% if pwic.links|count > 0 %}
|
||||
<div class="pwic_tagbox">
|
||||
{% for link in pwic.links %}
|
||||
<a href="/{{pwic.project|urlencode}}/{{link.page|urlencode}}">{{link.title|escape}}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p class="pwic_error">{{pwic.emojis.padlock}} {% trans %}The page does not exist.{% endtrans %}</p>
|
||||
<p>{% trans %}Please verify your authorizations, the spelling of the link and the revision level of the page.{% endtrans %}</p>
|
||||
<p>{% trans %}You can go back to:{% endtrans %}</p>
|
||||
<ol>
|
||||
<li class="pwic_js"><a href="#" onclick="history.back()">{% trans %}your last browsed page{% endtrans %}</a></li>
|
||||
<li><a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}">{% trans %}the latest revision of the page{% endtrans %}</a></li>
|
||||
<li><a href="/{{pwic.project|urlencode}}">{% trans %}the home page of the project{% endtrans %}</a></li>
|
||||
<li class="pwic_js"><a href="/{{pwic.project|urlencode}}/special/page?page={{pwic.page|urlencode}}">{% trans %}the creation of the missing page{% endtrans %}</a></li>
|
||||
<li><a href="/{{pwic.project|urlencode}}/special">{% trans %}the special page of the project{% endtrans %}</a></li>
|
||||
<li><a href="/">{% trans %}the selection of a new project{% endtrans %}</a></li>
|
||||
</ol>
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,93 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Audit{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}/special">{{pwic.emojis.finger_left}} {% trans %}Audit of the activities{% endtrans %}</a></div>
|
||||
<div class="pwic_ph2">[{{pwic.project|escape}}] {{pwic.project_description|escape}}</div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="pwic_action_bar">
|
||||
<a href="/{{pwic.project|urlencode}}/special/env">{{pwic.emojis.pill}} {% trans %}Settings{% endtrans %}</a>
|
||||
{% if not pwic.env.no_help %}
|
||||
<a href="/special/help#help_setup">{{pwic.emojis.help}} {% trans %}Help{% endtrans %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
<h1>{% trans %}Server information{% endtrans %}</h1>
|
||||
<p>{{ gettext('The server has started on %(date)s at %(time)s.')|format(date=pwic.up.date|escape, time=pwic.up.time|escape) }}</p>
|
||||
<p>{{ gettext('The current time on the server is %(date)s at %(time)s.')|format(date=pwic.systime.date|escape, time=pwic.systime.time|escape) }}</p>
|
||||
<p>{{ gettext('You are connected in %(protocol)s.')|format(protocol=pwic.protocol|escape) }}</p>
|
||||
|
||||
|
||||
<h1>{% trans %}Environment variables{% endtrans %}</h1>
|
||||
<table id="audit_envs">
|
||||
<tr>
|
||||
<th>{% trans %}Key{% endtrans %}</th>
|
||||
<th>{% trans %}Scope{% endtrans %}</th>
|
||||
<th>{% trans %}Value{% endtrans %}</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
{% if pwic.audits|count > 0 %}
|
||||
<h1>{{ gettext('Audit of the last %(n)d days')|format(n=pwic.range) }}</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
<th>{% trans %}Time{% endtrans %}</th>
|
||||
<th>{% trans %}Author{% endtrans %}</th>
|
||||
<th>{% trans %}Event{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Project{% endtrans %}</th>
|
||||
<th>{% trans %}Page{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Reference{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}String{% endtrans %}</th>
|
||||
</tr>
|
||||
|
||||
{% for audit in pwic.audits %}
|
||||
<tr>
|
||||
<td class="pwic_nowrap">{{audit.date|escape}}</td>
|
||||
<td>{{audit.time|escape}}</td>
|
||||
<td><a class="pwic_break" href="/special/user/{{audit.author|urlencode}}" rel="nofollow">{{audit.author|escape}}</a></td>
|
||||
<td>{{audit.event|escape}}</td>
|
||||
<td class="pwic_desktop">
|
||||
{% if audit.project != '' %}
|
||||
<a href="/{{audit.project|urlencode}}">{{audit.project|escape}}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if audit.page != '' %}
|
||||
<a href="/{{audit.project|urlencode}}/{{audit.page|urlencode}}">{{audit.page|escape}}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="pwic_desktop">
|
||||
{% if audit.reference > 0 %}
|
||||
{% if audit.event[-9:] == '-revision' %}
|
||||
<a href="/{{audit.project|urlencode}}/{{audit.page|urlencode}}/rev{{audit.reference|urlencode}}">{{audit.reference|escape}}</a>
|
||||
{% elif audit.event[-9:] == '-document' %}
|
||||
<a href="/special/document/{{audit.reference|urlencode}}?attachment" target="_blank">{{audit.reference|escape}}</a>
|
||||
{% else %}
|
||||
?
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="pwic_desktop">
|
||||
{% if audit.string != '' %}
|
||||
{{audit.string|escape}}
|
||||
{% elif audit.user != '' %}
|
||||
<a class="pwic_break" href="/special/user/{{audit.user|urlencode}}" rel="nofollow">{{audit.user|escape}}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% include 'js/page-audit.js' %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,17 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}">{{pwic.project_description|escape}}</a></div>
|
||||
<div class="pwic_ph2"><a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}/history">{{pwic.emojis.finger_left}} [{{pwic.page|escape}}] {{pwic.title|escape}}</a></div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<h2>Comparison of <a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}/rev{{pwic.old_revision|escape}}">revision {{pwic.old_revision|escape}}</a> and <a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}/rev{{pwic.new_revision|escape}}">revision {{pwic.new_revision|escape}}</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
{{pwic.diff}}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,53 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Create a new page{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/">{{pwic.emojis.finger_left}} {% trans %}Create a new page{% endtrans %}</a></div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
{% if pwic.projects|count == 0 %}
|
||||
|
||||
<p class="pwic_error">{{pwic.emojis.padlock}} {% trans %}You have no authorization to create a new page. Please contact your manager.{% endtrans %}</p>
|
||||
|
||||
{% else %}
|
||||
|
||||
<h1>{% trans %}New page{% endtrans %}</h1>
|
||||
<p><strong>{% trans %}Project:{% endtrans %}</strong><br>
|
||||
<select id="create_project">
|
||||
{% for proj in pwic.projects %}
|
||||
<option value="{{proj.project|escape}}"
|
||||
{% if proj.project == pwic.default_project %} selected="selected" {% endif %}
|
||||
>{{proj.description|escape}} [{{proj.project|escape}}]</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<p><strong>{% trans %}Page identifier:{% endtrans %}</strong>
|
||||
<br><input id="create_kb" type="checkbox"> <label for="create_kb">{% trans %}Generate a knowledge base article{% endtrans %}</label>
|
||||
<br><input id="create_page" class="pwic_fill" type="text" value="{{pwic.default_page|escape}}" spellcheck="false"></p>
|
||||
<p><strong>{% trans %}Tags:{% endtrans %}</strong> <input id="create_tags" class="pwic_fill" type="text" title="{% trans %}No hash and separated by a space{% endtrans %}" spellcheck="false"></p>
|
||||
<p><strong>{% trans %}Milestone:{% endtrans %}</strong> <input id="create_milestone" class="pwic_fill" type="text"></p>
|
||||
|
||||
<h1>{% trans %}Copy in reference to another page{% endtrans %}</h1>
|
||||
<p><strong>{% trans %}Project:{% endtrans %}</strong><br>
|
||||
<select id="create_ref_project">
|
||||
<option value=""></option>
|
||||
{% for p in pwic.projects %}
|
||||
<option value="{{p.project|escape}}">{{p.description|escape}} [{{p.project|escape}}]</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<p><strong>{% trans %}Page identifier:{% endtrans %}</strong> <input id="create_ref_page" class="pwic_fill" type="text" spellcheck="false"></p>
|
||||
<p><input id="create_ref_tags" type="checkbox" checked="checked"> <label for="create_ref_tags">{% trans %}Copy and merge the tags{% endtrans %}</label></p>
|
||||
|
||||
<p><input type="button" value="{{pwic.emojis.sparkles}} {% trans %}Create the page{% endtrans %}" onclick="create_submit()"></p>
|
||||
|
||||
{% include 'js/page-create.js' %}
|
||||
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,149 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block header_scripts %}
|
||||
<link rel="stylesheet" type="text/css" href="/static/codemirror.min.css">
|
||||
<style>
|
||||
.CodeMirror { height: 75vh; margin-top: 5px; border: 1px solid black }
|
||||
</style>
|
||||
<script src="/static/codemirror_md.min.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}">{{pwic.emojis.finger_left}} {% trans %}Edit the page{% endtrans %}</a></div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<h1>[{{pwic.page|escape}}] {{pwic.title|escape}}</h1>
|
||||
|
||||
{% if not pwic.manager and (pwic.protection or not pwic.editor) %}
|
||||
<p class="pwic_error">{{pwic.emojis.padlock}} {% trans %}You are not authorized to edit the page.{% endtrans %}</p>
|
||||
{% else %}
|
||||
<form id="edit_form" action="/api/page/edit" method="post">
|
||||
<p><strong><span class="pwic_red">*</span> {% trans %}Title:{% endtrans %}</strong> <input id="edit_title" class="pwic_fill" type="text" value="{{pwic.title|escape}}"></p>
|
||||
|
||||
<p><strong>{% trans %}Tags:{% endtrans %}</strong> <input id="edit_tags" class="pwic_fill" type="text" value="{{pwic.tags|escape}}" title="{% trans %}No hash and separated by a space{% endtrans %}" spellcheck="false"></p>
|
||||
|
||||
<div id="edit_toolbar">
|
||||
<div>
|
||||
<input type="button" value="{{pwic.emojis.glasses}}" title="{% trans %}Preview{% endtrans %}" onclick="edit_preview_md('{{pwic.page|urlencode}}')" data-shortcut="Ctrl-E">
|
||||
<input type="button" value="{{pwic.emojis.round_arrow_left}}" title="{% trans %}Undo{% endtrans %}" onclick="edit_undo(true)" data-shortcut="Ctrl-Z">
|
||||
<input type="button" value="{{pwic.emojis.round_arrow_right}}" title="{% trans %}Redo{% endtrans %}" onclick="edit_undo(false)" data-shortcut="Ctrl-Y">
|
||||
</div>
|
||||
<div>
|
||||
<input type="button" value="B" title="** {% trans %}Bold{% endtrans %} **" style="font-weight: bold" onclick="edit_decorate('**', '**')" data-shortcut="Ctrl-B">
|
||||
<input type="button" value="I" title="* {% trans %}Italic{% endtrans %} *" style="font-style: italic" onclick="edit_decorate('*', '*')" data-shortcut="Ctrl-I">
|
||||
<input type="button" value="U" title="-- {% trans %}Underline{% endtrans %} --" style="text-decoration: underline" onclick="edit_decorate('--', '--')" data-shortcut="Ctrl-U">
|
||||
<input type="button" value="S" title="~~ {% trans %}Strikethrough{% endtrans %} ~~" style="text-decoration: line-through" onclick="edit_decorate('~~', '~~')">
|
||||
<input type="button" value="^2" title="<sup> {% trans %}Superscript{% endtrans %} </sup>" onclick="edit_decorate('<sup>', '</sup>')">
|
||||
<input type="button" value="_2" title="<sub> {% trans %}Subscript{% endtrans %} </sub>" onclick="edit_decorate('<sub>', '</sub>')">
|
||||
<input type="button" value="{{pwic.emojis.chains}}" title="[{% trans %}Link{% endtrans %}](url)" onclick="edit_link()" data-shortcut="Ctrl-K">
|
||||
</div>
|
||||
<div>
|
||||
<input type="button" value="abCD" title="{% trans %}Upper/Lower case{% endtrans %}" onclick="edit_switch_case()" data-shortcut="Shift-F3">
|
||||
<input type="button" value="{{pwic.emojis.double}}" title="{% trans %}No double spaces{% endtrans %}" onclick="edit_double_spaces()">
|
||||
<input type="button" value="{{pwic.emojis.right}}" title="{% trans %}Shift to the right{% endtrans %}" onclick="edit_prepend(' ')">
|
||||
<input type="button" value="{{pwic.emojis.left}}" title="{% trans %}Shift to the left{% endtrans %}" onclick="edit_left_line()">
|
||||
<input type="button" value="{{pwic.emojis.noblank}}" title="{% trans %}No blank line{% endtrans %}" onclick="edit_no_blank_line()">
|
||||
<input type="button" value="{{pwic.emojis.oneline}}" title="{% trans %}As single line{% endtrans %}" onclick="edit_single_line()">
|
||||
</div>
|
||||
<div>
|
||||
<input type="button" value="H1" title="# {% trans %}Title{% endtrans %} 1" onclick="edit_prepend('# ')" data-shortcut="Shift-Ctrl-F1">
|
||||
<input type="button" value="H2" title="## {% trans %}Title{% endtrans %} 2" onclick="edit_prepend('## ')" data-shortcut="Shift-Ctrl-F2">
|
||||
<input type="button" value="H3" title="### {% trans %}Title{% endtrans %} 3" onclick="edit_prepend('### ')" data-shortcut="Shift-Ctrl-F3">
|
||||
<input type="button" value="H4" title="#### {% trans %}Title{% endtrans %} 4" onclick="edit_prepend('#### ')" data-shortcut="Shift-Ctrl-F4">
|
||||
<input type="button" value="H5" title="##### {% trans %}Title{% endtrans %} 5" onclick="edit_prepend('##### ')" data-shortcut="Shift-Ctrl-F5">
|
||||
<input type="button" value="H6" title="###### {% trans %}Title{% endtrans %} 6" onclick="edit_prepend('###### ')" data-shortcut="Shift-Ctrl-F6">
|
||||
<input type="button" value="{% trans %}Footnote{% endtrans %}" title="[^1] {% trans %}Footnote{% endtrans %}" onclick="edit_footnote()">
|
||||
<input type="button" value="[{% trans %}Annotation{% endtrans %}]" title="<!-- {% trans %}Annotation{% endtrans %} -->" onclick="edit_decorate('<!-- ', ' -->')">
|
||||
</div>
|
||||
<div>
|
||||
<input type="button" value="{% trans %}Line{% endtrans %}" title="{% trans %}Horizontal line{% endtrans %}" onclick="edit_decorate('\n---\n\n', '')">
|
||||
<input id="edit_toolbar_table" type="button" value="Table" title="{% trans %}Table{% endtrans %} | {% trans %}Table{% endtrans %}" onclick="edit_table()">
|
||||
<input type="button" value="{% trans %}AutoTable{% endtrans %}" title="{% trans %}Paste as target table{% endtrans %}" onclick="edit_table_import()">
|
||||
<input type="button" value="- {% trans %}List{% endtrans %}" title="- {% trans %}Bulleted list{% endtrans %}" onclick="edit_prepend('- ')" data-shortcut="Ctrl-L">
|
||||
<input type="button" value="1. {% trans %}List{% endtrans %}" title="1. {% trans %}Numbered list{% endtrans %}" onclick="edit_prepend_nlist()">
|
||||
<input type="button" value="- [X] {% trans %}Tasks{% endtrans %}" onclick="edit_prepend('- [ ] ')">
|
||||
<input type="button" value="> {% trans %}Quote{% endtrans %}" onclick="edit_prepend('> ')">
|
||||
<input type="button" value=">! {% trans %}Spoiler{% endtrans %}" onclick="edit_prepend('>! ')">
|
||||
<input type="button" value="`{% trans %}Keyword{% endtrans %}`" title="`{% trans %}Monospaced keyword{% endtrans %}`" onclick="edit_decorate('`', '`')" data-shortcut="Ctrl-'">
|
||||
<input type="button" value="{% trans %}Code{% endtrans %}" title="```{% trans %}Code{% endtrans %}```" onclick="edit_decorate('```\n', '\n```')">
|
||||
{% if pwic.env.emojis %}
|
||||
<input type="button" value="{{pwic.emojis.bang}}" title="{% trans %}Emojis{% endtrans %}" onclick="$('#edit_emojis').toggleClass('pwic_hidden');md_editor.focus()">
|
||||
{% endif %}
|
||||
{% if pwic.env.remote_url %}
|
||||
<input type="button" value="{{pwic.emojis.recycle}}" title="{% trans %}Fetch a remote web page{% endtrans %}" onclick="edit_convert_remote_document()">
|
||||
{% endif %}
|
||||
{% if not pwic.env.no_dictation %}
|
||||
<input id="edit_toolbar_dictate" type="button" value="{{pwic.emojis.microphone}}" title="{% trans %}Dictate{% endtrans %}">
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if pwic.env.emojis %}
|
||||
<div id="edit_emojis" class="pwic_hidden">
|
||||
{% set list = pwic.emojis_toolbar.split(' ') %}
|
||||
{% for e in list %}
|
||||
{% if e|is_hex %}
|
||||
{% if e[-4:] == 'fe0f' %}
|
||||
{% set e = '&#x' + e[:-4]|upper + ';️' %}
|
||||
{% else %}
|
||||
{% set e = '&#x' + e|upper + ';' %}
|
||||
{% endif %}
|
||||
<span title="{% trans %}Insert{% endtrans %}" onclick="edit_decorate_end('{{e|escape}} ')">{{e}}</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<textarea id="edit_markdown">{{pwic.markdown|escape}}</textarea>
|
||||
|
||||
{% if (not pwic.env.document_size_max) or (pwic.env.document_size_max.value|int > 0) %}
|
||||
<h2>{% trans %}Documents{% endtrans %}</h2>
|
||||
<div id="edit_files_drop" ondrop="edit_drop(event)" ondragover="edit_dragover(event)" ondragleave="edit_dragleave(event)">
|
||||
<input type="button" value="{{pwic.emojis.refresh}}" title="{% trans %}Refresh{% endtrans %}" onclick="edit_refresh_documents()">
|
||||
<input class="pwic_mobile" type="button" value="{{pwic.emojis.inbox}}" title="{% trans %}Upload a new document{% endtrans %}" onclick="edit_upload_document()" style="margin-left: 15px">
|
||||
<br>
|
||||
{% trans %}Drop the files here{% endtrans %}
|
||||
{% if pwic.env.document_size_max %}
|
||||
({% trans %}max:{% endtrans %} {{pwic.env.document_size_max.value|size2str|escape}})
|
||||
{% endif %}
|
||||
|
||||
{% trans %}and save immediately{% endtrans %}
|
||||
</div>
|
||||
<table id="edit_files_list" class="pwic_break">
|
||||
<tr>
|
||||
<th>{% trans %}Action{% endtrans %}</th>
|
||||
<th>{% trans %}File name{% endtrans %}</th>
|
||||
<th class="pwic_desktop" title="{% trans %}For the latest saved revision only{% endtrans %}">{% trans %}Used{% endtrans %}</th>
|
||||
<th>{% trans %}Size{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Format{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Author{% endtrans %}</th>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Time{% endtrans %}</th>
|
||||
<th>{% trans %}File{% endtrans %}</th>
|
||||
</tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<h2>{% trans %}Attributes{% endtrans %}</h2>
|
||||
<p><strong><span class="pwic_red">*</span> {% trans %}Reason for the modification:{% endtrans %}</strong> <input id="edit_comment" class="pwic_fill" type="text" placeholder="{{pwic.comment|escape}}"></p>
|
||||
<p><strong>{% trans %}Milestone:{% endtrans %}</strong> <input id="edit_milestone" class="pwic_fill" type="text" value="{{pwic.milestone|escape}}" title="{% trans %}Free text to report the expected readiness of the page{% endtrans %}"></p>
|
||||
<p>
|
||||
<input id="edit_draft" type="checkbox" {% if pwic.draft %}checked="checked"{% endif %} onclick="$('#edit_final').prop('checked', false)"> <label for="edit_draft">{% trans %}Draft{% endtrans %}</label>
|
||||
<br><input id="edit_final" type="checkbox" onclick="$('#edit_draft').prop('checked', false)"> <label for="edit_final">{% trans %}Final version{% endtrans %}</label>
|
||||
<br><input id="edit_header" type="checkbox" {% if pwic.header %}checked="checked"{% endif %} {% if not pwic.manager %}disabled="disabled"{% endif %}> <label for="edit_header">{% trans %}Header line *{% endtrans %}</label>
|
||||
<br><input id="edit_protection" type="checkbox" {% if pwic.protection %}checked="checked"{% endif %} {% if not pwic.manager %}disabled="disabled"{% endif %}> <label for="edit_protection">{% trans %}Protected page *{% endtrans %}</label>
|
||||
</p>
|
||||
<p>
|
||||
<input id="edit_submit" type="button" value="{{pwic.emojis.save}} {% trans %}Save the modifications{% endtrans %}" onclick="edit_submit_form()">
|
||||
<input id="edit_preview" type="button" value="{{pwic.emojis.glasses}} {% trans %}Preview{% endtrans %}" onclick="edit_preview_md('{{pwic.page|urlencode}}')">
|
||||
</p>
|
||||
</form>
|
||||
|
||||
{% include 'js/page-edit.js' %}
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,37 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Project-dependent environment variables{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}/special">{{pwic.emojis.finger_left}} {% trans %}Project-dependent settings{% endtrans %}</a></div>
|
||||
<div class="pwic_ph2">[{{pwic.project|escape}}] {{pwic.project_description|escape}}</div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p>{% trans %}The following settings are changeable online and they are applicable to the current project only.{% endtrans %}</p>
|
||||
<p>{{ gettext('Refer to your administrator to configure the <a href="/%(project)s/special/audit">other environment variables</a> (whose details are available in the <a href="/special/help#help_setup">help page</a>), or if you want a setting to apply once for all the projects hosted on the server.')|format(project=pwic.project|urlencode) }}</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th style="width:33%">{% trans %}Variable{% endtrans %}</th>
|
||||
<th style="width:67%">{% trans %}Value{% endtrans %}</th>
|
||||
</tr>
|
||||
{% for key in pwic.changeable_vars %}
|
||||
<tr>
|
||||
<td><code>{{key|escape}}</code></td>
|
||||
<td style="padding-right: 10px">
|
||||
<input class="pwic_fill" type="text" data-key="{{key|escape}}">
|
||||
<input type="button" data-key="{{key|escape}}" value="{{pwic.emojis.save}} {% trans %}Save{% endtrans %}">
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<p class="pwic_center"><a href="env" onclick="return confirm({% trans %}'Are you sure to reset the current changes?'{% endtrans %})">{% trans %}Cancel the current modifications{% endtrans %}</a></p>
|
||||
</article>
|
||||
|
||||
{% include 'js/page-env.js' %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,19 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Graph of the project{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}/special">{{pwic.emojis.finger_left}} {% trans %}Visual representation of the pages{% endtrans %}</a></div>
|
||||
<div class="pwic_ph2">[{{pwic.project|escape}}] {{pwic.project_description|escape}}</div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p><input type="button" value="{{pwic.emojis.inbox}} {% trans %}Download as a file{% endtrans %}" onclick="graph_get_data('download')"></p>
|
||||
<div id="graph_viz"></div>
|
||||
|
||||
{% include 'js/page-graph.js' %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,50 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}">{{pwic.emojis.finger_left}} {% trans %}History of the modifications{% endtrans %}</a></div>
|
||||
<div class="pwic_ph2"><a href="/{{pwic.project|urlencode}}">[{{pwic.project|escape}}] {{pwic.project_description|escape}}</a></div>
|
||||
</header>
|
||||
|
||||
{% include 'js/page-history.js' %}
|
||||
|
||||
<article>
|
||||
<h1>[{{pwic.page|escape}}] {{pwic.title|escape}}</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<th class="pwic_js"><span class="pwic_desktop">{% trans %}Compare{% endtrans %}</span></th>
|
||||
<th>{% trans %}Rev<span class="pwic_desktop">ision</span>{% endtrans %}</th>
|
||||
<th>{% trans %}Flags{% endtrans %}</th>
|
||||
<th>{% trans %}Author{% endtrans %}</th>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Time{% endtrans %}</th>
|
||||
<th>{% trans %}Comment{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Milestone{% endtrans %}</th>
|
||||
</tr>
|
||||
|
||||
{% for rev in pwic.revisions %}
|
||||
<tr>
|
||||
<td class="pwic_js"><input type="checkbox" data-revision="{{rev.revision|escape}}" onclick="return history_compare()"></td>
|
||||
<td><a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}/rev{{rev.revision|urlencode}}">{{rev.revision|escape}}</a></td>
|
||||
<td>
|
||||
{% if rev.draft %}
|
||||
<span title="{% trans %}Draft{% endtrans %}">{{pwic.emojis.hourglass}}</span>
|
||||
{% endif %}
|
||||
{% if rev.final %}
|
||||
<span title="{% trans %}Marked as final{% endtrans %}">{{pwic.emojis.notes}}</span>
|
||||
{% endif %}
|
||||
{% if rev.valuser != '' %}
|
||||
<span title="{{ gettext('Validated by %(valuser)s on %(valdate)s at %(valtime)s.')|format(valuser=rev.valuser|escape, valdate=rev.valdate|escape, valtime=rev.valtime|escape) }}">{{pwic.emojis.flag}}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a class="pwic_break" href="/special/user/{{rev.author|urlencode}}" rel="nofollow">{{rev.author|escape}}</a></td>
|
||||
<td>{{rev.date|escape}}</td>
|
||||
<td class="pwic_desktop">{{rev.time|escape}}</td>
|
||||
<td>{{rev.comment|escape}}</td>
|
||||
<td class="pwic_desktop">{{rev.milestone|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,68 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Report of the links{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}/special">{{pwic.emojis.finger_left}} {% trans %}Verification of the links{% endtrans %}</a></div>
|
||||
<div class="pwic_ph2">[{{pwic.project|escape}}] {{pwic.project_description|escape}}</div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<h1>{% trans %}Orphaned pages{% endtrans %}</h1>
|
||||
{% if pwic.orphans|count == 0 %}
|
||||
<p>{% trans %}You have no orphaned page.{% endtrans %}</p>
|
||||
{% else %}
|
||||
<p>{% trans %}These pages cannot be reached by simple clicks but are still referenced by the search engine.{% endtrans %}</p>
|
||||
<ul>
|
||||
{% for page in pwic.orphans %}
|
||||
<li><a href="/{{pwic.project|urlencode}}/{{page|urlencode}}">{{page|escape}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<h1>{% trans %}Broken links to a page{% endtrans %}</h1>
|
||||
{% if pwic.broken|count == 0 %}
|
||||
<p>{% trans %}You have no broken link to a page.{% endtrans %}</p>
|
||||
{% else %}
|
||||
<p>{% trans %}A broken link displays the error 404 because the targeted page does not exist.{% endtrans %}</p>
|
||||
<table class="pwic_fit">
|
||||
<tr>
|
||||
<th>{% trans %}Page{% endtrans %}</th>
|
||||
<th>{% trans %}Non-existent page{% endtrans %}</th>
|
||||
</tr>
|
||||
{% for page in pwic.broken %}
|
||||
<tr>
|
||||
<td><a href="/{{pwic.project|urlencode}}/{{page[0]|urlencode}}">{{page[0]|escape}}</a></td>
|
||||
<td>{{pwic.emojis.sheet}} <a href="/{{pwic.project|urlencode}}/special/page?page={{page[1]|urlencode}}" title="{% trans %}Create the page{% endtrans %}">{{page[1]|escape}}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p class="pwic_italic">{% trans %}Note: the table does not check the links to the other projects.{% endtrans %}</p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<h1>{% trans %}Broken links to a document{% endtrans %}</h1>
|
||||
{% if pwic.broken_docs|count == 0 %}
|
||||
<p>{% trans %}You have no broken link to a document.{% endtrans %}</p>
|
||||
{% else %}
|
||||
<p>{% trans %}Managing the files without updating the pages may result in invalid links.{% endtrans %}</p>
|
||||
<table class="pwic_fit">
|
||||
<tr>
|
||||
<th>{% trans %}Page{% endtrans %}</th>
|
||||
<th>{% trans %}Non-existent document{% endtrans %}</th>
|
||||
</tr>
|
||||
{% for page in pwic.broken_docs %}
|
||||
<tr>
|
||||
<td><a href="/{{pwic.project|urlencode}}/{{page|urlencode}}/edit">{{page|escape}}</a></td>
|
||||
<td>{{pwic.broken_docs[page]|sort|join(', ')|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,58 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Move a page{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}">{{pwic.emojis.finger_left}} {% trans %}Move the page and its attachments{% endtrans %}</a></div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<h1>[{{pwic.project|escape}}/{{pwic.page|escape}}] {{pwic.title|escape}}</h1>
|
||||
|
||||
<input id="move_src_project" type="hidden" value="{{pwic.project|escape}}">
|
||||
<input id="move_src_page" type="hidden" value="{{pwic.page|escape}}">
|
||||
|
||||
<p><strong>{% trans %}Target project:{% endtrans %}</strong><br>
|
||||
<select id="move_dst_project">
|
||||
{% for proj in pwic.projects %}
|
||||
<option value="{{proj.project|escape}}"
|
||||
{% if proj.project == pwic.project %} selected="selected" {% endif %}
|
||||
>{{proj.description|escape}} [{{proj.project|escape}}]</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<p><strong>{% trans %}Target page identifier:{% endtrans %}</strong> <input id="move_dst_page" class="pwic_fill" type="text" placeholder="{{pwic.page|escape}}" spellcheck="false"></p>
|
||||
|
||||
<p><input type="button" value="{{pwic.emojis.truck}} {% trans %}Move the page{% endtrans %}" onclick="move_submit()"></p>
|
||||
|
||||
<p class="pwic_italic">
|
||||
{% trans %}This form can be used to rename an existing page.{% endtrans %}
|
||||
|
||||
{% if pwic.relations|count > 0 %}
|
||||
{% trans %}No link will be updated within the following pages:{% endtrans %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% if pwic.relations|count > 0 %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>{% trans %}Link{% endtrans %}</th>
|
||||
<th>{% trans %}Title{% endtrans %}</th>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
</tr>
|
||||
{% for row in pwic.relations %}
|
||||
<tr>
|
||||
<td><a href="/{{row.project|urlencode}}/{{row.page|urlencode}}">/{{row.project|escape}}/{{row.page|escape}}</a></td>
|
||||
<td>{{row.title|escape}}</td>
|
||||
<td>{{row.date|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% include 'js/page-move.js' %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,261 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}">{{pwic.emojis.finger_up}} {{pwic.project_description|escape}}</a></div>
|
||||
{% if (not pwic.env.no_search) or (pwic.links|count > 0) %}
|
||||
<div class="pwic_tagbox">
|
||||
{% for link in pwic.links %}
|
||||
<a href="/{{pwic.project|urlencode}}/{{link.page|urlencode}}">{{link.title|escape}}</a>
|
||||
{% endfor %}
|
||||
{% if not pwic.env.no_search %}
|
||||
<div class="pwic_searchbox pwic_js">
|
||||
{{pwic.emojis.search}}
|
||||
<input type="text" id="page_search" onkeypress="page_search()">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
{% if not pwic.env.no_search %}
|
||||
{% include 'js/search.js' %}
|
||||
{% endif %}
|
||||
|
||||
<article>
|
||||
{% if pwic.env.maintenance %}
|
||||
<div class="pwic_error">{{pwic.emojis.calendar}} {{pwic.env.maintenance.value|escape}}</div>
|
||||
{% endif %}
|
||||
{% if pwic.env.message %}
|
||||
<div class="pwic_information">{{pwic.emojis.pin}} {{pwic.env.message.value|escape}}</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="pwic_action_bar">
|
||||
{% if pwic.admin %}
|
||||
<a class="pwic_js" href="/{{pwic.project|urlencode}}/special/user">{{pwic.emojis.users}} {% trans %}New user{% endtrans %}</a>
|
||||
<a class="pwic_js" href="/{{pwic.project|urlencode}}/special/roles">{{pwic.emojis.key}} {% trans %}Roles{% endtrans %}</a>
|
||||
<a href="/{{pwic.project|urlencode}}/special/audit">{{pwic.emojis.glasses}} {% trans %}Audit{% endtrans %}</a>
|
||||
<a class="pwic_js" href="/{{pwic.project|urlencode}}/special/env">{{pwic.emojis.pill}} {% trans %}Settings{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% if pwic.manager %}
|
||||
<a class="pwic_js" href="/{{pwic.project|urlencode}}/special/page">{{pwic.emojis.sparkles}} {% trans %}New page{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% if not pwic.env.no_feed and (not pwic.pure_reader or not pwic.env.no_history) %}
|
||||
<a href="/{{pwic.project|urlencode}}/special/feed/atom">{{pwic.emojis.atom}} {% trans %}ATOM{% endtrans %}</a>
|
||||
<a href="/{{pwic.project|urlencode}}/special/feed/rss">{{pwic.emojis.rss}} {% trans %}RSS{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% if pwic.manager %}
|
||||
{% if not pwic.env.no_link_review %}
|
||||
<a href="/{{pwic.project|urlencode}}/special/links">{{pwic.emojis.chains}} {% trans %}Links{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% if not pwic.env.no_graph %}
|
||||
<a class="pwic_js" href="/{{pwic.project|urlencode}}/special/graph">{{pwic.emojis.globe}} {% trans %}Graph{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if pwic.admin and not pwic.env.no_export_project %}
|
||||
<a class="pwic_desktop" href="/{{pwic.project|urlencode}}/special/export/zip" title="{{ gettext('Export to format %(format)s')|format(format='ZIP') }}">{{pwic.emojis.clamp}} ZIP</a>
|
||||
{% endif %}
|
||||
<a class="pwic_js" href="/api">{{pwic.emojis.brick}} {% trans %}API{% endtrans %}</a>
|
||||
<a href="/{{pwic.project|urlencode}}/special/random">{{pwic.emojis.dice}} {% trans %}Random page{% endtrans %}</a>
|
||||
</div>
|
||||
|
||||
|
||||
{% if pwic.env.support_email or pwic.env.support_phone or pwic.env.support_url or pwic.env.support_text %}
|
||||
<h1>{% trans %}Internal support{% endtrans %}</h1>
|
||||
{% include 'html/block-support.html' %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if pwic.recents|count > 0 %}
|
||||
<h1 class="pwic_cursor" title="{% trans %}Expand/Collapse{% endtrans %}" onclick="$('#page_updates_list').toggleClass('pwic_hidden')">{% trans %}Recent updates{% endtrans %}</h1>
|
||||
<table id="page_updates_list">
|
||||
<tr>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Time{% endtrans %}</th>
|
||||
<th>{% trans %}Page{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Author{% endtrans %}</th>
|
||||
<th>{% trans %}Comment{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Milestone{% endtrans %}</th>
|
||||
</tr>
|
||||
|
||||
{% for recent in pwic.recents %}
|
||||
<tr>
|
||||
<td class="pwic_nowrap">{{recent.date|escape}}</td>
|
||||
<td class="pwic_desktop">{{recent.time|escape}}</td>
|
||||
<td><a href="/{{pwic.project|urlencode}}/{{recent.page|urlencode}}">{{recent.title|escape}}</a></td>
|
||||
<td class="pwic_desktop"><a class="pwic_break" href="/special/user/{{recent.author|urlencode}}" rel="nofollow">{{recent.author|escape}}</a></td>
|
||||
<td>{{recent.comment|escape}}</td>
|
||||
<td class="pwic_desktop">{{recent.milestone|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if pwic.admins|count + pwic.managers|count + pwic.editors|count + pwic.validators|count + pwic.readers|count > 0 %}
|
||||
<h1 class="pwic_cursor" title="{% trans %}Expand/Collapse{% endtrans %}" onclick="$('#page_members_list').toggleClass('pwic_hidden')">{% trans %}Team members{% endtrans %}</h1>
|
||||
<ul id="page_members_list">
|
||||
{% if pwic.admins|count > 0 %}
|
||||
<li><strong>{% trans %}Administrators:{% endtrans %}</strong>
|
||||
{% for admin in pwic.admins %}
|
||||
<a href="/special/user/{{admin|urlencode}}" rel="nofollow">{{admin|escape}}</a>
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if pwic.managers|count > 0 %}
|
||||
<li><strong>{% trans %}Managers:{% endtrans %}</strong>
|
||||
{% for manager in pwic.managers %}
|
||||
<a href="/special/user/{{manager|urlencode}}" rel="nofollow">{{manager|escape}}</a>
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if pwic.editors|count > 0 %}
|
||||
<li><strong>{% trans %}Editors:{% endtrans %}</strong>
|
||||
{% for editor in pwic.editors %}
|
||||
<a href="/special/user/{{editor|urlencode}}" rel="nofollow">{{editor|escape}}</a>
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if pwic.validators|count > 0 %}
|
||||
<li><strong>{% trans %}Validators:{% endtrans %}</strong>
|
||||
{% for validator in pwic.validators %}
|
||||
<a href="/special/user/{{validator|urlencode}}" rel="nofollow">{{validator|escape}}</a>
|
||||
{% endfor %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if pwic.readers|count > 0 %}
|
||||
<li><strong>{% trans %}Readers:{% endtrans %}</strong>
|
||||
{% if pwic.readers|count > 100 %}
|
||||
too many users.
|
||||
{% else %}
|
||||
{% for reader in pwic.readers %}
|
||||
<a href="/special/user/{{reader|urlencode}}" rel="nofollow">{{reader|escape}}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if (pwic.pages|count > 0) and (not pwic.user|reserved_user_name) %}
|
||||
<h1 class="pwic_cursor" title="{% trans %}Expand/Collapse{% endtrans %}" onclick="$('#page_pages_list').toggleClass('pwic_hidden')">{% trans %}All the pages of the project{% endtrans %}</h1>
|
||||
<table id="page_pages_list">
|
||||
<tr>
|
||||
<th>{% trans %}Page{% endtrans %}</th>
|
||||
<th>{% trans %}Title{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Revision{% endtrans %}</th>
|
||||
<th>{% trans %}Flags{% endtrans %}</th>
|
||||
<th>{% trans %}Author{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Date{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Time{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Milestone{% endtrans %}</th>
|
||||
</tr>
|
||||
{% for page in pwic.pages %}
|
||||
<tr>
|
||||
<td>{{page.page|escape}}</td>
|
||||
<td><a href="/{{pwic.project|urlencode}}/{{page.page|urlencode}}">{{page.title|escape}}</a></td>
|
||||
<td class="pwic_desktop">{{page.revision|escape}}</td>
|
||||
<td>
|
||||
{% if page.draft %}
|
||||
<span title="{% trans %}Draft{% endtrans %}">{{pwic.emojis.hourglass}}</span>
|
||||
{% endif %}
|
||||
{% if page.final %}
|
||||
<span title="{% trans %}Marked as final{% endtrans %}">{{pwic.emojis.notes}}</span>
|
||||
{% endif %}
|
||||
{% if page.valuser != '' %}
|
||||
<span title="{{ gettext('Validated by %(valuser)s on %(valdate)s at %(valtime)s.')|format(valuser=page.valuser|escape, valdate=page.valdate|escape, valtime=page.valtime|escape) }}">{{pwic.emojis.flag}}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a class="pwic_break" href="/special/user/{{page.author|urlencode}}" rel="nofollow">{{page.author|escape}}</a></td>
|
||||
<td class="pwic_desktop pwic_nowrap">{{page.date|escape}}</td>
|
||||
<td class="pwic_desktop">{{page.time|escape}}</td>
|
||||
<td class="pwic_desktop">{{page.milestone|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if (pwic.tags|count > 0) and (not pwic.user|reserved_user_name) %}
|
||||
<h1 class="pwic_js">{% trans %}Progress by tag{% endtrans %}</h1>
|
||||
<div id="page_progress_tags" class="pwic_tagbox pwic_js">
|
||||
<a href="#" title="{% trans %}Select all{% endtrans %}">{{pwic.emojis.check}}</a>
|
||||
<a href="#" title="{% trans %}Deselect all{% endtrans %}">{{pwic.emojis.red_check}}</a>
|
||||
<a class="pwic_spacer" href="#" title="{% trans %}Combined selection{% endtrans %}">{{pwic.emojis.paperclip}}</a>
|
||||
{% for tag in pwic.tags %}
|
||||
<a href="#" title="{% trans %}De/Select this tag{% endtrans %}">#{{tag|escape}}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<table id="page_progress_list" class="pwic_hidden">
|
||||
<tr>
|
||||
<th>{% trans %}Tag{% endtrans %}</th>
|
||||
<th>{% trans %}Draft{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{{pwic.emojis.updown}}</th>
|
||||
<th>{% trans %}Step{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{{pwic.emojis.updown}}</th>
|
||||
<th>{% trans %}Final{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{{pwic.emojis.updown}}</th>
|
||||
<th>{% trans %}Validated{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{{pwic.emojis.updown}}</th>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% include 'js/page-special-progress.js' %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if (pwic.documents|count > 0) and (not pwic.user|reserved_user_name) %}
|
||||
<h1 class="pwic_cursor" title="{% trans %}Expand/Collapse{% endtrans %}" onclick="$('#page_documents_space, #page_documents_list').toggleClass('pwic_hidden')">{% trans %}All the documents of the project{% endtrans %}</h1>
|
||||
<p id="page_documents_space" class="pwic_center"><strong>{% trans %}Disk space usage:{% endtrans %}</strong>
|
||||
{% if pwic.disk_space.project_max > 0 %}
|
||||
<span class="pwic_progressbar">
|
||||
<span style="width:{{pwic.disk_space.percentage|escape}}%"> </span>
|
||||
</span>
|
||||
<span class="pwic_nowrap">{{pwic.disk_space.used|size2str|escape}} / {{pwic.disk_space.project_max|size2str|escape}} ({{pwic.disk_space.percentage|escape}} %)</span>
|
||||
{% else %}
|
||||
{{pwic.disk_space.used|size2str|escape}}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
<table id="page_documents_list">
|
||||
<tr>
|
||||
<th class="pwic_desktop">{% trans %}Page{% endtrans %}</th>
|
||||
<th>{% trans %}File name{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Format{% endtrans %}</th>
|
||||
<th>{% trans %}Size{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Hash{% endtrans %}</th>
|
||||
<th>{% trans %}Author{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Date{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Time{% endtrans %}</th>
|
||||
<th><span class="pwic_desktop">{% trans %}Download{% endtrans %}</span></th>
|
||||
</tr>
|
||||
{% for doc in pwic.documents %}
|
||||
<tr>
|
||||
<td class="pwic_desktop"><a href="/{{doc.project|urlencode}}/{{doc.page|urlencode}}">{{doc.page|escape}}</a></td>
|
||||
<td>
|
||||
<a class="pwic_break" href="/special/document/{{doc.id|urlencode}}/{{doc.filename|urlencode}}">{{doc.filename|escape}}</a>
|
||||
{% if doc.exturl != ''%}
|
||||
<span title="{% trans %}External storage{% endtrans %}">{{pwic.emojis.cloud}}</span>
|
||||
{% endif%}
|
||||
</td>
|
||||
<td class="pwic_desktop" title="{{doc.mime|escape}}">{{doc.mime_icon}} {{doc.extension|upper}}</td>
|
||||
<td data-sort="{{doc.size|escape}}">{{doc.size|size2str|escape}}</td>
|
||||
<td class="pwic_desktop">
|
||||
<span title="{{doc.hash|escape}}">{{doc.hash[:8]|escape}}</span>
|
||||
{% if doc.occurrence > 1 %}
|
||||
<span title="{% trans %}Duplicate file{% endtrans %}">{{pwic.emojis.gemini}}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a class="pwic_break" href="/special/user/{{doc.author|urlencode}}" rel="nofollow">{{doc.author|escape}}</a></td>
|
||||
<td class="pwic_desktop pwic_nowrap">{{doc.date|escape}}</td>
|
||||
<td class="pwic_desktop">{{doc.time|escape}}</td>
|
||||
<td><a href="/special/document/{{doc.id|urlencode}}?attachment">{{pwic.emojis.inbox}}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>API specification for Pwic.wiki</title>
|
||||
<link rel="stylesheet" type="text/css" href="/static/api/swagger-ui.css" >
|
||||
<style>
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="/static/api/swagger-ui-bundle.js"></script>
|
||||
<script src="/static/api/swagger-ui-standalone-preset.js"></script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
const ui = SwaggerUIBundle({
|
||||
url: '/static/api/swagger.txt',
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: 'StandaloneLayout'
|
||||
});
|
||||
window.ui = ui;
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,192 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block header_scripts %}
|
||||
{% if pwic.env.mathjax %}
|
||||
<script>
|
||||
window.MathJax = {
|
||||
tex: { inlineMath: [['$', '$'], ['\\(', '\\)']] },
|
||||
svg: { fontCache: 'global' }
|
||||
};
|
||||
</script>
|
||||
<script src="/static/mathjax.min.js" async></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{% if pwic.page != pwic.constants['default_home'] %}{{pwic.project|urlencode}}{% endif %}">{{pwic.project_description|escape}}</a></div>
|
||||
{% if (not pwic.env.no_search) or (pwic.links|count > 0) %}
|
||||
<div class="pwic_tagbox">
|
||||
{% for link in pwic.links %}
|
||||
<a href="/{{pwic.project|urlencode}}/{{link.page|urlencode}}">{{link.title|escape}}</a>
|
||||
{% endfor %}
|
||||
{% if not pwic.env.no_search %}
|
||||
<div class="pwic_searchbox pwic_js">
|
||||
{{pwic.emojis.search}}
|
||||
<input type="text" id="page_search" onkeypress="page_search()">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div id="pwic_progress"></div>
|
||||
|
||||
{% if pwic.env.maintenance %}
|
||||
<div class="pwic_error">{{pwic.emojis.calendar}} {{pwic.env.maintenance.value|escape|replace('\\n','<br>')}}</div>
|
||||
{% endif %}
|
||||
{% if pwic.env.message %}
|
||||
<div class="pwic_information">{{pwic.emojis.pin}} {{pwic.env.message.value|escape|replace('\\n','<br>')}}</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="pwic_action_bar">
|
||||
{% if pwic.protection %}
|
||||
<span title="{% trans %}The page is protected{% endtrans %}">{{pwic.emojis.padlock}}</span>
|
||||
{% endif %}
|
||||
<a href="/{{pwic.project|urlencode}}/special">{{pwic.emojis.star}} {% trans %}Special{% endtrans %}</a>
|
||||
{% if pwic.manager %}
|
||||
<a class="pwic_js" href="/{{pwic.project|urlencode}}/special/page">{{pwic.emojis.sparkles}} {% trans %}New page{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% if pwic.latest and (pwic.manager or (pwic.editor and not pwic.protection)) %}
|
||||
<a class="pwic_js" href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}/edit">{{pwic.emojis.set_square}} {% trans %}Edit{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% if not pwic.pure_reader or not pwic.env.no_history %}
|
||||
<a href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}/history">{{pwic.emojis.clock}} {% trans %}History{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% if pwic.manager %}
|
||||
<a class="pwic_js" href="/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}/move">{{pwic.emojis.truck}} {% trans %}Move{% endtrans %}</a>
|
||||
{% endif %}
|
||||
|
||||
<a class="pwic_js" href="#" onclick="return page_email()">{{pwic.emojis.outbox}} {% trans %}Email{% endtrans %}</a>
|
||||
{% if not pwic.env.no_printing %}
|
||||
<a class="pwic_desktop pwic_js" href="#" onclick="return page_print()">{{pwic.emojis.printer}} {% trans %}Print{% endtrans %}</a>
|
||||
{% endif %}
|
||||
|
||||
{% set no_formats = pwic.env.get('file_formats_disabled', {'value': ''}).value.split(' ') %}
|
||||
{% if '*' not in no_formats %}
|
||||
{% for f in pwic.file_formats %}
|
||||
{% if f not in no_formats %}
|
||||
<a class="pwic_js" href="#" title="{% trans %}Export to{% endtrans %} {{f|escape|upper}}" onclick="return page_export('{{f|escape}}')">{{pwic.emojis.save}} {{f|escape|upper}}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.validator and (pwic.valuser == '') and pwic.final %}
|
||||
<a class="pwic_js" href="#" onclick="return page_post_action('validate', {% trans %}'The validation cannot be undone.\n\nDo you want to continue?'{% endtrans %})">{{pwic.emojis.validate}} {% trans %}Validate{% endtrans %}</a>
|
||||
{% endif %}
|
||||
{% if pwic.removable %}
|
||||
<a class="pwic_js" href="#" onclick="return page_post_action('delete', {% trans %}'Warning: deleting the revision cannot be undone.\n\nDo you want to continue?'{% endtrans %})">{{pwic.emojis.trashcan}} {% trans %}Delete{% endtrans %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if not pwic.latest %}
|
||||
<p class="pwic_warning">{{pwic.emojis.eye}}
|
||||
{% if pwic.env.validated_only %}
|
||||
{{ gettext('You are viewing the <span class="pwic_bold">revision %(revision)d</span> and <a href="/%(project)s/%(page)s/history">other revisions</a> are pending.')|format(revision=pwic.revision, project=pwic.project|urlencode, page=pwic.page|urlencode) }}
|
||||
{% else %}
|
||||
{{ gettext('You are viewing the <span class="pwic_bold">revision %(revision)d</span>, but the <a href="/%(project)s/%(page)s">latest version</a> is available.')|format(revision=pwic.revision, project=pwic.project|urlencode, page=pwic.page|urlencode) }}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.valuser != '' %}
|
||||
<p class="pwic_information">{{pwic.emojis.flag}} {{ gettext('This page has been validated by <a href="/special/user/%(user1)s" rel="nofollow">%(user2)s</a> on %(sdate)s at %(stime)s.')|format(user1=pwic.valuser|urlencode, user2=pwic.valuser|escape, sdate=pwic.valdate|escape, stime=pwic.valtime|escape) }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.tmap|count + pwic.documents|count > 1 %}
|
||||
<div id="pwic_browser_access" class="pwic_js" title="{% trans %}Show/Hide the map of the page{% endtrans %}" onclick="page_tmap()">
|
||||
{{pwic.emojis.pin}}
|
||||
</div>
|
||||
<div id="pwic_browser" class="pwic_hidden">
|
||||
{% for tmap in pwic.tmap %}
|
||||
<a class="pwic_browser_item pwic_browser_item_h{{tmap.level}}" href="#{{tmap.tag|urlencode}}" onclick="page_tmap()">{% if not pwic.env.no_heading %}<span class="pwic_bold">{{tmap.header|escape}}</span> {% endif %}{{tmap.title|no_html|escape}}</a>
|
||||
{% endfor %}
|
||||
|
||||
{% if not pwic.env.no_document_list and (pwic.documents|count + pwic.images|count > 0) %}
|
||||
<a class="pwic_browser_item pwic_browser_item_h1" href="#page_documents" onclick="page_tmap()">{{pwic.emojis.scroll}} {% trans %}Attached documents{% endtrans %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.relations|count > 0 %}
|
||||
<p id="pwic_relations">
|
||||
<span class="pwic_bold">{% trans %}Related pages:{% endtrans %}</span>
|
||||
{% for p in pwic.relations %}
|
||||
{% if loop.index > 1 %} – {% endif %}
|
||||
<a href="{{p[0]|escape}}">{{p[1]|escape}}</a>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.tags|count > 0 %}
|
||||
<div class="pwic_tagbox">
|
||||
{% for tag in pwic.tags %}
|
||||
{% if pwic.env.no_search %}
|
||||
<a href="#" onclick="return false">#{{tag|escape}}</a>
|
||||
{% else %}
|
||||
<a href="/{{pwic.project|urlencode}}/special/search?q=%23{{tag|urlencode}}" title="{% trans %}Search for related classified pages{% endtrans %}">#{{tag|escape}}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{pwic.html}}
|
||||
|
||||
{% if not pwic.env.no_document_list and (pwic.documents|count + pwic.images|count > 0) %}
|
||||
<h1 id="page_documents" class="pwic_cursor" title="{% trans %}Expand/Collapse{% endtrans %}" onclick="$('#page_section_files').toggleClass('pwic_hidden')">{% trans %}Attached documents{% endtrans %}</h1>
|
||||
|
||||
<div id="page_section_files">
|
||||
{% if pwic.documents|count > 0 %}
|
||||
<div class="pwic_file_gallery">
|
||||
{% if pwic.documents|count + pwic.images|count > 1 %}
|
||||
<a href="/{{pwic.project|urlencode}}/special/documents/{{pwic.page|urlencode}}" rel="nofollow">
|
||||
<span>{% trans %}Download all{% endtrans %}</span>
|
||||
<br>{{pwic.emojis.inbox}}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% for doc in pwic.documents %}
|
||||
<a href="/special/document/{{doc.id|urlencode}}/{{doc.filename|urlencode}}" title="{{ gettext('Uploaded by %(author)s on %(date)s at %(time)s.')|format(author=doc.author|escape, date=doc.date|escape, time=doc.time|escape) }}">
|
||||
<span>{{doc.filename|escape}}</span>
|
||||
<br><small>{{doc.mime|escape}}</small> ({{doc.size|size2str|escape}})
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.images|count > 0 %}
|
||||
<div class="pwic_file_gallery">
|
||||
{% if (pwic.documents|count == 0) and (pwic.images|count > 1) %}
|
||||
<a href="/{{pwic.project|urlencode}}/special/documents/{{pwic.page|urlencode}}" rel="nofollow">
|
||||
<span>{% trans %}Download all{% endtrans %}</span>
|
||||
<br>{{pwic.emojis.inbox}}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% for doc in pwic.images %}
|
||||
<a href="/special/document/{{doc.id|urlencode}}/{{doc.filename|urlencode}}" title="{{ gettext('Uploaded by %(author)s on %(date)s at %(time)s.')|format(author=doc.author|escape, date=doc.date|escape, time=doc.time|escape) }}">
|
||||
<span>{{doc.filename|escape}}</span>
|
||||
<br><small>{{doc.mime|escape}}</small> ({{doc.size|size2str|escape}})
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<p id="page_lastmod">
|
||||
{{ gettext('Revision <span class="pwic_bold">#%(revision)d</span> was last modified by <a href="/special/user/%(author1)s" rel="nofollow">%(author2)s</a><br>on %(date)s at %(time)s — <span title="Hash: %(hash)s">%(shash)s</span>')|format(revision=pwic.revision, author1=pwic.author|urlencode, author2=pwic.author|escape, date=pwic.date|escape, time=pwic.time|escape, hash=pwic.hash|escape, shash=pwic.hash[:16]|escape) }}
|
||||
</p>
|
||||
|
||||
{% if pwic.env.legal_notice %}
|
||||
<div id="page_legal_notice">{{pwic.env.legal_notice.value|escape|replace('\n','<br>')}}</div>
|
||||
{% endif %}
|
||||
</article>
|
||||
|
||||
<!-- Scripts -->
|
||||
{% include 'js/page.js' %}
|
||||
{% if not pwic.env.no_search %}
|
||||
{% include 'js/search.js' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,22 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}No access{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/">{{pwic.emojis.finger_up}} [{{pwic.project|escape}}] {% trans %}Access denied{% endtrans %}</a></div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<p class="pwic_error">{{pwic.emojis.red_check}} {% trans %}You don't have the authorizations to access this project.{% endtrans %}</p>
|
||||
|
||||
{% if pwic.env.support_email or pwic.env.support_phone or pwic.env.support_url or pwic.env.support_text %}
|
||||
<p>{% trans %}To request your access, get in touch with the support team:{% endtrans %}</p>
|
||||
{% include 'html/block-support.html' %}
|
||||
{% else %}
|
||||
<p>{% trans %}Unfortunately, there is no defined support information to request your access.{% endtrans %}</p>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,62 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Select your project{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1">{{pwic.emojis.home}} {% trans %}Select your project{% endtrans %}</div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="pwic_action_bar">
|
||||
<a class="pwic_js" href="/api">{{pwic.emojis.brick}} {% trans %}API{% endtrans %}</a>
|
||||
{% if not pwic.env.no_help %}
|
||||
<a href="/special/help">{{pwic.emojis.help}} {% trans %}Help{% endtrans %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if (pwic.projects|count + pwic.joinable_projects|count) == 0 %}
|
||||
<p>{% trans %}Unfortunately, you have access to no project at all.{% endtrans %}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.projects|count > 0 %}
|
||||
<h1 class="pwic_cursor" title="{% trans %}Expand/Collapse{% endtrans %}" onclick="$('#projects_1').toggleClass('pwic_hidden')">{% trans %}Joined projects{% endtrans %}</h1>
|
||||
<table id="projects_1">
|
||||
<tr>
|
||||
<th>{% trans %}Project{% endtrans %}</th>
|
||||
<th>{% trans %}Description{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Last activity{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Creation date{% endtrans %}</th>
|
||||
</tr>
|
||||
{% for p in pwic.projects %}
|
||||
<tr>
|
||||
<td>{{p.project|escape}}</td>
|
||||
<td><a href="/{{p.project|urlencode}}">{{p.description|escape}}</a></td>
|
||||
<td class="pwic_desktop">{{(p.last_activity or '-')|escape}}</td>
|
||||
<td class="pwic_desktop">{{p.date|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.joinable_projects|count > 0 %}
|
||||
<h1 class="pwic_cursor" title="{% trans %}Expand/Collapse{% endtrans %}" onclick="$('#projects_2').toggleClass('pwic_hidden')">{% trans %}Available public projects{% endtrans %}</h1>
|
||||
<table id="projects_2">
|
||||
<tr>
|
||||
<th>{% trans %}Project{% endtrans %}</th>
|
||||
<th>{% trans %}Description{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Date{% endtrans %}</th>
|
||||
</tr>
|
||||
{% for p in pwic.joinable_projects %}
|
||||
<tr>
|
||||
<td>{{p.project|escape}}</td>
|
||||
<td><a href="/{{p.project|urlencode}}">{{p.description|escape}}</a></td>
|
||||
<td class="pwic_desktop">{{p.date|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,100 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Search{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}">{{pwic.emojis.finger_left}} {{pwic.project_description|escape}}</a></div>
|
||||
</header>
|
||||
|
||||
{% include 'js/search.js' %}
|
||||
|
||||
<article>
|
||||
<h1>{{pwic.pages|count + pwic.documents|count}} {% trans %}results{% endtrans %}</h1>
|
||||
|
||||
<p>{% trans %}Search terms:{% endtrans %}
|
||||
<input id="page_search" class="pwic_fill" type="text" value="{{pwic.terms|escape}}" onkeypress="page_search()">
|
||||
{% if not pwic.pure_reader or not pwic.env.no_history %}
|
||||
<span class="pwic_js">
|
||||
<input id="page_search_withrev" type="checkbox" {% if 'rev' in pwic.args %}checked="checked"{% endif %} onclick="page_start_search()">
|
||||
<label for="page_search_withrev">{% trans %}Include the old revisions{% endtrans %}</label>,
|
||||
</div>
|
||||
{% endif %}
|
||||
<span class="pwic_js">
|
||||
<input id="page_search_casesensitive" type="checkbox" {% if 'cs' in pwic.args %}checked="checked"{% endif %} onclick="page_start_search()">
|
||||
<label for="page_search_casesensitive">{% trans %}Case-sensitive{% endtrans %}</label>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
{% if pwic.pages|count > 0 %}
|
||||
<h2>{% trans %}Pages{% endtrans %}</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{% trans %}Page{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Revision{% endtrans %}</th>
|
||||
<th>{% trans %}Title{% endtrans %}</th>
|
||||
<th>{% trans %}Flags{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Author{% endtrans %}</th>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Time{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Score{% endtrans %}</th>
|
||||
</tr>
|
||||
|
||||
{% for page in pwic.pages %}
|
||||
<tr>
|
||||
<td>{{page.page|escape}}</td>
|
||||
<td class="pwic_desktop">{{page.revision|escape}}</td>
|
||||
<td><a href="/{{page.project|urlencode}}/{{page.page|urlencode}}{% if not page.latest %}/rev{{page.revision|urlencode}}{% endif %}">{{page.title|escape}}</a></td>
|
||||
<td>
|
||||
{% if pwic.with_rev and page.latest %}
|
||||
<span title="{% trans %}Latest{% endtrans %}">{{pwic.emojis.watch}}</span>
|
||||
{% endif %}
|
||||
{% if page.draft %}
|
||||
<span title="{% trans %}Draft{% endtrans %}">{{pwic.emojis.hourglass}}</span>
|
||||
{% endif %}
|
||||
{% if page.final %}
|
||||
<span title="{% trans %}Marked as final{% endtrans %}">{{pwic.emojis.notes}}</span>
|
||||
{% endif %}
|
||||
{% if page.valuser != '' %}
|
||||
<span title="{{ gettext('Validated by %(valuser)s on %(valdate)s at %(valtime)s.')|format(valuser=page.valuser|escape, valdate=page.valdate|escape, valtime=page.valtime|escape) }}">{{pwic.emojis.flag}}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="pwic_desktop"><a class="pwic_break" href="/special/user/{{page.author|urlencode}}" rel="nofollow">{{page.author|escape}}</a></td>
|
||||
<td>{{page.date|escape}}</td>
|
||||
<td class="pwic_desktop">{{page.time|escape}}</td>
|
||||
<td class="pwic_desktop">{{page.score|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.documents|count > 0 %}
|
||||
<h2>{% trans %}Documents{% endtrans %}</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{% trans %}Page{% endtrans %}</th>
|
||||
<th>{% trans %}File name{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Format{% endtrans %}</th>
|
||||
<th>{% trans %}Size{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Author{% endtrans %}</th>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
<!-- <th class="pwic_desktop">{% trans %}Time{% endtrans %}</th> -->
|
||||
</tr>
|
||||
|
||||
{% for doc in pwic.documents %}
|
||||
<tr>
|
||||
<td><a href="/{{pwic.project|urlencode}}/{{doc.page|urlencode}}">{{doc.page|escape}}</a></td>
|
||||
<td><a href="/special/document/{{doc.id|urlencode}}/{{doc.filename|escape}}">{{doc.filename|escape}}</a></td>
|
||||
<td class="pwic_desktop" title="{{doc.mime|escape}}">{{doc.mime_icon}} {{doc.extension|upper}}</td>
|
||||
<td>{{doc.size|size2str|escape}}</td>
|
||||
<td class="pwic_desktop"><a class="pwic_break" href="/special/user/{{doc.author|urlencode}}" rel="nofollow">{{doc.author|escape}}</a></td>
|
||||
<td>{{doc.date|escape}}</td>
|
||||
<!-- <td class="pwic_desktop">{{doc.time|escape}}</td> -->
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,36 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Create a new user{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/">{{pwic.emojis.finger_left}} {% if pwic.env.no_new_user %}{% trans %}Assign a new user{% endtrans %}{% else %}{% trans %}Create a new user{% endtrans %}{% endif %}</a></div>
|
||||
</header>
|
||||
|
||||
{% include 'js/user-create.js' %}
|
||||
|
||||
<article>
|
||||
{% if pwic.projects|count == 0 %}
|
||||
|
||||
<p class="pwic_error">{{pwic.emojis.padlock}} {% trans %}You have no authorization to create a new user. Please contact your administrator.{% endtrans %}</p>
|
||||
|
||||
{% else %}
|
||||
|
||||
<p class="pwic_italic">{% trans %}Reminder: your password must be changed before you can add a new user to the selected project.{% endtrans %}</p>
|
||||
<p><strong>{% trans %}Project:{% endtrans %}</strong><br>
|
||||
<select id="create_project" name="project">
|
||||
{% for proj in pwic.projects %}
|
||||
<option value="{{proj.project|escape}}"
|
||||
{% if proj.project == pwic.default_project %} selected="selected" {% endif %}
|
||||
>{{proj.description|escape}} [{{proj.project|escape}}]</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<p><strong>{% trans %}User name:{% endtrans %}</strong> <input id="create_user" class="pwic_fill" type="text" name="user" autofocus required="true" spellcheck="false"></p>
|
||||
<p><input type="button" value="{{pwic.emojis.users}} {% trans %}Create the user{% endtrans %}" onclick="create_submit()"></p>
|
||||
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,140 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}Roles of the users{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/{{pwic.project|urlencode}}/special">{{pwic.emojis.finger_left}} {% trans %}Roles of the users{% endtrans %}</a></div>
|
||||
<div class="pwic_ph2">[{{pwic.project|escape}}] {{pwic.project_description|escape}}</div>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="pwic_action_bar">
|
||||
<a href="/{{pwic.project|urlencode}}/special/audit">{{pwic.emojis.glasses}} {% trans %}Audit{% endtrans %}</a>
|
||||
<a href="/{{pwic.project|urlencode}}/special/user">{{pwic.emojis.users}} {% trans %}Create a user{% endtrans %}</a>
|
||||
</div>
|
||||
|
||||
<p class="pwic_italic">{% trans %}Reminder: the password of a user must be changed before his roles can be changed.{% endtrans %}</p>
|
||||
|
||||
<table id="roles_table" class="pwic_zebra">
|
||||
<tr>
|
||||
<th>{% trans %}User{% endtrans %}</th>
|
||||
<th class="pwic_desktop" title="{% trans %}Password{% endtrans %}">{% trans %}Pwd{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Activity{% endtrans %}</th>
|
||||
<th>{% trans %}A<span class="pwic_desktop">dmin</span>{% endtrans %}</th>
|
||||
<th>{% trans %}M<span class="pwic_desktop">anager</span>{% endtrans %}</th>
|
||||
<th>{% trans %}E<span class="pwic_desktop">ditor</span>{% endtrans %}</th>
|
||||
<th>{% trans %}V<span class="pwic_desktop">alidator</span>{% endtrans %}</th>
|
||||
<th>{% trans %}R<span class="pwic_desktop">eader</span>{% endtrans %}</th>
|
||||
<th>{% trans %}Dis<span class="pwic_desktop">abled</span>{% endtrans %}</th>
|
||||
<th>{% trans %}Del<span class="pwic_desktop">ete</span>{% endtrans %}</th>
|
||||
</tr>
|
||||
|
||||
{% set u = namespace(value=0) %}
|
||||
{% for role in pwic.roles %}
|
||||
<tr id="roles_tag_{{u.value+7}}">
|
||||
<td><a class="pwic_break" href="/special/user/{{role.user|urlencode}}" rel="nofollow">{{role.user|escape}}</a></td>
|
||||
<td class="pwic_desktop">
|
||||
{% if role.user|reserved_user_name %}
|
||||
<span title="{% trans %}Special account{% endtrans %}">{{pwic.emojis.star}}</span>
|
||||
{% elif role.oauth %}
|
||||
<span title="{% trans %}Federated authentication{% endtrans %}">{{pwic.emojis.id}}</span>
|
||||
{% elif role.initial %}
|
||||
<span title="{% trans %}The user must change his password{% endtrans %}">{{pwic.emojis.unlocked}}</span>
|
||||
{% else %}
|
||||
{{pwic.emojis.green_check}}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="pwic_desktop">{{role.activity|escape}}</td>
|
||||
<td>
|
||||
<input id="roles_tag_{{u.value+1}}"
|
||||
type="checkbox"
|
||||
{% if (role.user == pwic.user) or role.user|reserved_user_name or role.initial %}
|
||||
disabled="disabled"
|
||||
{% else %}
|
||||
onclick="return roles_toggle({{u.value+1}}, '{{pwic.project|escape}}', '{{role.user|escape}}', 'admin')"
|
||||
{% endif %}
|
||||
{% if role.admin %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
<input id="roles_tag_{{u.value+2}}"
|
||||
type="checkbox"
|
||||
onclick="return roles_toggle({{u.value+2}}, '{{pwic.project|escape}}', '{{role.user|escape}}', 'manager')"
|
||||
{% if role.initial %}
|
||||
disabled="disabled"
|
||||
{% endif %}
|
||||
{% if role.manager %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
<input id="roles_tag_{{u.value+3}}"
|
||||
type="checkbox"
|
||||
onclick="return roles_toggle({{u.value+3}}, '{{pwic.project|escape}}', '{{role.user|escape}}', 'editor')"
|
||||
{% if role.initial %}
|
||||
disabled="disabled"
|
||||
{% endif %}
|
||||
{% if role.editor %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
<input id="roles_tag_{{u.value+4}}"
|
||||
type="checkbox"
|
||||
onclick="return roles_toggle({{u.value+4}}, '{{pwic.project|escape}}', '{{role.user|escape}}', 'validator')"
|
||||
{% if role.initial %}
|
||||
disabled="disabled"
|
||||
{% endif %}
|
||||
{% if role.validator %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
<input id="roles_tag_{{u.value+5}}"
|
||||
type="checkbox"
|
||||
onclick="return roles_toggle({{u.value+5}}, '{{pwic.project|escape}}', '{{role.user|escape}}', 'reader')"
|
||||
{% if role.initial %}
|
||||
disabled="disabled"
|
||||
{% endif %}
|
||||
{% if role.reader %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
<input id="roles_tag_{{u.value+6}}" type="checkbox"
|
||||
{% if (role.user == pwic.user) or role.initial %}
|
||||
disabled="disabled"
|
||||
{% else %}
|
||||
onclick="return roles_toggle({{u.value+6}}, '{{pwic.project|escape}}', '{{role.user|escape}}', 'disabled')"
|
||||
{% endif %}
|
||||
{% if role.disabled %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
{% if (role.user != pwic.user) and (not role.user|reserved_user_name) %}
|
||||
<input type="button"
|
||||
onclick="return roles_delete('Are you sure to delete the rights of the user \'{{role.user|escape}}\' for the project?', {{u.value+7}}, '{{pwic.project|escape}}', '{{role.user|escape}}')"
|
||||
value="{{pwic.emojis.red_check}}"
|
||||
title="{% trans %}Delete{% endtrans %} {{role.user|escape}}"
|
||||
>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% set u.value = u.value + 7 %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
</article>
|
||||
|
||||
{% include 'js/user-roles.js' %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,150 @@
|
||||
{% extends 'html/main.html' %}
|
||||
|
||||
|
||||
{% block title %}{% trans %}User profile{% endtrans %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<header>
|
||||
<div class="pwic_ph1"><a href="/">{{pwic.emojis.finger_up}} {% trans %}User profile{% endtrans %}</a></div>
|
||||
</header>
|
||||
|
||||
{% include 'js/user.js' %}
|
||||
|
||||
<article>
|
||||
<h1>{{pwic.userpage|escape}}</h1>
|
||||
|
||||
<h2>{% trans %}Profile{% endtrans %}</h2>
|
||||
<ul>
|
||||
<li>{% trans %}Own password:{% endtrans %}
|
||||
<span id="user_password_status">{{pwic.emojis.red_check if pwic.password_initial else pwic.emojis.green_check}}</span>
|
||||
{% if pwic.password_totp %}
|
||||
<span title="{% trans %}Enabled two-factor authentication (2FA){% endtrans %}">{{pwic.emojis.slot}}</span>
|
||||
{% endif %}
|
||||
{% if pwic.password_oauth %}
|
||||
<span title="{% trans %}Federated authentication only{% endtrans %}">{{pwic.emojis.id}}</span>
|
||||
{% elif (pwic.user == pwic.userpage) and (not pwic.userpage|reserved_user_name) %}
|
||||
<span class="pwic_js">(<a href="#" onclick="return user_password_popup()">{% trans %}change it{% endtrans %}</a>)</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% if pwic.user == pwic.userpage %}
|
||||
<li>{% trans %}Language:{% endtrans %}
|
||||
<select id="user_language" onchange="user_language_set()">
|
||||
{% for lang in pwic.constants.languages %}
|
||||
<option value="{{lang|escape}}" {% if lang == pwic.language %} selected="selected" {% endif %}>{{lang|escape}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if pwic.projects|count > 0 %}
|
||||
<li>{% trans %}Projects:{% endtrans %}
|
||||
<ul>
|
||||
{% for project in pwic.projects %}
|
||||
<li><a href="/{{project.project|urlencode}}">{{project.description|escape}}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{% if (not pwic.password_oauth) and (pwic.user == pwic.userpage) and (not pwic.userpage|reserved_user_name) %}
|
||||
<div id="user_password_popup" class="pwic_blurcontainer pwic_hidden">
|
||||
<div class="pwic_popup">
|
||||
<form autocomplete="new-password">
|
||||
<p class="pwic_bold">{% trans %}Change your password{% endtrans %}</p>
|
||||
<p id="user_password_notice" class="pwic_italic">{{pwic.emojis.warning}} {% trans %}Warning: the site does not use a secure protocol. Please choose a dedicated password that you use nowhere else.{% endtrans %}</p>
|
||||
<table class="pwic_noborder">
|
||||
<tr><td>{% trans %}Current password:{% endtrans %}</td> <td><input class="pwic_fill" type="password" id="user_password_current" autocomplete="current-password" required="true"></td></tr>
|
||||
<tr><td>{% trans %}New password:{% endtrans %}</td> <td><input class="pwic_fill" type="password" id="user_password_new1" autocomplete="new-password" required="true"></td></tr>
|
||||
<tr><td>{% trans %}Repeat password:{% endtrans %}</td> <td><input class="pwic_fill" type="password" id="user_password_new2" autocomplete="off" required="true" onpaste="return false"></td></tr>
|
||||
</table>
|
||||
<p>
|
||||
<input type="button" value="{{pwic.emojis.locked}} {% trans %}Change{% endtrans %}" onclick="user_password_submit()">
|
||||
<input type="button" value="{% trans %}Cancel{% endtrans %}" onclick="user_password_popup()">
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<h2>{% trans %}Contributions in the last 90 days{% endtrans %}</h2>
|
||||
{% if pwic.pages|count == 0 %}
|
||||
<p class="pwic_center pwic_italic">{% trans %}The user has no recent contribution.{% endtrans %}</p>
|
||||
{% else%}
|
||||
<table>
|
||||
<tr>
|
||||
<th class="pwic_desktop">{% trans %}Project{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Page{% endtrans %}</th>
|
||||
<th>{% trans %}Title{% endtrans %}</th>
|
||||
<th>{% trans %}Flags{% endtrans %}</th>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Time{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Milestone{% endtrans %}</th>
|
||||
</tr>
|
||||
|
||||
{% for page in pwic.pages %}
|
||||
<tr>
|
||||
<td class="pwic_desktop pwic_break">{{page.project|escape}}</td>
|
||||
<td class="pwic_desktop pwic_break">{{page.page|escape}}</td>
|
||||
<td><a href="/{{page.project|urlencode}}/{{page.page|urlencode}}">{{page.title|escape}}</a></td>
|
||||
<td>
|
||||
{% if page.draft %}
|
||||
<span title="{% trans %}Draft{% endtrans %}">{{pwic.emojis.hourglass}}</span>
|
||||
{% endif %}
|
||||
{% if page.final %}
|
||||
<span title="{% trans %}Marked as final{% endtrans %}">{{pwic.emojis.notes}}</span>
|
||||
{% endif %}
|
||||
{% if page.valuser != '' %}
|
||||
<span title="{{ gettext('Validated by %(valuser)s on %(valdate)s at %(valtime)s.')|format(valuser=page.valuser|escape, valdate=page.valdate|escape, valtime=page.valtime|escape) }}">{{pwic.emojis.flag}}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{page.date|escape}}</td>
|
||||
<td class="pwic_desktop">{{page.time|escape}}</td>
|
||||
<td class="pwic_desktop">{{page.milestone|escape}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if (pwic.documents|count > 0) and (not pwic.user|reserved_user_name) %}
|
||||
<h2>{% trans %}Uploaded documents{% endtrans %}</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th class="pwic_desktop">{% trans %}Project{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Page{% endtrans %}</th>
|
||||
<th>{% trans %}File name{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Format{% endtrans %}</th>
|
||||
<th>{% trans %}Size{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Hash{% endtrans %}</th>
|
||||
<th>{% trans %}Date{% endtrans %}</th>
|
||||
<th class="pwic_desktop">{% trans %}Time{% endtrans %}</th>
|
||||
<th><span class="pwic_desktop">{% trans %}Download{% endtrans %}</span></th>
|
||||
</tr>
|
||||
|
||||
{% for doc in pwic.documents %}
|
||||
<tr>
|
||||
<td class="pwic_desktop pwic_break">{{doc.project|escape}}</td>
|
||||
<td class="pwic_desktop pwic_break"><a href="/{{doc.project|urlencode}}/{{doc.page|urlencode}}">{{doc.page|escape}}</a></td>
|
||||
<td>
|
||||
<a class="pwic_break" href="/special/document/{{doc.id|urlencode}}/{{doc.filename|urlencode}}">{{doc.filename|escape}}</a>
|
||||
{% if doc.exturl != ''%}
|
||||
<span title="{% trans %}External storage{% endtrans %}">{{pwic.emojis.cloud}}</span>
|
||||
{% endif%}
|
||||
</td>
|
||||
<td class="pwic_desktop" title="{{doc.mime|escape}}">{{doc.mime_icon}} {{doc.extension|upper}}</td>
|
||||
<td data-sort="{{doc.size|escape}}">{{doc.size|size2str|escape}}</td>
|
||||
<td class="pwic_desktop">
|
||||
<span title="{{doc.hash|escape}}">{{doc.hash[:8]|escape}}</span>
|
||||
{% if doc.occurrence > 1 %} <span title="{% trans %}Duplicate file{% endtrans %}">{{pwic.emojis.gemini}}</span> {% endif %}
|
||||
</td>
|
||||
<td>{{doc.date|escape}}</td>
|
||||
<td class="pwic_desktop">{{doc.time|escape}}</td>
|
||||
<td><a href="/special/document/{{doc.id|urlencode}}?attachment">{{pwic.emojis.inbox}}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,71 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function login_translate_langs(mapping) {
|
||||
$('#login_language OPTION').each((i, e) => {
|
||||
var lang = $(e).attr('value');
|
||||
if (mapping.hasOwnProperty(lang))
|
||||
$(e).html(lang + ' - ' + mapping[lang]);
|
||||
});
|
||||
}
|
||||
|
||||
function login_anonymous() {
|
||||
$('#login_user').val('{{pwic.constants.anonymous_user|escape}}');
|
||||
$('#login_password').val('');
|
||||
$('#login_pin').val('');
|
||||
$('#login_form')[0].submit();
|
||||
return true;
|
||||
}
|
||||
|
||||
{% if pwic.env.base_url and pwic.env.oauth_provider %}
|
||||
function login_oauth() {
|
||||
{% if pwic.env.oauth_provider.value == 'github' %}
|
||||
var args = {client_id: '{{pwic.env.oauth_identifier.value|escape}}',
|
||||
redirect_uri: '{{pwic.env.base_url.value|escape}}/api/oauth',
|
||||
login: $('#login_user').val(),
|
||||
scope: 'user:email',
|
||||
state: '{{pwic.oauth_user_secret|escape}}',
|
||||
allow_signup: false};
|
||||
window.location = 'https://github.com/login/oauth/authorize?' + (new URLSearchParams(args).toString());
|
||||
|
||||
{% elif pwic.env.oauth_provider.value == 'google' %}
|
||||
var args = {client_id: '{{pwic.env.oauth_identifier.value|escape}}',
|
||||
redirect_uri: '{{pwic.env.base_url.value|escape}}/api/oauth',
|
||||
scope: 'https://www.googleapis.com/auth/userinfo.email',
|
||||
access_type: 'online',
|
||||
state: '{{pwic.oauth_user_secret|escape}}',
|
||||
login_hint: $('#login_user').val(),
|
||||
response_type: 'code'};
|
||||
window.location = 'https://accounts.google.com/o/oauth2/v2/auth?' + (new URLSearchParams(args).toString());
|
||||
|
||||
{% elif pwic.env.oauth_provider.value == 'microsoft' %}
|
||||
var args = {client_id: '{{pwic.env.oauth_identifier.value|escape}}',
|
||||
response_type: 'code',
|
||||
redirect_uri: '{{pwic.env.base_url.value|escape}}/api/oauth',
|
||||
scope: 'https://graph.microsoft.com/user.read',
|
||||
response_mode: 'query',
|
||||
state: '{{pwic.oauth_user_secret|escape}}',
|
||||
login_hint: $('#login_user').val()};
|
||||
{% if pwic.env.oauth_domains %}
|
||||
var main = '{{pwic.env.oauth_domains.value|escape}}'.trim().split(' ')[0];
|
||||
if (main.length > 0)
|
||||
args['domain_hint'] = main;
|
||||
{% endif %}
|
||||
window.location = 'https://login.microsoftonline.com/{{pwic.env.oauth_tenant.value|urlencode}}/oauth2/v2.0/authorize?' + (new URLSearchParams(args).toString());
|
||||
|
||||
{% else %}
|
||||
throw 'Internal error - Invalid OAuth provider';
|
||||
{% endif %}
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{% if pwic.env.registration_link %}
|
||||
function login_register() {
|
||||
window.location = '{{pwic.env.registration_link.value|escape}}';
|
||||
return true;
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
if (window.fetch)
|
||||
$('#login_js').addClass('pwic_hidden');
|
||||
</script>
|
||||
@@ -0,0 +1,30 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
fetch('/api/server/env/get',
|
||||
{ method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({'project': '{{pwic.project|slash}}'}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (response.ok)
|
||||
response.json().then(data => {
|
||||
var key, buffer, tr;
|
||||
for (key in data) {
|
||||
tr = $(document.createElement('TR')).appendTo($('#audit_envs'));
|
||||
$(document.createElement('TD'))
|
||||
.html('<code>' + pwic_entities(key) + '</code>')
|
||||
.appendTo(tr);
|
||||
$(document.createElement('TD'))
|
||||
.html(data[key].global
|
||||
? '<span title="{% trans %}Global{% endtrans %}">{{pwic.emojis.globe}}</span>'
|
||||
: '<span title="{% trans %}Project-dependent{% endtrans %}">{{pwic.emojis.hammer}}</span>')
|
||||
.appendTo(tr);
|
||||
$(document.createElement('TD'))
|
||||
.addClass('pwic_monospace')
|
||||
.html(pwic_entities(data[key].value))
|
||||
.appendTo(tr);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,49 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
$('#create_kb').on('change', event => {
|
||||
if ($(event.target).prop('checked')) {
|
||||
var e = $('#create_page');
|
||||
if (e.val() == '')
|
||||
e.val('kb');
|
||||
e[0].select();
|
||||
}
|
||||
});
|
||||
|
||||
function create_submit() {
|
||||
var project = $('#create_project').val().trim().toLowerCase(),
|
||||
kbmode = $('#create_kb').prop('checked'),
|
||||
page = $('#create_page').val().trim().toLowerCase();
|
||||
|
||||
// Check the parameters
|
||||
if (!pwic_is_safe(project) || !pwic_is_safe(page)) {
|
||||
alert({% trans %}'The parameters are not acceptable.'{% endtrans %});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Submit the form
|
||||
$('INPUT[type=button]').attr('disabled', '');
|
||||
var args = {project: project,
|
||||
kb: kbmode,
|
||||
page: page,
|
||||
tags: $('#create_tags').val(),
|
||||
milestone: $('#create_milestone').val(),
|
||||
ref_project: $('#create_ref_project').val(),
|
||||
ref_page: $('#create_ref_page').val(),
|
||||
ref_tags: $('#create_ref_tags').val()};
|
||||
fetch('/api/page/create', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams(args),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
$('INPUT[type=button]').removeAttr('disabled');
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
response.json().then(data => window.location = data['url'] + '?success');
|
||||
})
|
||||
.catch(error => {
|
||||
alert(error);
|
||||
$('INPUT[type=button]').removeAttr('disabled');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,695 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
// -------------------------------- Toolbar
|
||||
|
||||
function edit_decorate(tagStart, tagEnd) {
|
||||
var nosel = !md_editor.somethingSelected();
|
||||
md_editor.replaceSelection(tagStart + md_editor.getSelection() + tagEnd);
|
||||
if (nosel) {
|
||||
var cur = md_editor.getCursor();
|
||||
md_editor.setCursor(cur.line, cur.ch - tagEnd.length);
|
||||
}
|
||||
md_editor.focus();
|
||||
}
|
||||
|
||||
function edit_decorate_end(text) {
|
||||
md_editor.replaceSelection(md_editor.getSelection() + text);
|
||||
md_editor.focus();
|
||||
}
|
||||
|
||||
function edit_link() {
|
||||
if (md_editor.somethingSelected()) {
|
||||
// Check the current selection for an autolink
|
||||
var txt = md_editor.getSelection();
|
||||
if (txt.match('^[a-z]{3,7}:\/\/')) {
|
||||
md_editor.replaceSelection('<' + md_editor.getSelection().replaceAll(' ', '%20') + '>');
|
||||
md_editor.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask for the link
|
||||
var url = prompt({% trans %}'Paste the link:'{% endtrans %}, '');
|
||||
if ((url != null) && (url != '')) {
|
||||
url = url.trim();
|
||||
if ((url.length > 0)
|
||||
&& (url.indexOf(':') === -1)
|
||||
&& (url.indexOf('/') === -1)
|
||||
&& (url == url.toLowerCase()))
|
||||
url = '/{{pwic.project}}/' + url;
|
||||
|
||||
// Replace the text by another one
|
||||
md_editor.replaceSelection('[' + txt + '](' + url + ')');
|
||||
}
|
||||
}
|
||||
md_editor.focus();
|
||||
}
|
||||
|
||||
function _edit_prepend_generic(ftag) {
|
||||
// Fit the selection
|
||||
var lft = md_editor.getCursor('start'),
|
||||
rgt = md_editor.getCursor('end');
|
||||
md_editor.setCursor(lft.line, 0);
|
||||
md_editor.setSelection(md_editor.getCursor('start'), rgt);
|
||||
|
||||
// Adapt the content to the new format
|
||||
var txt = ftag() + md_editor.getSelection();
|
||||
md_editor.replaceSelection(txt.split('').map(c => c == '\n' ? '\n' + ftag() : c).join(''));
|
||||
md_editor.focus();
|
||||
}
|
||||
|
||||
function edit_prepend(tag) {
|
||||
return _edit_prepend_generic(() => tag);
|
||||
}
|
||||
|
||||
function edit_prepend_nlist() {
|
||||
var id = 0;
|
||||
return _edit_prepend_generic(() => ++id + '. ');
|
||||
}
|
||||
|
||||
function _edit_block_transform(f) {
|
||||
if (md_editor.somethingSelected())
|
||||
md_editor.replaceSelection(f(md_editor.getSelection()), 'around');
|
||||
md_editor.focus();
|
||||
}
|
||||
|
||||
function edit_switch_case() {
|
||||
_edit_block_transform(s => (s == s.toUpperCase()
|
||||
? s.toLowerCase()
|
||||
: (s == s.toLowerCase()
|
||||
? s.substring(0,1).toUpperCase() + s.substring(1).toLowerCase()
|
||||
: s.toUpperCase())));
|
||||
}
|
||||
|
||||
function edit_double_spaces() {
|
||||
_edit_block_transform(s => s.replace(/ +/g, ' '));
|
||||
}
|
||||
|
||||
function edit_left_line() {
|
||||
_edit_block_transform(s => s.replaceAll('\r', '').replace(/\n\s+/g, '\n'));
|
||||
}
|
||||
|
||||
function edit_no_blank_line() {
|
||||
_edit_block_transform(s => s.replaceAll('\r', '').replaceAll(/\n\s*\n/g, '\n'));
|
||||
}
|
||||
|
||||
function edit_single_line() {
|
||||
_edit_block_transform(s => s.replaceAll('\r', '').replace(/[\s\t]*\n[\s\t]*/, '\n').replaceAll('\n', ' '));
|
||||
}
|
||||
|
||||
function edit_table() {
|
||||
// Get the dimensions of the table
|
||||
var ncol = parseInt(prompt({% trans %}'Number of columns:'{% endtrans %}, 0));
|
||||
if (isNaN(ncol) || (ncol < 1))
|
||||
return false;
|
||||
var nrow = parseInt(prompt({% trans %}'Number of rows:'{% endtrans %}, 0)) + 1;
|
||||
if (isNaN(nrow) || (nrow < 1))
|
||||
return false;
|
||||
|
||||
// Prepare the associated markdown
|
||||
var i, j, buffer = '';
|
||||
for (i=0 ; i<nrow ; i++) {
|
||||
buffer += '|';
|
||||
for (j=0 ; j<ncol ; j++)
|
||||
buffer += ' |';
|
||||
buffer += '\n';
|
||||
if (i == 0) {
|
||||
buffer += '|';
|
||||
for (j=0 ; j<ncol ; j++)
|
||||
buffer += ' -------- |';
|
||||
buffer += '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the text
|
||||
md_editor.replaceSelection(buffer);
|
||||
md_editor.focus();
|
||||
}
|
||||
|
||||
function edit_table_import() {
|
||||
try {
|
||||
navigator.clipboard.readText()
|
||||
.then(input_text => {
|
||||
var i, j, lines, cols,
|
||||
ncols = 0,
|
||||
nlens = [],
|
||||
txt, buffer, nice;
|
||||
|
||||
// Check
|
||||
input_text = input_text.replaceAll('\r', '').trim();
|
||||
if (input_text.length == 0) {
|
||||
$('#edit_toolbar_table').trigger('click');
|
||||
return;
|
||||
}
|
||||
|
||||
// Scan the dimensions of the table
|
||||
lines = input_text.split('\n');
|
||||
for (i=0 ; i<lines.length ; i++) {
|
||||
cols = lines[i].split('\t');
|
||||
ncols = Math.max(ncols, cols.length);
|
||||
for (j=0 ; j<cols.length ; j++) {
|
||||
if (nlens.length <= j)
|
||||
nlens.push(0);
|
||||
nlens[j] = Math.max(nlens[j], cols[j].trim().length);
|
||||
}
|
||||
}
|
||||
nice = (nlens.reduce((a, b) => a + b, 0) <= 128); // To shorten large tables
|
||||
|
||||
// Build the final text
|
||||
buffer = '';
|
||||
for (i=0 ; i<lines.length ; i++) {
|
||||
buffer += '\n';
|
||||
cols = lines[i].split('\t');
|
||||
for (j=0 ; j<ncols ; j++) {
|
||||
txt = (j < cols.length ? cols[j] : '').trim();
|
||||
buffer += '| ' + txt + ' '.repeat((nice ? nlens[j] - txt.length : 0) + 1);
|
||||
}
|
||||
buffer += '|';
|
||||
|
||||
// Header line
|
||||
if (i == 0) {
|
||||
buffer += '\n';
|
||||
for (j=0 ; j<ncols ; j++)
|
||||
buffer += '|' + '-'.repeat((nice ? nlens[j] : 1) + 2);
|
||||
buffer += '|';
|
||||
}
|
||||
}
|
||||
|
||||
// Paste the table
|
||||
edit_decorate_end('\n' + buffer + '\n\n');
|
||||
});
|
||||
} catch (e) {
|
||||
// See dom.events.testing.asyncClipboard in Firefox
|
||||
alert({% trans %}'You cannot use this feature.'{% endtrans %});
|
||||
}
|
||||
}
|
||||
|
||||
function edit_footnote() {
|
||||
// Search for the highest current footnote
|
||||
var id = 0,
|
||||
list = [...md_editor.getValue().matchAll(/\[\^([0-9]+)\]/g)];
|
||||
list.forEach(match => {
|
||||
var value = parseInt(match[1]);
|
||||
if (value > id)
|
||||
id = value;
|
||||
});
|
||||
|
||||
// Apply the footnote
|
||||
md_editor.replaceSelection(md_editor.getSelection() + ' [^'+(id+1)+']');
|
||||
md_editor.setValue(md_editor.getValue() + '\n\n' + '[^'+(id+1)+']: ');
|
||||
md_editor.focus();
|
||||
md_editor.setCursor(md_editor.lineCount(), 0);
|
||||
}
|
||||
|
||||
function edit_join_document(id, filename, mime) {
|
||||
var buffer = '';
|
||||
|
||||
// Include an image
|
||||
if (mime.substring(0, 6) == 'image/') {
|
||||
var tip = prompt({% trans %}'Tooltip of the image:'{% endtrans %}, ''),
|
||||
alt = prompt({% trans %}'Alternate text for the image:'{% endtrans %}, '');
|
||||
buffer = '![';
|
||||
if (alt != '')
|
||||
buffer += pwic_kick(alt, '["]');
|
||||
buffer += '](/special/document/' + id;
|
||||
if (tip != '')
|
||||
buffer += ' "'+pwic_kick(tip, '"')+'"';
|
||||
buffer += ')';
|
||||
}
|
||||
|
||||
// Any other file
|
||||
else
|
||||
buffer = '['+filename+'](/special/document/'+id+'?attachment)'
|
||||
|
||||
// Set the value
|
||||
md_editor.replaceSelection(buffer);
|
||||
md_editor.focus();
|
||||
}
|
||||
|
||||
function _edit_convert(endpoint, payload) {
|
||||
fetch(endpoint, { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams(payload),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
response.text().then(text => {
|
||||
if ((text != '') && confirm({% trans %}'Do you want to replace the current content by the one of the selected document?'{% endtrans %})) {
|
||||
md_editor.setValue(text);
|
||||
md_editor.focus();
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
|
||||
function edit_convert_document(id) {
|
||||
_edit_convert('/api/document/convert', {id: id});
|
||||
}
|
||||
|
||||
{% if pwic.env.remote_url %}
|
||||
function edit_convert_remote_document() {
|
||||
var url = prompt({% trans %}'Remote URL to fetch:'{% endtrans %}, '');
|
||||
if ((url != null) && (url != ''))
|
||||
_edit_convert( '/api/document/remote/convert',
|
||||
{project: '{{pwic.project|slash}}', url: url});
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
// -------------------------------- Dictation
|
||||
|
||||
{% if not pwic.env.no_dictation %}
|
||||
class PwicSpeech {
|
||||
constructor() {
|
||||
this._timeout = null;
|
||||
|
||||
// Load the speech recognition
|
||||
if ((location.protocol != 'https:') || (window.webkitSpeechRecognition === undefined)) {
|
||||
$('#edit_toolbar_dictate').prop('disabled', 'disabled');
|
||||
return false;
|
||||
}
|
||||
this._handler = new webkitSpeechRecognition();
|
||||
this._handler.continuous = true;
|
||||
this._handler.interimResults = true;
|
||||
this._handler.lang = $('HTML').prop('lang');
|
||||
|
||||
// Event when started
|
||||
this._handler.onstart = () => {
|
||||
this._timeout = setTimeout(() => this._handler.stop(), 5000);
|
||||
$('#edit_toolbar_dictate').addClass('pwic_limebg');
|
||||
};
|
||||
|
||||
// Event on word received
|
||||
// https://developer.chrome.com/blog/voice-driven-web-apps-introduction-to-the-web-speech-api
|
||||
this._handler.onresult = (event) => {
|
||||
// Fetch the words
|
||||
var buffer, i, result, lft, rgt;
|
||||
buffer = '';
|
||||
for (i=event.resultIndex; i<event.results.length; ++i) {
|
||||
result = event.results[i];
|
||||
buffer += result[0].transcript;
|
||||
}
|
||||
|
||||
// Update the Markdown editor
|
||||
md_editor.replaceSelection(buffer);
|
||||
if (!result.isFinal) {
|
||||
rgt = md_editor.getCursor();
|
||||
lft = {...rgt};
|
||||
lft.ch -= buffer.length;
|
||||
md_editor.setSelection(lft, rgt);
|
||||
}
|
||||
|
||||
// Delay
|
||||
clearTimeout(this._timeout);
|
||||
this._timeout = setTimeout(() => this._handler.stop(), 5000);
|
||||
};
|
||||
|
||||
// Event when ended
|
||||
this._handler.onend = () => {
|
||||
clearTimeout(this._timeout);
|
||||
this._timeout = null;
|
||||
$('#edit_toolbar_dictate').removeClass('pwic_limebg');
|
||||
};
|
||||
|
||||
// Install
|
||||
$('#edit_toolbar_dictate').on('click', (event) => {
|
||||
if ($(event.target).hasClass('pwic_limebg'))
|
||||
this._handler.stop();
|
||||
else
|
||||
if (this._timeout == null) {
|
||||
this._handler.start();
|
||||
md_editor.focus();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new PwicSpeech();
|
||||
{% endif %}
|
||||
|
||||
// -------------------------------- File drop
|
||||
|
||||
function edit_refresh_documents() {
|
||||
fetch('/api/document/list', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ project: '{{pwic.project|slash}}',
|
||||
page: '{{pwic.page|slash}}' }),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
response.json().then(data => {
|
||||
$('#edit_files_list TR:nth-child(n+2)').remove();
|
||||
var i, doc, tr, td;
|
||||
for (i=0 ; i<data.length ; i++) {
|
||||
doc = data[i];
|
||||
tr = $(document.createElement('TR')).appendTo($('#edit_files_list'));
|
||||
td = $(document.createElement('TD')).appendTo(tr);
|
||||
$(document.createElement('INPUT'))
|
||||
.attr('type', 'button')
|
||||
.val(pwic_unimoji('{{pwic.emojis.plus}}'))
|
||||
.attr('title', "{% trans %}Add a link{% endtrans %}")
|
||||
.data('id', doc.id)
|
||||
.data('filename', doc.filename)
|
||||
.data('mime', doc.mime)
|
||||
.on('click', (e) => edit_join_document($(e.target).data('id'), $(e.target).data('filename'), $(e.target).data('mime')))
|
||||
.appendTo(td);
|
||||
if (doc.convertible)
|
||||
$(document.createElement('INPUT'))
|
||||
.addClass('pwic_desktop')
|
||||
.attr('type', 'button')
|
||||
.val(pwic_unimoji('{{pwic.emojis.hammer}}'))
|
||||
.attr('title', "{% trans %}Import the content of the document{% endtrans %}")
|
||||
.data('id', doc.id)
|
||||
.on('click', (e) => edit_convert_document($(e.target).data('id')))
|
||||
.appendTo(td);
|
||||
|
||||
td = $(document.createElement('TD')).appendTo(tr);
|
||||
$(document.createElement('A'))
|
||||
.attr('href', '/special/document/' + encodeURIComponent(doc.id) + '/' + encodeURIComponent(doc.filename))
|
||||
.attr('target', '_blank')
|
||||
.html(pwic_entities(doc.filename) + (doc.exturl != '' ? ' {{pwic.emojis.cloud}}' : ''))
|
||||
.appendTo(td);
|
||||
|
||||
$(document.createElement('TD'))
|
||||
.addClass('pwic_desktop')
|
||||
.html(doc.used ? '{{pwic.emojis.green_check}}' : '')
|
||||
.appendTo(tr);
|
||||
|
||||
$(document.createElement('TD'))
|
||||
.attr('title', "{% trans %}Hash:{% endtrans %} " + pwic_entities(doc.hash.substring(0, 8)))
|
||||
.html(doc.size_str)
|
||||
.appendTo(tr);
|
||||
|
||||
$(document.createElement('TD'))
|
||||
.addClass('pwic_desktop')
|
||||
.attr('title', pwic_entities(doc.mime))
|
||||
.html(doc.mime_icon + ' ' + pwic_entities(doc.extension).toUpperCase())
|
||||
.appendTo(tr);
|
||||
|
||||
td = $(document.createElement('TD'))
|
||||
.addClass('pwic_desktop')
|
||||
.appendTo(tr);
|
||||
$(document.createElement('A'))
|
||||
.attr('href', '/special/user/' + encodeURIComponent(doc.author))
|
||||
.attr('target', '_blank')
|
||||
.attr('rel', 'nofollow')
|
||||
.html(pwic_entities(doc.author))
|
||||
.appendTo(td);
|
||||
|
||||
$(document.createElement('TD'))
|
||||
.html(pwic_entities(doc.date))
|
||||
.appendTo(tr);
|
||||
|
||||
$(document.createElement('TD'))
|
||||
.addClass('pwic_desktop')
|
||||
.html(pwic_entities(doc.time))
|
||||
.appendTo(tr);
|
||||
|
||||
td = $(document.createElement('TD')).appendTo(tr);
|
||||
$(document.createElement('INPUT'))
|
||||
.attr('type', 'button')
|
||||
.val(pwic_unimoji('{{pwic.emojis.curved_left_arrow}}'))
|
||||
.attr('title', "{% trans %}Rename the document{% endtrans %}")
|
||||
.data('id', doc.id)
|
||||
.data('filename', doc.filename)
|
||||
.on('click', (e) => edit_rename_document($(e.target).data('id'), $(e.target).data('filename')))
|
||||
.appendTo(td);
|
||||
$(document.createElement('INPUT'))
|
||||
.attr('type', 'button')
|
||||
.val(pwic_unimoji('{{pwic.emojis.red_check}}'))
|
||||
.attr('title', "{% trans %}Delete the document{% endtrans %}")
|
||||
.data('id', doc.id)
|
||||
.data('filename', doc.filename)
|
||||
.on('click', (e) => edit_delete_document($(e.target).data('id'), $(e.target).data('filename')))
|
||||
.appendTo(td);
|
||||
}
|
||||
$('#edit_files_list').toggleClass('pwic_hidden', data.length == 0);
|
||||
});
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
|
||||
edit_refresh_documents(); // For the initialization
|
||||
|
||||
function _edit_transfer_files(files) {
|
||||
// Create an XHR for each file
|
||||
var notification = null;
|
||||
for (var i=0 ; i<files.length ; i++) {
|
||||
// Fields
|
||||
var form = new FormData();
|
||||
form.append('project', '{{pwic.project|slash}}');
|
||||
form.append('page', '{{pwic.page|slash}}');
|
||||
form.append('content', files[i]);
|
||||
|
||||
// Request
|
||||
fetch('/api/document/create', { method: 'POST',
|
||||
body: form,
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
if (notification != null)
|
||||
clearTimeout(notification);
|
||||
notification = setTimeout(() => {
|
||||
edit_refresh_documents();
|
||||
alert({% trans %}'The file is uploaded and usable in the list below.'{% endtrans %});
|
||||
}, 2000);
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
}
|
||||
|
||||
function edit_upload_document() {
|
||||
var obj = $(document.createElement('INPUT'))
|
||||
.attr('type', 'file')
|
||||
.addClass('pwic_hidden')
|
||||
.appendTo('body')
|
||||
.on('change', e => { _edit_transfer_files(e.target.files), obj.remove() })
|
||||
.on('cancel', () => obj.remove())
|
||||
.trigger('click');
|
||||
}
|
||||
|
||||
function edit_drop(event) {
|
||||
$('#edit_files_drop').removeClass('pwic_dragover');
|
||||
if (event.dataTransfer.items) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
_edit_transfer_files(event.dataTransfer.files);
|
||||
} else
|
||||
alert({% trans %}'Unsupported feature.'{% endtrans %});
|
||||
}
|
||||
|
||||
function edit_dragover(event) {
|
||||
$('#edit_files_drop').addClass('pwic_dragover');
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
function edit_dragleave(event) {
|
||||
$('#edit_files_drop').removeClass('pwic_dragover');
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
function edit_rename_document(id, filename) {
|
||||
var newfn = prompt('Type the new file name:', filename);
|
||||
if ((newfn != null) && (newfn != filename)) {
|
||||
fetch('/api/document/rename', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ id: id,
|
||||
project: '{{pwic.project|slash}}',
|
||||
filename: newfn}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
setTimeout(edit_refresh_documents, 1000);
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function edit_delete_document(id, filename) {
|
||||
if (confirm({% trans %}'Are sure to delete "%s"?'{% endtrans %}.replace('%s', filename))) {
|
||||
fetch('/api/document/delete', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ id: id,
|
||||
project: '{{pwic.project|slash}}'}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
setTimeout(edit_refresh_documents, 1000);
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------- Submit a page
|
||||
|
||||
$('#edit_comment').on('dblclick', event => {
|
||||
if ($(event.target).val() == '')
|
||||
$(event.target).val($(event.target).prop('placeholder'));
|
||||
});
|
||||
|
||||
var edit_submittable = false,
|
||||
edit_preview_hwnd = null;
|
||||
|
||||
function edit_submit_form() {
|
||||
// Check the current values
|
||||
edit_submittable = ($('#edit_title').val() != '')
|
||||
&& ($('#edit_comment').val() != '');
|
||||
if (!edit_submittable) {
|
||||
alert({% trans %}'Some fields are mandatory.'{% endtrans %});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable the button temporarily
|
||||
$('#edit_submit').prop('disabled', true);
|
||||
setTimeout(() => $('#edit_submit').prop('disabled', false), 5000);
|
||||
|
||||
// First ping-pong the server to make sure that the session is still valid
|
||||
fetch('/api/server/ping', { method: 'POST',
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
var errorPing = {% trans %}'Your session is not valid anymore. Please reconnect from another tab and retry.'{% endtrans %};
|
||||
if (!response.ok)
|
||||
alert('['+response.status+'] '+errorPing);
|
||||
else
|
||||
response.text().then(text => {
|
||||
if (text != 'OK') {
|
||||
alert(errorPing);
|
||||
return;
|
||||
}
|
||||
|
||||
// Close the preview
|
||||
if (edit_preview_hwnd != null) {
|
||||
edit_preview_hwnd.close();
|
||||
edit_preview_hwnd = null;
|
||||
}
|
||||
|
||||
// Query the current revision of the modified page
|
||||
fetch('/api/project/get', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ project: '{{pwic.project|slash}}',
|
||||
page: '{{pwic.page|slash}}'}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error('['+response.status+'] '+response.statusText);
|
||||
response.json().then(data => {
|
||||
// Check the conflict
|
||||
if (data['{{pwic.page|slash}}']['revisions'][0]['revision'] > {{pwic.revision}}) {
|
||||
if (!confirm({% trans %}'Warning: the page has been modified in parallel of your current modifications.\n\nConsequently, your changes will be posted as a removable draft. You must merge the changes manually later.'{% endtrans %}))
|
||||
return false;
|
||||
$('#edit_draft').prop('checked', true);
|
||||
$('#edit_final').prop('checked', false);
|
||||
}
|
||||
|
||||
// Submit the modifications
|
||||
{# sof/7542586 #}
|
||||
var form = {project: '{{pwic.project|slash}}',
|
||||
page: '{{pwic.page|slash}}',
|
||||
title: $('#edit_title').val(),
|
||||
tags: $('#edit_tags').val(),
|
||||
markdown: md_editor.getValue(),
|
||||
comment: $('#edit_comment').val(),
|
||||
milestone: $('#edit_milestone').val(),
|
||||
draft: $('#edit_draft').prop('checked'),
|
||||
final: $('#edit_final').prop('checked'),
|
||||
header: $('#edit_header').prop('checked'),
|
||||
protection: $('#edit_protection').prop('checked')};
|
||||
fetch('/api/page/edit', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams(form),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
window.location = '/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}?success';
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
});
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
});
|
||||
})
|
||||
.catch(error => alert({% trans %}'The server or your Internet connection is down.'{% endtrans %}));
|
||||
}
|
||||
|
||||
function edit_preview_md(pageName) {
|
||||
fetch('/api/markdown/convert', {method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ project: '{{pwic.project|slash}}',
|
||||
markdown: md_editor.somethingSelected() ? md_editor.getSelection() : md_editor.getValue()}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
response.text().then(text => {
|
||||
if (edit_preview_hwnd != null)
|
||||
edit_preview_hwnd.close();
|
||||
edit_preview_hwnd = window.open('');
|
||||
edit_preview_hwnd.document.head.innerHTML = '<link rel="stylesheet" type="text/css" href="'+window.location.protocol+'//'+window.location.host+'/static/styles.css" />';
|
||||
edit_preview_hwnd.document.title = {% trans %}'Preview of the page'{% endtrans %} + ' "'+pageName+'"';
|
||||
edit_preview_hwnd.document.body.innerHTML = '\
|
||||
<article>\
|
||||
<p style="position:fixed; top:0px; right:0px; padding:15px">\
|
||||
<input type="button" onclick="window.close()" value="{{pwic.emojis.door}} '+{% trans %}'Close the preview'{% endtrans %}+'" />\
|
||||
<\/p>\
|
||||
'+text+'\
|
||||
<\/article>';
|
||||
edit_preview_hwnd.window.onkeydown = function(event) {
|
||||
if (event.key == 'Escape') {
|
||||
edit_preview_hwnd.close();
|
||||
edit_preview_hwnd = null;
|
||||
}
|
||||
};
|
||||
});
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------- Leave without saving
|
||||
|
||||
window.onbeforeunload = function(e) {
|
||||
var e = e || window.event;
|
||||
if (!edit_submittable)
|
||||
if (e)
|
||||
e.returnValue = {% trans %}'The current changes may be lost.'{% endtrans %};
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------- Markdown editor
|
||||
|
||||
function edit_undo(mode) {
|
||||
if (mode)
|
||||
md_editor.undo();
|
||||
else
|
||||
md_editor.redo();
|
||||
md_editor.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
function _edit_get_shortcuts() { // Callable once
|
||||
var sc = {};
|
||||
$("INPUT[type='button'][data-shortcut]").each((i, e) => {
|
||||
e.title = (e.title || '') + ' (' + e.dataset['shortcut'] + ')';
|
||||
sc[e.dataset.shortcut] = cm => e.click();
|
||||
});
|
||||
return sc;
|
||||
}
|
||||
|
||||
var md_editor = CodeMirror.fromTextArea(document.getElementById('edit_markdown'), {
|
||||
mode: 'markdown',
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
extraKeys: _edit_get_shortcuts()
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,76 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
// Easy copy of the global value
|
||||
$('INPUT[type=text]').on('dblclick', event => {
|
||||
if ($(event.target).val() == '') {
|
||||
$(event.target).val($(event.target).prop('placeholder'));
|
||||
$(event.target).trigger('keyup');
|
||||
}
|
||||
});
|
||||
|
||||
// Manage the visibility of the save button
|
||||
$('INPUT[type=button]').addClass('pwic_hidden');
|
||||
$('INPUT[type=text]').on('keyup', event => {
|
||||
// Inbound values
|
||||
var value = $(event.target).val(),
|
||||
saved = ($(event.target).data('saved') || ''),
|
||||
global = ($(event.target).data('global') == 'X');
|
||||
// Conditions to show it
|
||||
var b1 = !global && (value != saved),
|
||||
b2 = global && (value != '');
|
||||
$('INPUT[type=button][data-key='+$(event.target).data('key')+']').toggleClass('pwic_hidden', !b1 && !b2);
|
||||
});
|
||||
|
||||
// Manage the save button
|
||||
$('INPUT[type=button]').on('click', event => {
|
||||
var key = $(event.target).data('key'),
|
||||
value = $('INPUT[type=text][data-key='+key+']').val();
|
||||
env_set(key, value);
|
||||
});
|
||||
|
||||
// Load the default values of the configuration
|
||||
$('INPUT[type=text]').attr('readonly', '').addClass('pwic_disabled_bg');
|
||||
fetch('/api/server/env/get', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({project: '{{pwic.project|slash}}'}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
response.json().then(data => {
|
||||
var key, item, element;
|
||||
for (key in data) {
|
||||
item = data[key];
|
||||
element = $('INPUT[type=text][data-key='+key+']');
|
||||
if (element.length == 1) {
|
||||
element.data('saved', item['value'])
|
||||
.data('global', (item['global'] ? 'X' : ''));
|
||||
if (item['global'])
|
||||
element.attr('placeholder', item['value']);
|
||||
else
|
||||
element.val(item['value']);
|
||||
}
|
||||
}
|
||||
$('INPUT[type=text]').removeAttr('readonly').removeClass('pwic_disabled_bg');
|
||||
});
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
|
||||
// Action when the save button is pressed
|
||||
function env_set(key, value) {
|
||||
fetch('/api/project/env/set', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ project: '{{pwic.project|slash}}',
|
||||
key: key,
|
||||
value: value}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
$('INPUT[type=text][data-key='+key+']').data('saved', value);
|
||||
$('INPUT[type=button][data-key='+key+']').addClass('pwic_hidden');
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,70 @@
|
||||
<script src="/static/svg-pan-zoom.min.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
// Get the graph from the API
|
||||
var graph_cache = null;
|
||||
|
||||
function graph_get_data(action) {
|
||||
// Download from cache
|
||||
if ((action == 'download') && (graph_cache != null))
|
||||
return graph_download();
|
||||
|
||||
// Else first download
|
||||
fetch('/api/project/graph/get', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({project: '{{pwic.project|slash}}'}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
response.text().then(text => {
|
||||
graph_cache = text;
|
||||
if (action == 'render')
|
||||
graph_generate_svg();
|
||||
else
|
||||
if (action == 'download')
|
||||
graph_download();
|
||||
});
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
graph_get_data('render');
|
||||
|
||||
// Download the graph as a raw file
|
||||
function graph_download() {
|
||||
if (graph_cache == null)
|
||||
return false;
|
||||
var blob = window.URL.createObjectURL(new Blob([graph_cache], {type: 'text/vnd.graphviz'}));
|
||||
$(document.createElement('A'))
|
||||
.addClass('pwic_hidden')
|
||||
.attr('href', blob)
|
||||
.attr('download', '{{pwic.project|slash}}.gv')
|
||||
.appendTo('BODY')
|
||||
.trigger('click')
|
||||
.remove();
|
||||
window.URL.revokeObjectURL(blob);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Generate the graph
|
||||
function graph_generate_svg() {
|
||||
var worker = new Worker('/static/viz.js');
|
||||
worker.onmessage = function(e) {
|
||||
// Render SVG
|
||||
var graph = $('#graph_viz')[0];
|
||||
var svg = (new DOMParser()).parseFromString(e.data, 'image/svg+xml').documentElement;
|
||||
graph.appendChild(svg);
|
||||
|
||||
// Zooming area for SVG
|
||||
var panZoom = svgPanZoom(svg, {zoomEnabled: true, controlIconsEnabled: true, center: true, minZoom: 0.1});
|
||||
svg.addEventListener('paneresize', e => panZoom.resize(), false);
|
||||
window.addEventListener('resize', e => panZoom.resize());
|
||||
worker.terminate();
|
||||
};
|
||||
worker.onerror = function(e) {
|
||||
alert(e.message === undefined ? 'The graph cannot be rendered.' : e.message);
|
||||
};
|
||||
worker.postMessage({src: graph_cache, options: {engine: 'dot', format: 'svg'}});
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,19 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function history_compare() {
|
||||
var rev = [];
|
||||
$('input').each((i, e) => {
|
||||
e = $(e);
|
||||
if ((e.attr('type') == 'checkbox') && e.prop('checked'))
|
||||
rev.push(e.data('revision'));
|
||||
});
|
||||
if (rev.length > 2)
|
||||
return false;
|
||||
if (rev.length == 2) {
|
||||
rev.sort();
|
||||
window.location = '/{{pwic.project|urlencode}}/{{pwic.page|urlencode}}/rev'+rev[1]+'/compare/rev'+rev[0];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,52 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
$('#move_dst_page').on('dblclick', event => {
|
||||
if ($(event.target).val() == '')
|
||||
$(event.target).val($(event.target).prop('placeholder'));
|
||||
});
|
||||
|
||||
function move_submit() {
|
||||
// Fetch the parameters
|
||||
var srcproj = $('#move_src_project').val(),
|
||||
srcpage = $('#move_src_page').val(),
|
||||
dstproj = $('#move_dst_project').val(),
|
||||
dstpage = $('#move_dst_page').val().trim().toLowerCase();
|
||||
|
||||
// Check the parameters
|
||||
if (dstpage == '')
|
||||
dstpage = srcpage;
|
||||
if ( !pwic_is_safe(srcproj)
|
||||
|| !pwic_is_safe(srcpage)
|
||||
|| !pwic_is_safe(dstproj)
|
||||
|| !pwic_is_safe(dstpage)
|
||||
|| ((srcproj == dstproj) && (dstpage == srcpage))
|
||||
|| ((srcproj != dstproj) && (dstpage == ''))
|
||||
) {
|
||||
alert({% trans %}'The parameters are not acceptable.'{% endtrans %});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Submit the form
|
||||
$('INPUT[type=button]').attr('disabled', '');
|
||||
var args = {project: dstproj,
|
||||
page: dstpage,
|
||||
ref_project: srcproj,
|
||||
ref_page: srcpage,
|
||||
ignore_file_errors: 'X'};
|
||||
fetch('/api/page/move', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams(args),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
$('INPUT[type=button]').removeAttr('disabled');
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
window.location = response.url;
|
||||
})
|
||||
.catch(error => {
|
||||
alert(error);
|
||||
$('INPUT[type=button]').removeAttr('disabled');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,86 @@
|
||||
<script>
|
||||
(function() {
|
||||
var list_initial = null,
|
||||
timeout = null;
|
||||
|
||||
$('#page_progress_tags > A:nth-child(1)').on('click', event => {
|
||||
$('#page_progress_tags > A:nth-child(n+4)').addClass('pwic_selected');
|
||||
clearTimeout(timeout);
|
||||
page_progress_refresh();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#page_progress_tags > A:nth-child(2)').on('click', event => {
|
||||
$('#page_progress_tags > A:nth-child(n+4)').removeClass('pwic_selected');
|
||||
clearTimeout(timeout);
|
||||
page_progress_refresh();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#page_progress_tags > A:nth-child(n+3)').on('click', event => {
|
||||
$(event.target).toggleClass('pwic_selected');
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(page_progress_refresh, 2000);
|
||||
return false;
|
||||
});
|
||||
|
||||
async function page_progress_refresh() {
|
||||
function _pc(a, b) {
|
||||
return (b == 0 ? '' : Math.floor(100 * a / b) + ' %');
|
||||
}
|
||||
function _sl(terms, text, entries) {
|
||||
if ({% if pwic.env.no_search %} true {% else %} false {% endif %} || (entries == 0))
|
||||
return encodeURIComponent(text);
|
||||
return '<a href="/{{pwic.project|urlencode}}/special/search?q=%23'+encodeURIComponent(terms)+'" target="_blank">'+encodeURIComponent(text)+'<\/a>';
|
||||
}
|
||||
|
||||
// Get the selected tags
|
||||
var tags = '';
|
||||
$('#page_progress_tags > A:nth-child(n+4)').each((i, e) => {
|
||||
if ($(e).hasClass('pwic_selected'))
|
||||
tags += ' ' + $(e).text().substring(1);
|
||||
});
|
||||
tags = tags.trim();
|
||||
|
||||
// Calculate the progress
|
||||
var buffer = '';
|
||||
if (tags.length > 0) {
|
||||
var args = {project: '{{pwic.project|slash}}',
|
||||
tags: tags,
|
||||
combined: $('#page_progress_tags > A:nth-child(3)').hasClass('pwic_selected') ? 'on' : ''},
|
||||
options = { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams(args),
|
||||
credentials: 'same-origin'};
|
||||
try {
|
||||
var request = await fetch('/api/project/progress/get', options);
|
||||
if (request.ok) {
|
||||
var data = await request.json();
|
||||
for (var tag in data) {
|
||||
var item = data[tag];
|
||||
if (item['total'] > 0)
|
||||
buffer += '<tr>'
|
||||
+ '<td>' + _sl(tag, tag, 1) + '<\/td>'
|
||||
+ '<td>' + _sl(tag + ' :draft', item['draft'], item['draft']) + '<\/td>'
|
||||
+ '<td class="pwic_desktop">' + _pc(item['draft'], item['total']) + '<\/td>'
|
||||
+ '<td>' + _sl(tag + ' -:draft -:final -:validated', item['step'], item['step']) + '<\/td>'
|
||||
+ '<td class="pwic_desktop">' + _pc(item['step'], item['total']) + '<\/td>'
|
||||
+ '<td>' + _sl(tag + ' :final', item['final'], item['final']) + '<\/td>'
|
||||
+ '<td class="pwic_desktop">' + _pc(item['final'], item['total']) + '<\/td>'
|
||||
+ '<td>' + _sl(tag + ' :validated', item['validated'], item['validated']) + '<\/td>'
|
||||
+ '<td class="pwic_desktop">' + _pc(item['validated'], item['total']) + '<\/td>'
|
||||
+ '<\/tr>';
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// Display the result
|
||||
var e = $('#page_progress_list');
|
||||
e.html((list_initial = list_initial || e.html()) + buffer).toggleClass('pwic_hidden', buffer.length == 0);
|
||||
}
|
||||
}());
|
||||
</script>
|
||||
@@ -0,0 +1,156 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
{% if pwic.env.no_text_selection %}
|
||||
$(document).on('keydown', e => !((e.key == 'F12') || (e.ctrlKey && e.shiftKey && (e.key == 'I')) || (e.ctrlKey && (e.key == 'u'))));
|
||||
$(document).on('selectstart', () => false);
|
||||
$(document).on('contextmenu', () => false);
|
||||
$('ARTICLE *').css(atob('dXNlci1zZWxlY3Q='), 'none');
|
||||
{% endif %}
|
||||
|
||||
window.onscroll = () => {
|
||||
var scroll = document.body.scrollTop || document.documentElement.scrollTop,
|
||||
height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
|
||||
$('#pwic_progress')[0].style.width = ((scroll / height) * 100).toString() + 'vw';
|
||||
$('#page_topofpage').toggleClass('pwic_hidden', scroll == 0);
|
||||
};
|
||||
|
||||
$(document).on('keyup', event => {
|
||||
if (!$('#pwic_browser').hasClass('pwic_hidden'))
|
||||
if ((event || window.event).key == 'Escape')
|
||||
$('#pwic_browser_access').trigger('click');
|
||||
});
|
||||
|
||||
function page_email() {
|
||||
{% if pwic.draft %}
|
||||
if (confirm({% trans %}'Warning: the current page is a draft, so its content may disappear in the future without notice.'{% endtrans %}))
|
||||
{% endif %}
|
||||
{
|
||||
var url = window.location.toString();
|
||||
if (url.endsWith('#'))
|
||||
url = url.substring(0, url.length - 1);
|
||||
window.location = "mailto:?subject={{pwic.title|urlencode}}&body="+encodeURIComponent('\n\n'+url);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function page_print() {
|
||||
window.print();
|
||||
return false;
|
||||
}
|
||||
|
||||
function page_tmap() {
|
||||
var element = $('#pwic_browser');
|
||||
element.toggleClass('pwic_hidden');
|
||||
if (!element.hasClass('pwic_hidden'))
|
||||
element[0].focus();
|
||||
}
|
||||
|
||||
function page_post_action(action, confirmText) {
|
||||
if (confirm(confirmText)) {
|
||||
fetch('/api/page/'+action, {method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ project: '{{pwic.project|slash}}',
|
||||
page: '{{pwic.page|slash}}',
|
||||
revision: {{pwic.revision}}}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
window.location = '/{{pwic.project|urlencode}}' +
|
||||
'/{{pwic.page|urlencode}}' +
|
||||
(action != 'delete' ? '/rev{{pwic.revision|urlencode}}' : '') +
|
||||
(action == 'delete' ? '?success' : '');
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function page_export(format) {
|
||||
fetch('/api/page/export', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ project: '{{pwic.project|slash}}',
|
||||
page: '{{pwic.page|slash}}',
|
||||
revision: {{pwic.revision}},
|
||||
format: format}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
var filename = response.headers.get('Content-Disposition').split('"')[1];
|
||||
filename = filename.substring(10,filename.length-2);
|
||||
filename = decodeURIComponent(escape(atob(filename)))
|
||||
response.blob().then(blob => {
|
||||
var dl = $(document.createElement('A'))
|
||||
.addClass('pwic_hidden')
|
||||
.attr('href', window.URL.createObjectURL(new Blob([blob], {type: blob.type})))
|
||||
.attr('download', filename)
|
||||
.appendTo('body')
|
||||
.trigger('click')
|
||||
.remove();
|
||||
window.URL.revokeObjectURL(dl.href);
|
||||
return true;
|
||||
});
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
{% if not pwic.env.no_copy_code %}
|
||||
function page_copy_code() {
|
||||
var code = $(this).parent().text().substring($(this).text().length);
|
||||
navigator.clipboard.writeText(code).then(
|
||||
() => alert({% trans %}'The code has been copied successfully to the clipboard.'{% endtrans %}),
|
||||
() => alert({% trans %}'The code cannot be copied to the clipboard.'{% endtrans %})
|
||||
);
|
||||
}
|
||||
|
||||
$('CODE').each((i, e) => {
|
||||
if ((e.clientHeight >= 100) || (e.clientWidth >= 300))
|
||||
$(e).prepend($(document.createElement('SPAN'))
|
||||
.addClass('pwic_copy_code' + (e.clientHeight <= 50 ? '_tiny' : ''))
|
||||
.attr('title', 'Copy')
|
||||
.html('{{pwic.emojis.notes}}')
|
||||
.on('click', page_copy_code));
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% if not pwic.env.no_table_csv %}
|
||||
function page_export_table() {
|
||||
var csv, row, x, y, val,
|
||||
table = this.parentElement;
|
||||
|
||||
// Prepare the table
|
||||
csv = [];
|
||||
for (y=0; y<table.rows.length; y++) {
|
||||
row = [];
|
||||
for (x=0; x<table.rows[y].cells.length; x++) {
|
||||
val = table.rows[y].cells[x].textContent;
|
||||
if ((val.indexOf('"') != -1) || (val.indexOf(';') != -1))
|
||||
val = '"' + val.replaceAll('"', '""') + '"';
|
||||
row.push(val);
|
||||
}
|
||||
csv.push(row.join(';'));
|
||||
}
|
||||
|
||||
// Download the file
|
||||
var blob = window.URL.createObjectURL(new Blob([csv], {type: 'text/csv'}));
|
||||
$(document.createElement('A'))
|
||||
.addClass('pwic_hidden')
|
||||
.attr('href', blob)
|
||||
.attr('download', 'table.csv')
|
||||
.appendTo('BODY')
|
||||
.trigger('click')
|
||||
.remove();
|
||||
window.URL.revokeObjectURL(blob);
|
||||
}
|
||||
|
||||
$('ARTICLE > TABLE').each((i, e) => {
|
||||
if (e.rows.length >= 10)
|
||||
$(e).append($(document.createElement('CAPTION'))
|
||||
.html('<span class="pwic_desktop">' + {% trans %}'Download this table as CSV file'{% endtrans %} + '<\/span><span class="pwic_mobile">💾 CSV<\/span>')
|
||||
.on('click', page_export_table));
|
||||
});
|
||||
{% endif %}
|
||||
</script>
|
||||
@@ -0,0 +1,20 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function page_start_search() {
|
||||
var args = {q: $('#page_search').val()};
|
||||
if (args['q'].length > 0) {
|
||||
if ($('#page_search_withrev').prop('checked'))
|
||||
args['rev'] = 'on';
|
||||
if ($('#page_search_casesensitive').prop('checked'))
|
||||
args['cs'] = 'on';
|
||||
window.location = '/{{pwic.project|urlencode}}/special/search?' + (new URLSearchParams(args).toString());
|
||||
}
|
||||
}
|
||||
|
||||
function page_search(event) {
|
||||
event = event || window.event;
|
||||
if (event.key == 'Enter')
|
||||
page_start_search();
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,28 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function create_submit() {
|
||||
var project = $('#create_project').val(),
|
||||
user = $('#create_user').val().trim().toLowerCase();
|
||||
if ((project == '') || (user.substring(0, 4) == 'pwic'))
|
||||
alert({% trans %}'The parameters are not acceptable.'{% endtrans %});
|
||||
else {
|
||||
$('INPUT[type=button]').attr('disabled', '');
|
||||
fetch('/api/user/create', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ project: project,
|
||||
user: user}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
$('INPUT[type=button]').removeAttr('disabled');
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
window.location = '/' + project + '/special/roles';
|
||||
})
|
||||
.catch(error => {
|
||||
alert(error);
|
||||
$('INPUT[type=button]').removeAttr('disabled');
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,33 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function roles_toggle(id, project, user, role) {
|
||||
var element = $('#roles_tag_' + id);
|
||||
if (element.length > 0) {
|
||||
element.toggleClass('pwic_hidden'); // Hide until the request is completed
|
||||
fetch('/api/user/roles/set', { method: 'POST',
|
||||
body: new URLSearchParams({ project: project,
|
||||
name: user,
|
||||
role: role}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok)
|
||||
throw Error(response.status + ' ' + response.statusText);
|
||||
response.text().then(text => {
|
||||
setTimeout(() => {
|
||||
if (element.attr('type') == 'checkbox')
|
||||
element.prop('checked', text == 'X');
|
||||
if (text != 'OK')
|
||||
element.toggleClass('pwic_hidden');
|
||||
}, 2000);
|
||||
});
|
||||
})
|
||||
.catch(error => setTimeout(() => element.toggleClass('pwic_hidden'), 2000));
|
||||
}
|
||||
return false; // The element is updated async later
|
||||
}
|
||||
|
||||
function roles_delete(text, id, project, user) {
|
||||
return confirm(text) && roles_toggle(id, project, user, 'delete');
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,55 @@
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function user_password_popup() {
|
||||
$('#user_password_popup').toggleClass('pwic_hidden');
|
||||
$('BODY').toggleClass('pwic_nooverflow');
|
||||
if ($('#user_password_popup').hasClass('pwic_hidden'))
|
||||
$('#user_password_current, #user_password_new1, #user_password_new2').val('');
|
||||
else {
|
||||
window.scrollTo(0, 0);
|
||||
$('#user_password_notice').toggleClass('pwic_hidden', window.location.toString().startsWith('https'));
|
||||
document.getElementById('user_password_current').focus();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$('body').on('keydown', event => {
|
||||
if ((event.key == 'Escape') && (!$('#user_password_popup').hasClass('pwic_hidden')))
|
||||
user_password_popup();
|
||||
});
|
||||
|
||||
function user_password_submit() {
|
||||
var cur = $('#user_password_current').val(),
|
||||
new1 = $('#user_password_new1').val(),
|
||||
new2 = $('#user_password_new2').val();
|
||||
if (([cur, new1, new2].indexOf('') !== -1) || (new1 != new2) || (new1 == cur))
|
||||
alert({% trans %}'The form is inconsistent.'{% endtrans %});
|
||||
else {
|
||||
fetch('/api/user/password/change', {method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({ password_current: cur,
|
||||
password_new1: new1,
|
||||
password_new2: new2}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
document.getElementById('user_password_new1').focus();
|
||||
throw Error({% trans %}'Failure to save your new password. Verify that it matches with the security rules.'{% endtrans %} + ' ['+response.status+']');
|
||||
}
|
||||
user_password_popup();
|
||||
$('#user_password_status').html('{{pwic.emojis.green_check}}');
|
||||
alert({% trans %}'Your password has been changed successfully.'{% endtrans %});
|
||||
})
|
||||
.catch(error => alert(error));
|
||||
}
|
||||
}
|
||||
|
||||
function user_language_set() {
|
||||
fetch('/api/user/language/set', { method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: new URLSearchParams({language: $('#user_language').val()}),
|
||||
credentials: 'same-origin'})
|
||||
.then(response => { if (response.ok) location.reload() });
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user