WIP: Vendoo 1.44.0 – UX Foundation & Guided Workspaces #29

Draft
Masterluke77 wants to merge 284 commits from release/1.44.0-ux-foundation-production-update-v1 into main
Showing only changes of commit 9100e018e2 - Show all commits
+210
View File
@@ -0,0 +1,210 @@
(() => {
'use strict';
const root = document.documentElement;
if (root.dataset.uxSafeActionAdaptersReady === '1') return;
root.dataset.uxSafeActionAdaptersReady = '1';
let lastArticleRow = null;
let lastMediaPreview = null;
const usable = element => Boolean(element
&& element.isConnected !== false
&& !element.hidden
&& !element.disabled
&& element.getAttribute?.('aria-disabled') !== 'true');
function sectionVisible(id) {
const section = document.getElementById(id);
if (!section || section.hidden || section.classList?.contains('hidden') || section.getAttribute?.('aria-hidden') === 'true') return false;
const style = typeof window.getComputedStyle === 'function' ? window.getComputedStyle(section) : null;
return !style || (style.display !== 'none' && style.visibility !== 'hidden');
}
const find = selector => {
const element = document.querySelector(selector);
return usable(element) ? element : null;
};
const click = selector => {
const element = find(selector);
if (!element || typeof element.click !== 'function') return false;
element.click();
return true;
};
function currentArticleRow() {
if (usable(lastArticleRow)) return lastArticleRow;
const row = document.querySelector('#history-list .history-row input[type="checkbox"]:checked')?.closest?.('.history-row');
return usable(row) ? row : null;
}
function currentMediaPreview() {
if (usable(lastMediaPreview)) return lastMediaPreview;
const preview = document.querySelector('#media-grid .media-card input[type="checkbox"]:checked')
?.closest?.('.media-card')?.querySelector?.('[data-media-preview]');
return usable(preview) ? preview : null;
}
function trackContext(event) {
const row = event.target?.closest?.('#history-list .history-row');
if (row) lastArticleRow = row;
const preview = event.target?.closest?.('[data-media-preview]');
if (preview) lastMediaPreview = preview;
}
document.addEventListener('focusin', trackContext, true);
document.addEventListener('pointerdown', trackContext, true);
function adapter({ id, title, description, icon, group, aliases = [], keywords = [], visible, enabled, handler }) {
return {
id,
title,
description,
icon,
group,
aliases,
keywords,
surfaces: ['command-palette'],
danger: 'none',
visible,
enabled,
handler,
};
}
function registerAdapters() {
const actions = window.VendooActions;
if (!actions || root.dataset.uxSafeActionAdaptersRegistered === '1') return false;
const moduleVisible = () => sectionVisible('admin-modules-panel');
const articleVisible = () => sectionVisible('history');
const mediaVisible = () => sectionVisible('media-library');
actions.registerMany([
adapter({
id: 'workspace:modules:refresh',
title: 'Module neu laden',
description: 'Die vorhandene Modulübersicht mit ihrem bestehenden Refresh-Handler aktualisieren.',
icon: '↻',
group: 'Module & Extensions',
aliases: ['Module aktualisieren'],
keywords: ['module', 'refresh', 'neu laden'],
visible: moduleVisible,
enabled: () => Boolean(find('#module-manager-refresh')),
handler: () => click('#module-manager-refresh'),
}),
adapter({
id: 'workspace:modules:filter-all',
title: 'Alle Module anzeigen',
description: 'Den vorhandenen Modulfilter auf alle Einträge setzen.',
icon: '◫',
group: 'Module & Extensions',
keywords: ['module', 'filter', 'alle'],
visible: moduleVisible,
enabled: () => Boolean(find('[data-ux-module-group="modules"][data-ux-module-filter="all"]')),
handler: () => click('[data-ux-module-group="modules"][data-ux-module-filter="all"]'),
}),
adapter({
id: 'workspace:modules:filter-problems',
title: 'Module mit Problemen anzeigen',
description: 'Den vorhandenen Modulfilter auf fehlerhafte oder ungültige Module setzen.',
icon: '!',
group: 'Module & Extensions',
aliases: ['Problematische Module', 'Modulfehler'],
keywords: ['module', 'probleme', 'fehler'],
visible: moduleVisible,
enabled: () => Boolean(find('[data-ux-module-group="modules"][data-ux-module-filter="problems"]')),
handler: () => click('[data-ux-module-group="modules"][data-ux-module-filter="problems"]'),
}),
adapter({
id: 'workspace:articles:open-current',
title: 'Aktuellen Artikel öffnen',
description: 'Den zuletzt fokussierten oder ausgewählten Artikel mit dem bestehenden Handler öffnen.',
icon: '↗',
group: 'Artikel',
aliases: ['Artikel öffnen', 'Ausgewählten Artikel öffnen'],
keywords: ['artikel', 'öffnen', 'auswahl'],
visible: articleVisible,
enabled: () => Boolean(currentArticleRow()?.querySelector?.('.history-article-title')),
handler: () => {
const title = currentArticleRow()?.querySelector?.('.history-article-title');
if (!usable(title) || typeof title.click !== 'function') return false;
title.click();
return true;
},
}),
adapter({
id: 'workspace:articles:view-cards',
title: 'Artikel als Karten anzeigen',
description: 'Die bestehende Kartenansicht der Artikelübersicht aktivieren.',
icon: '▦',
group: 'Artikel',
aliases: ['Kartenansicht'],
keywords: ['artikel', 'karten', 'ansicht'],
visible: articleVisible,
enabled: () => Boolean(find('[data-article-view-choice="cards"]')),
handler: () => click('[data-article-view-choice="cards"]'),
}),
adapter({
id: 'workspace:articles:view-list',
title: 'Artikel als Liste anzeigen',
description: 'Die bestehende Listenansicht der Artikelübersicht aktivieren.',
icon: '☷',
group: 'Artikel',
aliases: ['Listenansicht'],
keywords: ['artikel', 'liste', 'ansicht'],
visible: articleVisible,
enabled: () => Boolean(find('[data-article-view-choice="list"]')),
handler: () => click('[data-article-view-choice="list"]'),
}),
adapter({
id: 'workspace:media:open-current-preview',
title: 'Aktuelles Bild groß öffnen',
description: 'Das zuletzt fokussierte oder ausgewählte Bild mit der bestehenden Vorschau öffnen.',
icon: '⌕',
group: 'Medien',
aliases: ['Bildvorschau öffnen', 'Bild groß anzeigen'],
keywords: ['bild', 'medien', 'vorschau', 'lightbox'],
visible: mediaVisible,
enabled: () => Boolean(currentMediaPreview()),
handler: () => {
const preview = currentMediaPreview();
if (!preview || typeof preview.click !== 'function') return false;
preview.click();
return true;
},
}),
adapter({
id: 'workspace:media:density-comfortable',
title: 'Galerie normal anzeigen',
description: 'Die bestehende normale Kartengröße der Medienbibliothek aktivieren.',
icon: '▦',
group: 'Medien',
aliases: ['Mittlere Bildkarten'],
keywords: ['medien', 'galerie', 'normal', 'dichte'],
visible: mediaVisible,
enabled: () => Boolean(find('[data-media-density-option="comfortable"]')),
handler: () => click('[data-media-density-option="comfortable"]'),
}),
adapter({
id: 'workspace:media:reset-filters',
title: 'Medienfilter zurücksetzen',
description: 'Den vorhandenen Filter-Reset der Medienbibliothek ausführen.',
icon: '×',
group: 'Medien',
keywords: ['medien', 'filter', 'zurücksetzen'],
visible: mediaVisible,
enabled: () => Boolean(find('.ux-media-filter-reset')),
handler: () => click('.ux-media-filter-reset'),
}),
]);
root.dataset.uxSafeActionAdaptersRegistered = '1';
actions.refresh();
window.dispatchEvent(new CustomEvent('vendoo:safe-action-adapters-ready', { detail: { count: 9 } }));
return true;
}
if (!registerAdapters()) window.addEventListener('vendoo:actions-ready', registerAdapters, { once: true });
})();