adsd
This commit is contained in:
@@ -10,7 +10,7 @@ return [
|
|||||||
'zone' => 'sidebar',
|
'zone' => 'sidebar',
|
||||||
'default_enabled' => true,
|
'default_enabled' => true,
|
||||||
'supports_public_home' => true,
|
'supports_public_home' => true,
|
||||||
'summary' => 'Startet die persoenlichen Desktop-Einstellungen fuer Skin, Apps, Widgets und Benutzerdaten.',
|
'summary' => 'Startet die persoenlichen Desktop-Einstellungen fuer Skin, Apps, Infobereich und Benutzerdaten.',
|
||||||
'content' => 'Oeffnet den zentralen Setup-Bereich mit linker Navigation und lokaler Persistenz pro Benutzer.',
|
'content' => 'Oeffnet den zentralen Setup-Bereich mit linker Navigation und lokaler Persistenz pro Benutzer.',
|
||||||
'launch_app_id' => 'user-self-management',
|
'launch_app_id' => 'user-self-management',
|
||||||
'action_label' => 'Setup oeffnen',
|
'action_label' => 'Setup oeffnen',
|
||||||
@@ -53,6 +53,6 @@ return [
|
|||||||
'default_enabled' => false,
|
'default_enabled' => false,
|
||||||
'supports_public_home' => false,
|
'supports_public_home' => false,
|
||||||
'summary' => 'Platz fuer persoenliche Hinweise und Notizen je Workspace.',
|
'summary' => 'Platz fuer persoenliche Hinweise und Notizen je Workspace.',
|
||||||
'content' => 'Dieses Widget ist vorbereitet, aber standardmaessig noch nicht eingeblendet.',
|
'content' => 'Dieser Bereich ist vorbereitet, aber standardmaessig noch nicht eingeblendet.',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ $renderStartIcon = static function (array $profile): string {
|
|||||||
<div id="start-menu-actions"></div>
|
<div id="start-menu-actions"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="start-menu-block">
|
<div class="start-menu-block">
|
||||||
<p class="eyebrow">Widgets</p>
|
<p class="eyebrow">Infobereich</p>
|
||||||
<div id="start-menu-widgets"></div>
|
<div id="start-menu-widgets"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -132,13 +132,18 @@ $renderStartIcon = static function (array $profile): string {
|
|||||||
<div class="taskbar-apps" id="taskbar-apps"></div>
|
<div class="taskbar-apps" id="taskbar-apps"></div>
|
||||||
<div class="tray">
|
<div class="tray">
|
||||||
<?php foreach ($desktopPayload['tray'] as $trayItem): ?>
|
<?php foreach ($desktopPayload['tray'] as $trayItem): ?>
|
||||||
<span class="tray-pill" data-tray-id="<?= htmlspecialchars((string) $trayItem['id'], ENT_QUOTES) ?>"><?= htmlspecialchars($trayItem['label'], ENT_QUOTES) ?></span>
|
<button class="tray-pill tray-pill-button" type="button" data-tray-id="<?= htmlspecialchars((string) $trayItem['id'], ENT_QUOTES) ?>"><?= htmlspecialchars($trayItem['label'], ENT_QUOTES) ?></button>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php if (($desktopPayload['session']['authenticated'] ?? false) === true && !empty($desktopPayload['session']['logout_url'])): ?>
|
|
||||||
<a class="tray-action" href="<?= htmlspecialchars((string) $desktopPayload['session']['logout_url'], ENT_QUOTES) ?>">Logout</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
<time id="clock"></time>
|
<time id="clock"></time>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tray-menu" id="tray-account-menu" hidden>
|
||||||
|
<button class="tray-menu-entry" type="button" data-account-action="settings">Einstellungen</button>
|
||||||
|
<?php if (($desktopPayload['session']['authenticated'] ?? false) === true && !empty($desktopPayload['session']['logout_url'])): ?>
|
||||||
|
<a class="tray-menu-entry" data-account-action="logout" href="<?= htmlspecialchars((string) $desktopPayload['session']['logout_url'], ENT_QUOTES) ?>">Logout</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<button class="tray-menu-entry" type="button" data-account-action="login">Login</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
{ id: 'desktop', label: 'Desktop Type' },
|
{ id: 'desktop', label: 'Desktop Type' },
|
||||||
{ id: 'profile', label: 'Benutzerdaten' },
|
{ id: 'profile', label: 'Benutzerdaten' },
|
||||||
{ id: 'apps', label: 'App-Installation' },
|
{ id: 'apps', label: 'App-Installation' },
|
||||||
{ id: 'widgets', label: 'Widget-Installation' },
|
{ id: 'widgets', label: 'Infobereich' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const escapeHtml = (value) => String(value)
|
const escapeHtml = (value) => String(value)
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
return 'Bestimmt, welche Desktop-Apps fuer diesen Benutzer sichtbar bleiben.';
|
return 'Bestimmt, welche Desktop-Apps fuer diesen Benutzer sichtbar bleiben.';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'Steuert, welche Widgets in der rechten Leiste des Desktops aktiv sind.';
|
return 'Steuert, welche Elemente im rechten Infobereich des Desktops aktiv sind.';
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSkinChoices = (state) => state.bootstrap.options.skins.map((skin) => {
|
const renderSkinChoices = (state) => state.bootstrap.options.skins.map((skin) => {
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
<span class="usm-item-main">
|
<span class="usm-item-main">
|
||||||
<strong>${escapeHtml(widget.title)}</strong>
|
<strong>${escapeHtml(widget.title)}</strong>
|
||||||
<p>${escapeHtml(widget.summary || '')}</p>
|
<p>${escapeHtml(widget.summary || '')}</p>
|
||||||
<span class="usm-item-meta">${widget.default_enabled ? 'Standard-Widget' : 'Optionales Widget'}</span>
|
<span class="usm-item-meta">${widget.default_enabled ? 'Standardbereich' : 'Optionaler Bereich'}</span>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
`;
|
`;
|
||||||
@@ -177,9 +177,9 @@
|
|||||||
|
|
||||||
return `
|
return `
|
||||||
<section class="usm-card">
|
<section class="usm-card">
|
||||||
<p class="usm-kicker">Widget-Auswahl</p>
|
<p class="usm-kicker">Infobereich</p>
|
||||||
<h2>Aktive Widget-Leiste</h2>
|
<h2>Rechter Desktopbereich</h2>
|
||||||
<p class="usm-copy">Widgets bleiben Teil der Desktop-Mechanik und werden hier nur benutzerbezogen ein- oder ausgeblendet.</p>
|
<p class="usm-copy">Diese Inhalte liegen aktuell im rechten Infobereich des Desktops und werden hier benutzerbezogen ein- oder ausgeblendet.</p>
|
||||||
<div class="usm-list">
|
<div class="usm-list">
|
||||||
${renderWidgetItems(state)}
|
${renderWidgetItems(state)}
|
||||||
</div>
|
</div>
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
<div class="usm-brand">
|
<div class="usm-brand">
|
||||||
<p class="usm-kicker">Setup</p>
|
<p class="usm-kicker">Setup</p>
|
||||||
<h1>User Self Management</h1>
|
<h1>User Self Management</h1>
|
||||||
<p>Ein gemeinsamer Setup-Bereich fuer Desktop-Typ, Benutzerdaten, Apps und Widgets.</p>
|
<p>Ein gemeinsamer Setup-Bereich fuer Desktop-Typ, Benutzerdaten, Apps und den rechten Infobereich.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="usm-nav-list">
|
<div class="usm-nav-list">
|
||||||
${SECTIONS.map((section) => `
|
${SECTIONS.map((section) => `
|
||||||
|
|||||||
@@ -814,27 +814,6 @@ h1 {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tray-skins {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tray-skin-button {
|
|
||||||
border: 0;
|
|
||||||
border-radius: 999px;
|
|
||||||
padding: 8px 10px;
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
|
||||||
color: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tray-skin-button.is-active {
|
|
||||||
background: var(--accent);
|
|
||||||
color: #0f172a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tray-pill {
|
.tray-pill {
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
@@ -842,22 +821,55 @@ h1 {
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tray-action {
|
.tray-pill-button {
|
||||||
display: inline-flex;
|
border: 0;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 8px 12px;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font-size: 13px;
|
font: inherit;
|
||||||
text-decoration: none;
|
cursor: pointer;
|
||||||
transition: background-color 140ms ease, transform 140ms ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tray-action:hover {
|
.tray-pill-button:hover,
|
||||||
|
.tray-pill-button[aria-expanded="true"] {
|
||||||
background: rgba(255, 255, 255, 0.16);
|
background: rgba(255, 255, 255, 0.16);
|
||||||
transform: translateY(-1px);
|
}
|
||||||
|
|
||||||
|
.tray-menu {
|
||||||
|
position: absolute;
|
||||||
|
right: 16px;
|
||||||
|
bottom: calc(100% + 12px);
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
min-width: 220px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 18px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.14);
|
||||||
|
background: rgba(15, 23, 42, 0.94);
|
||||||
|
box-shadow: 0 18px 40px rgba(15, 23, 42, 0.24);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-menu[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-menu-entry {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 40px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: transparent;
|
||||||
|
color: #f8fafc;
|
||||||
|
font: inherit;
|
||||||
|
text-align: left;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tray-menu-entry:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-content p:last-child {
|
.window-content p:last-child {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ if (payloadNode) {
|
|||||||
const startMenuApps = document.getElementById('start-menu-apps');
|
const startMenuApps = document.getElementById('start-menu-apps');
|
||||||
const startMenuWidgets = document.getElementById('start-menu-widgets');
|
const startMenuWidgets = document.getElementById('start-menu-widgets');
|
||||||
const startMenuActions = document.getElementById('start-menu-actions');
|
const startMenuActions = document.getElementById('start-menu-actions');
|
||||||
|
const accountMenu = document.getElementById('tray-account-menu');
|
||||||
const clockNode = document.getElementById('clock');
|
const clockNode = document.getElementById('clock');
|
||||||
const clockTopNode = document.getElementById('clock-top');
|
const clockTopNode = document.getElementById('clock-top');
|
||||||
const windows = new Map();
|
const windows = new Map();
|
||||||
@@ -179,6 +180,17 @@ if (payloadNode) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setAccountMenuOpen = (isOpen) => {
|
||||||
|
const accountButton = document.querySelector('.tray-pill[data-tray-id="account"]');
|
||||||
|
|
||||||
|
if (!(accountMenu instanceof HTMLElement) || !(accountButton instanceof HTMLElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
accountMenu.hidden = !isOpen;
|
||||||
|
accountButton.setAttribute('aria-expanded', String(isOpen));
|
||||||
|
};
|
||||||
|
|
||||||
const findAppById = (appId) => payload.apps.find((app) => app.app_id === appId) || null;
|
const findAppById = (appId) => payload.apps.find((app) => app.app_id === appId) || null;
|
||||||
|
|
||||||
const dispatchUserSettingsUpdate = (detail) => {
|
const dispatchUserSettingsUpdate = (detail) => {
|
||||||
@@ -614,6 +626,14 @@ if (payloadNode) {
|
|||||||
setStartMenuOpen(false);
|
setStartMenuOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openAccountSettings = () => {
|
||||||
|
const app = findAppById('user-self-management');
|
||||||
|
if (app) {
|
||||||
|
openApp(app);
|
||||||
|
}
|
||||||
|
setAccountMenuOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
const applyWindowLayout = (record) => {
|
const applyWindowLayout = (record) => {
|
||||||
const { x, y, width, height } = record.layout;
|
const { x, y, width, height } = record.layout;
|
||||||
record.node.style.left = `${x}px`;
|
record.node.style.left = `${x}px`;
|
||||||
@@ -1275,11 +1295,16 @@ if (payloadNode) {
|
|||||||
if (!(event.target instanceof Element) || !event.target.closest('.desktop-context-menu')) {
|
if (!(event.target instanceof Element) || !event.target.closest('.desktop-context-menu')) {
|
||||||
closeDesktopContextMenu();
|
closeDesktopContextMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(event.target instanceof Element) || !event.target.closest('.tray-pill[data-tray-id="account"], #tray-account-menu')) {
|
||||||
|
setAccountMenuOpen(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('keydown', (event) => {
|
document.addEventListener('keydown', (event) => {
|
||||||
if (event.key === 'Escape') {
|
if (event.key === 'Escape') {
|
||||||
closeDesktopContextMenu();
|
closeDesktopContextMenu();
|
||||||
|
setAccountMenuOpen(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1291,6 +1316,41 @@ if (payloadNode) {
|
|||||||
|
|
||||||
const isClosed = startMenu.hasAttribute('hidden');
|
const isClosed = startMenu.hasAttribute('hidden');
|
||||||
setStartMenuOpen(isClosed);
|
setStartMenuOpen(isClosed);
|
||||||
|
setAccountMenuOpen(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector('.tray-pill[data-tray-id="account"]')?.addEventListener('click', () => {
|
||||||
|
if (!(accountMenu instanceof HTMLElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStartMenuOpen(false);
|
||||||
|
setAccountMenuOpen(accountMenu.hidden);
|
||||||
|
});
|
||||||
|
|
||||||
|
accountMenu?.addEventListener('click', (event) => {
|
||||||
|
const target = event.target instanceof Element ? event.target.closest('[data-account-action]') : null;
|
||||||
|
|
||||||
|
if (!target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const action = target.getAttribute('data-account-action');
|
||||||
|
|
||||||
|
if (action === 'settings') {
|
||||||
|
event.preventDefault();
|
||||||
|
openAccountSettings();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'login') {
|
||||||
|
event.preventDefault();
|
||||||
|
const loginApp = findAppById('desktop-login');
|
||||||
|
if (loginApp) {
|
||||||
|
openApp(loginApp);
|
||||||
|
}
|
||||||
|
setAccountMenuOpen(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('desktop:user-settings-updated', (event) => {
|
window.addEventListener('desktop:user-settings-updated', (event) => {
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ final class DesktopState
|
|||||||
public static function trayItems(): array
|
public static function trayItems(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
['id' => 'network', 'label' => 'Netzwerk'],
|
|
||||||
['id' => 'widgets', 'label' => 'Widgets'],
|
|
||||||
['id' => 'account', 'label' => 'Gast'],
|
['id' => 'account', 'label' => 'Gast'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -57,8 +55,8 @@ final class DesktopState
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'action_id' => 'toggle-all-widgets',
|
'action_id' => 'toggle-all-widgets',
|
||||||
'label' => 'Widgets umschalten',
|
'label' => 'Infobereich umschalten',
|
||||||
'description' => 'Blendet alle registrierten Widgets ein oder aus.',
|
'description' => 'Blendet den rechten Infobereich des Desktops ein oder aus.',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user