Изменения документа App

Редактировал(а) A1MTestAdmin 2026/10/17 17:15

От версии 35.1
отредактировано A1MTestAdmin
на 2026/10/17 09:11
Изменить комментарий: К данной версии нет комментариев
К версии 38.1
отредактировано A1MTestAdmin
на 2026/10/17 17:15
Изменить комментарий: К данной версии нет комментариев

Сводка

Подробности

Свойства страницы
Название
... ... @@ -1,1 +1,1 @@
1 -A1M
1 +App
Содержимое
... ... @@ -1,6 +1,19 @@
1 1  {{velocity}}
2 -#set($discard = $xwiki.ssx.use('A1M.Style'))
3 -#set($discard = $xwiki.jsx.use('A1M.Style'))
2 +#set($discard = $xwiki.ssx.use('A1M.App'))
3 +#set($discard = $xwiki.jsx.use('A1M.App'))
4 +## Keep the existing protected workflow renderer and replace its legacy overview slot.
5 +#set($rendered = $xwiki.getDocument('A1M.Renderer').getRenderedContent())
6 +#set($legacyPanel = '<section class="panel"><div class="panel-head">01–03 · Основополагающие направления</div>')
7 +#set($start = $rendered.indexOf($legacyPanel))
8 +#if($start >= 0)
9 + #set($end = $rendered.indexOf('</section>', $start) + 10)
10 + #set($before = $rendered.substring(0, $start))
11 + #set($after = $rendered.substring($end))
12 + #set($panel = $xwiki.getDocument('A1M.FoundationPanel').getRenderedContent())
13 + #set($rendered = $before + $panel + $after)
14 +#end
15 +{{html clean="false" wiki="false"}}
16 +$rendered
17 +{{/html}}
4 4  {{/velocity}}
5 5  
6 -{{a1m/}}
XWiki.JavaScriptExtension[0]
name
... ... @@ -1,0 +1,1 @@
1 +A1M interface 1.0.1
code
... ... @@ -1,0 +1,76 @@
1 +/* A1M native JavaScript skin extension. No requests, storage or application data cache. */
2 +(() => {
3 + 'use strict';
4 + function enhance() {
5 + const shell = document.querySelector('.a1m-shell');
6 + if (!shell || shell.dataset.interfaceVersion === '1.0.1') return;
7 + shell.dataset.interfaceVersion = '1.0.1';
8 + const labels = {
9 + priority: 'По приоритету', title: 'По названию', updated: 'По дате изменения',
10 + relevance: 'По релевантности', asc: 'По возрастанию', desc: 'По убыванию'
11 + };
12 + shell.querySelectorAll('select[name=sort] option,select[name=direction] option').forEach(option => {
13 + if (labels[option.value]) option.textContent = labels[option.value];
14 + });
15 + const current = new URL(window.location.href);
16 + const section = current.searchParams.get('section') || '';
17 + shell.querySelectorAll('.side nav a').forEach(link => {
18 + const destination = new URL(link.href, window.location.href);
19 + if (destination.pathname === current.pathname && (destination.searchParams.get('section') || '') === section) {
20 + link.setAttribute('aria-current', 'page');
21 + }
22 + });
23 + // Every option was already filtered by server-side permissions. Only replace its control.
24 + const select = shell.querySelector('.filters select[name=theme][multiple]');
25 + if (select) {
26 + const originalLabel = select.closest('label');
27 + const fieldset = document.createElement('fieldset');
28 + fieldset.className = 'theme-options';
29 + const legend = document.createElement('legend');
30 + legend.textContent = 'Тематика · можно выбрать несколько';
31 + fieldset.append(legend);
32 + select.hidden = true;
33 + select.setAttribute('aria-hidden', 'true');
34 + select.tabIndex = -1;
35 + const checkboxes = [];
36 + const options = Array.from(select.options);
37 + for (const option of options.filter(item => item.value)) {
38 + const label = document.createElement('label');
39 + const checkbox = document.createElement('input');
40 + checkbox.type = 'checkbox';
41 + checkbox.checked = option.selected;
42 + checkbox.addEventListener('change', () => {
43 + option.selected = checkbox.checked;
44 + const empty = options.find(item => !item.value);
45 + if (empty) empty.selected = !checkboxes.some(item => item.checked);
46 + });
47 + checkboxes.push(checkbox);
48 + label.append(checkbox, document.createTextNode(option.textContent));
49 + fieldset.append(label);
50 + }
51 + const reset = document.createElement('button');
52 + reset.type = 'button';
53 + reset.textContent = 'Все темы';
54 + reset.addEventListener('click', () => {
55 + options.forEach(option => { option.selected = !option.value; });
56 + checkboxes.forEach(checkbox => { checkbox.checked = false; });
57 + });
58 + fieldset.append(reset, select);
59 + originalLabel.replaceWith(fieldset);
60 + }
61 + shell.querySelectorAll('.panel-head').forEach(header => {
62 + header.setAttribute('role', 'heading');
63 + header.setAttribute('aria-level', '2');
64 + });
65 + // Keep the intended destination even when a login starts directly from a record.
66 + const login = shell.querySelector('a[href*="/bin/login/"]');
67 + if (login) {
68 + const target = new URL(login.href, window.location.href);
69 + target.searchParams.set('xredirect', current.pathname + current.search);
70 + login.href = target.pathname + target.search;
71 + }
72 + }
73 + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', enhance, { once: true });
74 + else enhance();
75 +})();
76 +
use
... ... @@ -1,0 +1,1 @@
1 +onDemand
parse
... ... @@ -1,0 +1,1 @@
1 +Нет
cache
... ... @@ -1,0 +1,1 @@
1 +default