Initial commit: IT Nexus Web-App
This commit is contained in:
1601
frontend/public/DOKUMENTATION.md
Normal file
1601
frontend/public/DOKUMENTATION.md
Normal file
File diff suppressed because it is too large
Load Diff
99
frontend/public/addin/manifest.xml
Normal file
99
frontend/public/addin/manifest.xml
Normal file
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<OfficeApp
|
||||
xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
|
||||
xmlns:mailappor="http://schemas.microsoft.com/office/mailappversionoverrides/1.0"
|
||||
xsi:type="MailApp">
|
||||
|
||||
<Id>c4e2a1b7-3f8d-4a92-b651-7e0d9f3a2c84</Id>
|
||||
<Version>1.0.2</Version>
|
||||
<ProviderName>Cereda Systems GmbH</ProviderName>
|
||||
<DefaultLocale>en-US</DefaultLocale>
|
||||
<DisplayName DefaultValue="IT Nexus Ticket"/>
|
||||
<Description DefaultValue="Create a support ticket in IT Nexus directly from an email."/>
|
||||
<IconUrl DefaultValue="https://it-nexus.cereda-systems.de/cereda-logo.png"/>
|
||||
<HighResolutionIconUrl DefaultValue="https://it-nexus.cereda-systems.de/cereda-logo.png"/>
|
||||
<SupportUrl DefaultValue="https://it-nexus.cereda-systems.de"/>
|
||||
<AppDomains>
|
||||
<AppDomain>https://it-nexus.cereda-systems.de</AppDomain>
|
||||
<AppDomain>https://login.microsoftonline.com</AppDomain>
|
||||
<AppDomain>https://login.microsoft.com</AppDomain>
|
||||
<AppDomain>https://microsoftonline.com</AppDomain>
|
||||
</AppDomains>
|
||||
<Hosts>
|
||||
<Host Name="Mailbox"/>
|
||||
</Hosts>
|
||||
<Requirements>
|
||||
<Sets>
|
||||
<Set Name="Mailbox" MinVersion="1.1"/>
|
||||
</Sets>
|
||||
</Requirements>
|
||||
<FormSettings>
|
||||
<Form xsi:type="ItemRead">
|
||||
<DesktopSettings>
|
||||
<SourceLocation DefaultValue="https://it-nexus.cereda-systems.de/addin/taskpane.html"/>
|
||||
<RequestedHeight>450</RequestedHeight>
|
||||
</DesktopSettings>
|
||||
</Form>
|
||||
</FormSettings>
|
||||
<Permissions>ReadItem</Permissions>
|
||||
<Rule xsi:type="RuleCollection" Mode="Or">
|
||||
<Rule xsi:type="ItemIs" ItemType="Message" FormType="Read"/>
|
||||
</Rule>
|
||||
<DisableEntityHighlighting>false</DisableEntityHighlighting>
|
||||
|
||||
<VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0">
|
||||
<Requirements>
|
||||
<bt:Sets DefaultMinVersion="1.3">
|
||||
<bt:Set Name="Mailbox"/>
|
||||
</bt:Sets>
|
||||
</Requirements>
|
||||
<Hosts>
|
||||
<Host xsi:type="MailHost">
|
||||
<DesktopFormFactor>
|
||||
<ExtensionPoint xsi:type="MessageReadCommandSurface">
|
||||
<OfficeTab id="TabDefault">
|
||||
<Group id="msgReadGroup">
|
||||
<Label resid="GroupLabel"/>
|
||||
<Control xsi:type="Button" id="msgReadOpenPaneButton">
|
||||
<Label resid="TaskpaneButton.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="TaskpaneButton.Label"/>
|
||||
<Description resid="TaskpaneButton.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<SourceLocation resid="Taskpane.Url"/>
|
||||
</Action>
|
||||
</Control>
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
</DesktopFormFactor>
|
||||
</Host>
|
||||
</Hosts>
|
||||
<Resources>
|
||||
<bt:Images>
|
||||
<bt:Image id="Icon.16x16" DefaultValue="https://it-nexus.cereda-systems.de/cereda-logo.png"/>
|
||||
<bt:Image id="Icon.32x32" DefaultValue="https://it-nexus.cereda-systems.de/cereda-logo.png"/>
|
||||
<bt:Image id="Icon.80x80" DefaultValue="https://it-nexus.cereda-systems.de/cereda-logo.png"/>
|
||||
</bt:Images>
|
||||
<bt:Urls>
|
||||
<bt:Url id="Taskpane.Url" DefaultValue="https://it-nexus.cereda-systems.de/addin/taskpane.html"/>
|
||||
</bt:Urls>
|
||||
<bt:ShortStrings>
|
||||
<bt:String id="GroupLabel" DefaultValue="IT Nexus"/>
|
||||
<bt:String id="TaskpaneButton.Label" DefaultValue="Create Ticket"/>
|
||||
</bt:ShortStrings>
|
||||
<bt:LongStrings>
|
||||
<bt:String id="TaskpaneButton.Tooltip" DefaultValue="Create an IT Nexus support ticket from this email"/>
|
||||
</bt:LongStrings>
|
||||
</Resources>
|
||||
</VersionOverrides>
|
||||
|
||||
</OfficeApp>
|
||||
246
frontend/public/addin/taskpane.html
Normal file
246
frontend/public/addin/taskpane.html
Normal file
@@ -0,0 +1,246 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>IT Nexus – Ticket erstellen</title>
|
||||
<script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: 'Segoe UI', sans-serif; font-size: 13px; background: #1a1a2e; color: #e0e0e0; min-height: 100vh; }
|
||||
.container { padding: 16px; }
|
||||
.logo { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; font-size: 15px; font-weight: 600; color: #7c9ef8; }
|
||||
label { display: block; font-size: 11px; color: #9aa3b2; margin-bottom: 4px; margin-top: 10px; text-transform: uppercase; letter-spacing: 0.5px; }
|
||||
input, textarea, select { width: 100%; padding: 8px 10px; background: #252540; border: 1px solid #3a3a5c; border-radius: 6px; color: #e0e0e0; font-size: 13px; font-family: inherit; outline: none; transition: border-color 0.2s; }
|
||||
input:focus, textarea:focus, select:focus { border-color: #7c9ef8; }
|
||||
textarea { resize: vertical; min-height: 80px; }
|
||||
select option { background: #252540; }
|
||||
.btn { display: block; width: 100%; padding: 10px; margin-top: 14px; background: #7c9ef8; color: #fff; border: none; border-radius: 6px; font-size: 14px; font-weight: 600; cursor: pointer; transition: background 0.2s; }
|
||||
.btn:hover { background: #5b7ef5; }
|
||||
.btn:disabled { background: #3a3a5c; cursor: not-allowed; }
|
||||
.btn-secondary { background: transparent; border: 1px solid #3a3a5c; color: #9aa3b2; margin-top: 8px; }
|
||||
.btn-secondary:hover { border-color: #7c9ef8; color: #7c9ef8; }
|
||||
.btn-ms { background: #2f6baf; display: flex; align-items: center; justify-content: center; gap: 8px; }
|
||||
.btn-ms:hover { background: #1e5a9e; }
|
||||
.alert { padding: 10px 12px; border-radius: 6px; margin-top: 12px; font-size: 12px; }
|
||||
.alert-success { background: #1a3a2a; border: 1px solid #2a6a4a; color: #5edb9a; }
|
||||
.alert-error { background: #3a1a1a; border: 1px solid #6a2a2a; color: #f08080; }
|
||||
.alert-info { background: #1a2a3a; border: 1px solid #2a4a6a; color: #7cb8f8; }
|
||||
#login-section, #form-section, #success-section { display: none; }
|
||||
.loading { text-align: center; padding: 30px; color: #9aa3b2; }
|
||||
.ticket-num { font-size: 20px; font-weight: 700; color: #7c9ef8; text-align: center; margin: 10px 0 4px; }
|
||||
.ticket-sub { text-align: center; font-size: 12px; color: #9aa3b2; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="logo">🎫 IT Nexus</div>
|
||||
|
||||
<!-- Login -->
|
||||
<div id="login-section">
|
||||
<div class="alert alert-info" style="margin-bottom:12px;">Mit Microsoft-Konto anmelden</div>
|
||||
<button class="btn btn-ms" id="btn-ms-login">
|
||||
<svg width="16" height="16" viewBox="0 0 21 21" fill="none"><rect x="1" y="1" width="9" height="9" fill="#f25022"/><rect x="11" y="1" width="9" height="9" fill="#7fba00"/><rect x="1" y="11" width="9" height="9" fill="#00a4ef"/><rect x="11" y="11" width="9" height="9" fill="#ffb900"/></svg>
|
||||
Mit Microsoft anmelden
|
||||
</button>
|
||||
<div id="login-error"></div>
|
||||
</div>
|
||||
|
||||
<!-- Ticket-Formular -->
|
||||
<div id="form-section">
|
||||
<div id="user-info" style="font-size:11px;color:#9aa3b2;margin-bottom:8px;"></div>
|
||||
<label>Titel</label>
|
||||
<input type="text" id="f-title" maxlength="200" />
|
||||
<label>Beschreibung</label>
|
||||
<textarea id="f-desc" rows="5"></textarea>
|
||||
<label>Kategorie</label>
|
||||
<select id="f-category">
|
||||
<option value="Allgemein">Allgemein</option>
|
||||
<option value="Hardware">Hardware</option>
|
||||
<option value="Software">Software</option>
|
||||
<option value="Netzwerk">Netzwerk</option>
|
||||
<option value="Zugang & Berechtigungen">Zugang & Berechtigungen</option>
|
||||
<option value="E-Mail">E-Mail</option>
|
||||
<option value="Drucker">Drucker</option>
|
||||
<option value="Sonstiges">Sonstiges</option>
|
||||
</select>
|
||||
<label>Priorität</label>
|
||||
<select id="f-priority">
|
||||
<option value="niedrig">Niedrig</option>
|
||||
<option value="mittel" selected>Mittel</option>
|
||||
<option value="hoch">Hoch</option>
|
||||
<option value="kritisch">Kritisch</option>
|
||||
</select>
|
||||
<button class="btn" id="btn-submit">Ticket erstellen</button>
|
||||
<button class="btn btn-secondary" id="btn-logout">Abmelden</button>
|
||||
<div id="form-error"></div>
|
||||
</div>
|
||||
|
||||
<!-- Erfolg -->
|
||||
<div id="success-section">
|
||||
<div class="alert alert-success" style="text-align:center;padding:20px;">
|
||||
<div style="font-size:28px;margin-bottom:8px;">✅</div>
|
||||
<div style="font-weight:600;margin-bottom:4px;">Ticket erstellt!</div>
|
||||
<div class="ticket-num" id="s-number"></div>
|
||||
<div class="ticket-sub" id="s-title"></div>
|
||||
</div>
|
||||
<button class="btn btn-secondary" id="btn-new">Weiteres Ticket erstellen</button>
|
||||
</div>
|
||||
|
||||
<div id="loading-section" class="loading">⏳ Wird geladen…</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let token = localStorage.getItem('it_nexus_addin_token') || null;
|
||||
let currentUser = JSON.parse(localStorage.getItem('it_nexus_addin_user') || 'null');
|
||||
|
||||
function show(id) {
|
||||
['login-section','form-section','success-section','loading-section'].forEach(s => {
|
||||
document.getElementById(s).style.display = s === id ? 'block' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
function setError(elId, msg) {
|
||||
document.getElementById(elId).innerHTML = msg ? `<div class="alert alert-error">${msg}</div>` : '';
|
||||
}
|
||||
|
||||
// ── Microsoft SSO Login (Polling-basiert, kein messageParent) ─────────────
|
||||
document.getElementById('btn-ms-login').addEventListener('click', () => {
|
||||
show('loading-section');
|
||||
const sessionId = Date.now().toString(36) + Math.random().toString(36).slice(2);
|
||||
const dialogUrl = 'https://it-nexus.cereda-systems.de/api/auth/microsoft/addin?sessionId=' + sessionId;
|
||||
|
||||
Office.context.ui.displayDialogAsync(
|
||||
dialogUrl,
|
||||
{ height: 60, width: 30, promptBeforeOpen: false },
|
||||
(result) => {
|
||||
if (result.status === Office.AsyncResultStatus.Failed) {
|
||||
show('login-section');
|
||||
setError('login-error', 'Popup konnte nicht geöffnet werden.');
|
||||
return;
|
||||
}
|
||||
const dialog = result.value;
|
||||
let pollInterval = null;
|
||||
|
||||
const handleResult = (data) => {
|
||||
if (pollInterval) clearInterval(pollInterval);
|
||||
try { dialog.close(); } catch(e) {}
|
||||
if (data.error) {
|
||||
show('login-section');
|
||||
const msgs = {
|
||||
user_not_found: 'Kein IT Nexus Konto gefunden.',
|
||||
account_inactive: 'Konto ist deaktiviert.',
|
||||
};
|
||||
setError('login-error', msgs[data.error] || 'Fehler: ' + data.error);
|
||||
return;
|
||||
}
|
||||
token = data.token;
|
||||
currentUser = data.user;
|
||||
localStorage.setItem('it_nexus_addin_token', token);
|
||||
localStorage.setItem('it_nexus_addin_user', JSON.stringify(currentUser));
|
||||
loadEmailAndShowForm();
|
||||
};
|
||||
|
||||
// Poll server every 2 seconds for login result
|
||||
pollInterval = setInterval(async () => {
|
||||
try {
|
||||
const r = await fetch('https://it-nexus.cereda-systems.de/api/auth/microsoft/addin-result/' + sessionId);
|
||||
const data = await r.json();
|
||||
if (!data.pending) handleResult(data);
|
||||
} catch(e) {}
|
||||
}, 2000);
|
||||
|
||||
// Also handle if user manually closes dialog
|
||||
dialog.addEventHandler(Office.EventType.DialogEventReceived, () => {
|
||||
if (pollInterval) clearInterval(pollInterval);
|
||||
show('login-section');
|
||||
});
|
||||
|
||||
// Keep messageParent as fallback
|
||||
dialog.addEventHandler(Office.EventType.DialogMessageReceived, (msg) => {
|
||||
try { handleResult(JSON.parse(msg.message)); } catch(e) {}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// ── Logout ─────────────────────────────────────────────────────────────────
|
||||
document.getElementById('btn-logout').addEventListener('click', () => {
|
||||
token = null; currentUser = null;
|
||||
localStorage.removeItem('it_nexus_addin_token');
|
||||
localStorage.removeItem('it_nexus_addin_user');
|
||||
show('login-section');
|
||||
});
|
||||
|
||||
// ── Ticket erstellen ───────────────────────────────────────────────────────
|
||||
document.getElementById('btn-submit').addEventListener('click', async () => {
|
||||
const title = document.getElementById('f-title').value.trim();
|
||||
if (!title) return setError('form-error', 'Titel ist erforderlich.');
|
||||
document.getElementById('btn-submit').disabled = true;
|
||||
setError('form-error', '');
|
||||
try {
|
||||
const res = await fetch('/api/tickets', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
|
||||
body: JSON.stringify({
|
||||
title,
|
||||
description: document.getElementById('f-desc').value.trim(),
|
||||
category: document.getElementById('f-category').value,
|
||||
priority: document.getElementById('f-priority').value,
|
||||
source: 'email',
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
if (res.status === 401) { token = null; localStorage.removeItem('it_nexus_addin_token'); show('login-section'); return; }
|
||||
throw new Error(data.message || 'Fehler beim Erstellen');
|
||||
}
|
||||
document.getElementById('s-number').textContent = data.data.ticket_number;
|
||||
document.getElementById('s-title').textContent = title;
|
||||
show('success-section');
|
||||
} catch (e) {
|
||||
setError('form-error', e.message);
|
||||
} finally {
|
||||
document.getElementById('btn-submit').disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('btn-new').addEventListener('click', () => loadEmailAndShowForm());
|
||||
|
||||
// ── E-Mail laden ───────────────────────────────────────────────────────────
|
||||
function loadEmailAndShowForm() {
|
||||
show('loading-section');
|
||||
if (currentUser) {
|
||||
document.getElementById('user-info').textContent =
|
||||
`Angemeldet als: ${currentUser.first_name || ''} ${currentUser.last_name || currentUser.username}`.trim();
|
||||
}
|
||||
if (typeof Office !== 'undefined' && Office.context?.mailbox) {
|
||||
const item = Office.context.mailbox.item;
|
||||
document.getElementById('f-title').value = item.subject || '';
|
||||
item.body.getAsync(Office.CoercionType.Text, {}, (r) => {
|
||||
document.getElementById('f-desc').value =
|
||||
r.status === Office.AsyncResultStatus.Succeeded ? r.value.substring(0, 2000).trim() : '';
|
||||
show('form-section');
|
||||
});
|
||||
} else {
|
||||
document.getElementById('f-title').value = '';
|
||||
document.getElementById('f-desc').value = '';
|
||||
show('form-section');
|
||||
}
|
||||
}
|
||||
|
||||
// ── Init ───────────────────────────────────────────────────────────────────
|
||||
Office.onReady(async () => {
|
||||
if (token) {
|
||||
try {
|
||||
const res = await fetch('/api/auth/me', { headers: { Authorization: `Bearer ${token}` } });
|
||||
if (res.ok) { loadEmailAndShowForm(); return; }
|
||||
} catch {}
|
||||
token = null;
|
||||
localStorage.removeItem('it_nexus_addin_token');
|
||||
}
|
||||
show('login-section');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
frontend/public/cereda-logo.png
Normal file
BIN
frontend/public/cereda-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
856
frontend/public/design-preview.html
Normal file
856
frontend/public/design-preview.html
Normal file
@@ -0,0 +1,856 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>IT Nexus — Design Preview (Cereda Systems)</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
/* ================================================================
|
||||
IT NEXUS — CURRENT DESIGN (Cereda Systems GmbH)
|
||||
This is a STATIC MOCKUP for design review purposes only.
|
||||
Technology stack: React + CSS Custom Properties
|
||||
================================================================ */
|
||||
:root {
|
||||
--cereda-primary: #3fa3a3;
|
||||
--cereda-primary-dark: #008487;
|
||||
--bg-primary: #0f172a;
|
||||
--bg-secondary: #1e293b;
|
||||
--bg-tertiary: #334155;
|
||||
--bg-card: #1e293b;
|
||||
--text-primary: #f1f5f9;
|
||||
--text-secondary:#94a3b8;
|
||||
--text-muted: #64748b;
|
||||
--border-color: #334155;
|
||||
--success: #10b981;
|
||||
--danger: #ef4444;
|
||||
--warning: #f59e0b;
|
||||
--info: #3b82f6;
|
||||
--sidebar-width: 220px;
|
||||
--topbar-height: 56px;
|
||||
}
|
||||
|
||||
* { margin:0; padding:0; box-sizing:border-box; }
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
background:
|
||||
radial-gradient(ellipse at 15% 15%, rgba(63,163,163,0.10) 0%, transparent 50%),
|
||||
radial-gradient(ellipse at 85% 80%, rgba(59,130,246,0.09) 0%, transparent 50%),
|
||||
linear-gradient(145deg, #050d1e 0%, #0b1628 40%, #0d1f2d 70%, #060f1c 100%);
|
||||
background-attachment: fixed;
|
||||
color: var(--text-primary);
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── SIDEBAR ── */
|
||||
.sidebar {
|
||||
width: var(--sidebar-width);
|
||||
min-height: 100vh;
|
||||
background: rgba(8,15,30,0.72);
|
||||
backdrop-filter: blur(20px);
|
||||
border-right: 1px solid rgba(255,255,255,0.07);
|
||||
box-shadow: 4px 0 32px rgba(0,0,0,0.5);
|
||||
position: fixed;
|
||||
left:0; top:0; bottom:0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 90;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.sidebar-logo {
|
||||
padding: 16px 20px 12px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
.sidebar-logo img { height: 36px; width: auto; }
|
||||
.sidebar-logo-text {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
letter-spacing: -0.01em;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.sidebar-nav { flex:1; padding: 8px 0; }
|
||||
.sidebar-group { padding: 4px 0; }
|
||||
.sidebar-group + .sidebar-group {
|
||||
border-top: 1px solid var(--border-color);
|
||||
margin-top: 4px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.sidebar-group-label {
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--text-muted);
|
||||
padding: 6px 20px 4px;
|
||||
}
|
||||
.sidebar-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 9px 20px;
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-size: 13.5px;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
.sidebar-link:hover { background: var(--bg-tertiary); color: var(--text-primary); }
|
||||
.sidebar-link.active {
|
||||
color: var(--cereda-primary) !important;
|
||||
background: rgba(63,163,163,0.10) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
.sidebar-link.active::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left:0; top:0; bottom:0;
|
||||
width: 3px;
|
||||
background: var(--cereda-primary);
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
.sidebar-icon { font-size: 16px; width: 20px; text-align: center; flex-shrink:0; }
|
||||
|
||||
/* ── TOPBAR ── */
|
||||
.topbar {
|
||||
position: fixed;
|
||||
top:0; left: var(--sidebar-width); right:0;
|
||||
height: var(--topbar-height);
|
||||
background: rgba(8,15,30,0.65);
|
||||
backdrop-filter: blur(20px);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.07);
|
||||
box-shadow: 0 4px 24px rgba(0,0,0,0.35);
|
||||
z-index: 80;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 0 20px;
|
||||
gap: 12px;
|
||||
}
|
||||
.topbar-btn {
|
||||
display: flex; align-items:center; justify-content:center;
|
||||
width:34px; height:34px;
|
||||
border-radius: 8px;
|
||||
background: var(--bg-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--text-secondary);
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.topbar-badge {
|
||||
position:absolute; top:-4px; right:-4px;
|
||||
background:#ef4444; color:#fff;
|
||||
font-size:10px; font-weight:700;
|
||||
border-radius:10px; min-width:16px; height:16px;
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
padding:0 3px;
|
||||
}
|
||||
.topbar-user {
|
||||
display:flex; align-items:center; gap:8px;
|
||||
padding:6px 12px;
|
||||
border-radius:8px;
|
||||
border: 1px solid var(--border-color);
|
||||
background: var(--bg-primary);
|
||||
font-size:13px; font-weight:500;
|
||||
}
|
||||
.user-avatar {
|
||||
width:26px; height:26px;
|
||||
border-radius:6px;
|
||||
background: linear-gradient(135deg, var(--cereda-primary), var(--cereda-primary-dark));
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
font-size:11px; font-weight:700; color:#fff;
|
||||
}
|
||||
.role-badge {
|
||||
font-size:10px; font-weight:700;
|
||||
background: rgba(63,163,163,0.15);
|
||||
color: var(--cereda-primary);
|
||||
border-radius:4px;
|
||||
padding:2px 6px;
|
||||
text-transform:uppercase;
|
||||
letter-spacing:0.06em;
|
||||
}
|
||||
|
||||
/* ── MAIN LAYOUT ── */
|
||||
.app-main {
|
||||
margin-left: var(--sidebar-width);
|
||||
padding-top: var(--topbar-height);
|
||||
min-height: 100vh;
|
||||
}
|
||||
.page {
|
||||
padding: 28px 28px 40px;
|
||||
max-width: 1400px;
|
||||
}
|
||||
|
||||
/* ── PAGE HEADER ── */
|
||||
.page-header {
|
||||
display:flex; align-items:center; justify-content:space-between;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.page-title { font-size:22px; font-weight:700; letter-spacing:-0.02em; }
|
||||
.page-subtitle { font-size:13px; color:var(--text-muted); margin-top:2px; }
|
||||
|
||||
/* ── STATS GRID ── */
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.stat-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 14px;
|
||||
padding: 18px 20px;
|
||||
display:flex; align-items:center; gap:14px;
|
||||
position:relative; overflow:hidden;
|
||||
}
|
||||
.stat-card::before {
|
||||
content:'';
|
||||
position:absolute; top:0; left:0; right:0;
|
||||
height:2px;
|
||||
}
|
||||
.stat-card.teal::before { background: linear-gradient(90deg, var(--cereda-primary), var(--cereda-primary-dark)); }
|
||||
.stat-card.green::before { background: linear-gradient(90deg, #10b981, #059669); }
|
||||
.stat-card.orange::before{ background: linear-gradient(90deg, #f59e0b, #d97706); }
|
||||
.stat-card.blue::before { background: linear-gradient(90deg, #3b82f6, #2563eb); }
|
||||
.stat-icon {
|
||||
width:44px; height:44px;
|
||||
border-radius:12px;
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
font-size:20px; flex-shrink:0;
|
||||
}
|
||||
.stat-icon.teal { background: rgba(63,163,163,0.15); }
|
||||
.stat-icon.green { background: rgba(16,185,129,0.15); }
|
||||
.stat-icon.orange{ background: rgba(245,158,11,0.15); }
|
||||
.stat-icon.blue { background: rgba(59,130,246,0.15); }
|
||||
.stat-value { font-size:26px; font-weight:700; letter-spacing:-0.02em; line-height:1; }
|
||||
.stat-label { font-size:12px; color:var(--text-muted); margin-top:3px; }
|
||||
.stat-delta { font-size:11px; margin-top:4px; }
|
||||
.delta-up { color:#10b981; }
|
||||
.delta-down { color:#ef4444; }
|
||||
|
||||
/* ── CARD ── */
|
||||
.card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 14px;
|
||||
overflow:hidden;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.card-header {
|
||||
padding:16px 20px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
display:flex; align-items:center; justify-content:space-between;
|
||||
}
|
||||
.card-title { font-size:15px; font-weight:600; letter-spacing:-0.01em; }
|
||||
.card-body { padding:20px; }
|
||||
|
||||
/* ── TABLE ── */
|
||||
table { width:100%; border-collapse:collapse; }
|
||||
thead th {
|
||||
background: rgba(15,23,42,0.5);
|
||||
color: var(--text-muted);
|
||||
font-size:11px; font-weight:600;
|
||||
text-transform:uppercase; letter-spacing:0.06em;
|
||||
padding:10px 16px;
|
||||
text-align:left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
tbody td {
|
||||
padding:12px 16px;
|
||||
font-size:13.5px;
|
||||
border-bottom: 1px solid rgba(51,65,85,0.5);
|
||||
}
|
||||
tbody tr:last-child td { border-bottom:none; }
|
||||
tbody tr:hover { background: rgba(51,65,85,0.3); }
|
||||
|
||||
/* ── BADGES ── */
|
||||
.badge {
|
||||
display:inline-flex; align-items:center; gap:4px;
|
||||
padding:3px 8px;
|
||||
border-radius:6px;
|
||||
font-size:11px; font-weight:600;
|
||||
}
|
||||
.badge-open { background:rgba(59,130,246,0.15); color:#60a5fa; }
|
||||
.badge-pending { background:rgba(245,158,11,0.15); color:#fbbf24; }
|
||||
.badge-done { background:rgba(16,185,129,0.15); color:#34d399; }
|
||||
.badge-high { background:rgba(239,68,68,0.15); color:#f87171; }
|
||||
.badge-medium { background:rgba(245,158,11,0.15); color:#fbbf24; }
|
||||
.badge-low { background:rgba(16,185,129,0.15); color:#34d399; }
|
||||
.badge-teal { background:rgba(63,163,163,0.15); color:var(--cereda-primary); }
|
||||
|
||||
/* ── BUTTONS ── */
|
||||
.btn {
|
||||
display:inline-flex; align-items:center; gap:6px;
|
||||
padding:8px 16px;
|
||||
border-radius:8px;
|
||||
font-size:13px; font-weight:600;
|
||||
border:none; cursor:pointer;
|
||||
font-family:inherit;
|
||||
}
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, var(--cereda-primary), var(--cereda-primary-dark));
|
||||
color:#fff;
|
||||
}
|
||||
.btn-secondary {
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
.btn-ghost { background:transparent; color:var(--text-secondary); border:1px solid var(--border-color); }
|
||||
|
||||
/* ── DASHBOARD GRID ── */
|
||||
.dashboard-grid {
|
||||
display:grid;
|
||||
grid-template-columns: 1fr 340px;
|
||||
gap:20px;
|
||||
}
|
||||
|
||||
/* ── MONITORING DEVICES ── */
|
||||
.device-row {
|
||||
display:flex; align-items:center; gap:12px;
|
||||
padding:10px 0;
|
||||
border-bottom:1px solid rgba(51,65,85,0.5);
|
||||
}
|
||||
.device-row:last-child { border-bottom:none; }
|
||||
.device-status {
|
||||
width:8px; height:8px;
|
||||
border-radius:50%; flex-shrink:0;
|
||||
}
|
||||
.device-status.online { background:#10b981; box-shadow:0 0 6px rgba(16,185,129,0.5); }
|
||||
.device-status.offline { background:#ef4444; }
|
||||
.device-status.warn { background:#f59e0b; }
|
||||
.device-name { font-size:13px; font-weight:500; flex:1; }
|
||||
.device-meta { font-size:12px; color:var(--text-muted); }
|
||||
|
||||
/* ── HEALTH STRIP ── */
|
||||
.health-strip {
|
||||
display:flex; gap:3px; margin-top:8px;
|
||||
}
|
||||
.health-day {
|
||||
flex:1; height:28px; border-radius:4px;
|
||||
background:#10b981;
|
||||
}
|
||||
.health-day.warn { background:#f59e0b; }
|
||||
.health-day.err { background:#ef4444; }
|
||||
|
||||
/* ── QUICK ACTIONS ── */
|
||||
.quick-actions {
|
||||
display:grid; grid-template-columns:1fr 1fr; gap:10px;
|
||||
}
|
||||
.quick-action {
|
||||
background:var(--bg-secondary);
|
||||
border:1px solid var(--border-color);
|
||||
border-radius:10px;
|
||||
padding:14px;
|
||||
display:flex; flex-direction:column; align-items:center;
|
||||
gap:6px; cursor:pointer; text-align:center;
|
||||
transition:border-color 0.15s, background 0.15s;
|
||||
}
|
||||
.quick-action:hover { border-color:var(--cereda-primary); background:rgba(63,163,163,0.05); }
|
||||
.quick-action-icon { font-size:22px; }
|
||||
.quick-action-label { font-size:12px; font-weight:500; color:var(--text-secondary); }
|
||||
|
||||
/* ── TABS ── */
|
||||
.tabs { display:flex; gap:2px; margin-bottom:20px; background:var(--bg-secondary); border-radius:10px; padding:4px; }
|
||||
.tab {
|
||||
flex:1; padding:8px 14px; text-align:center;
|
||||
border-radius:8px; font-size:13px; font-weight:500;
|
||||
color:var(--text-muted); cursor:pointer;
|
||||
}
|
||||
.tab.active { background:var(--cereda-primary); color:#fff; }
|
||||
|
||||
/* ── FORM ── */
|
||||
.form-row { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-bottom:14px; }
|
||||
.form-group { display:flex; flex-direction:column; gap:6px; }
|
||||
.form-label { font-size:12px; font-weight:500; color:var(--text-secondary); }
|
||||
.form-input {
|
||||
background:var(--bg-primary); border:1px solid var(--border-color);
|
||||
border-radius:8px; padding:9px 12px;
|
||||
color:var(--text-primary); font-size:13px; font-family:inherit;
|
||||
}
|
||||
.form-input:focus { outline:none; border-color:var(--cereda-primary); }
|
||||
|
||||
/* ── PROGRESS ── */
|
||||
.progress-bar {
|
||||
height:6px; border-radius:4px;
|
||||
background:var(--bg-tertiary); overflow:hidden;
|
||||
margin-top:6px;
|
||||
}
|
||||
.progress-fill { height:100%; border-radius:4px; background:var(--cereda-primary); }
|
||||
|
||||
/* ── ANNOTATION ── */
|
||||
.annotation {
|
||||
position:fixed; bottom:20px; right:20px;
|
||||
background:rgba(63,163,163,0.15);
|
||||
border:1px solid rgba(63,163,163,0.3);
|
||||
border-radius:10px; padding:12px 16px;
|
||||
font-size:12px; color:var(--cereda-primary);
|
||||
max-width:260px; z-index:999;
|
||||
}
|
||||
.annotation strong { display:block; margin-bottom:4px; font-size:13px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ================================================================
|
||||
SIDEBAR
|
||||
================================================================ -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-logo">
|
||||
<div style="display:flex;align-items:center;gap:10px;">
|
||||
<div style="width:32px;height:32px;background:linear-gradient(135deg,#3fa3a3,#008487);border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:800;color:#fff;">C</div>
|
||||
<div>
|
||||
<div class="sidebar-logo-text">IT Nexus</div>
|
||||
<div style="font-size:10px;color:var(--text-muted);">Cereda Systems</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="sidebar-nav">
|
||||
<div class="sidebar-group">
|
||||
<a class="sidebar-link active">
|
||||
<span class="sidebar-icon">📊</span> Dashboard
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🏠</span> Mein Portal
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-group">
|
||||
<div class="sidebar-group-label">Helpdesk</div>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🎫</span> Tickets
|
||||
<span style="margin-left:auto;background:rgba(63,163,163,0.2);color:var(--cereda-primary);font-size:10px;font-weight:700;padding:2px 6px;border-radius:10px;">12</span>
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">📚</span> Wissensdatenbank
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">📄</span> Anleitungen
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-group">
|
||||
<div class="sidebar-group-label">IT-Verwaltung</div>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">💻</span> Assets
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">📦</span> Lager
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">📋</span> Lizenzen
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🔧</span> Wartung
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🔑</span> FIDO-Keys
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🔄</span> Lifecycle
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-group">
|
||||
<div class="sidebar-group-label">Monitoring & Security</div>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">📡</span> Monitoring
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🛡️</span> Microsoft Defender
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🔧</span> Patch Management
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🛡️</span> Security Reports
|
||||
</a>
|
||||
<a class="sidebar-link" style="padding-left:32px;font-size:13px;">
|
||||
<span class="sidebar-icon">📈</span> IT Übersicht
|
||||
</a>
|
||||
<a class="sidebar-link" style="padding-left:32px;font-size:13px;">
|
||||
<span class="sidebar-icon">🛡️</span> ISO-Zertifizierung
|
||||
</a>
|
||||
<a class="sidebar-link" style="padding-left:32px;font-size:13px;">
|
||||
<span class="sidebar-icon">⚠️</span> Risikoanalyse
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-group">
|
||||
<div class="sidebar-group-label">Administration</div>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🔐</span> Entra Rechte
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">👥</span> Benutzer
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🔗</span> Sichere Links
|
||||
</a>
|
||||
<a class="sidebar-link">
|
||||
<span class="sidebar-icon">🧠</span> KI Wissendatenbank
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<!-- ================================================================
|
||||
TOPBAR
|
||||
================================================================ -->
|
||||
<div class="topbar">
|
||||
<div class="topbar-btn">
|
||||
🔔
|
||||
<span class="topbar-badge">3</span>
|
||||
</div>
|
||||
<div class="topbar-btn">⚙️</div>
|
||||
<div class="topbar-user">
|
||||
<div class="user-avatar">AG</div>
|
||||
<span style="font-size:13px;font-weight:500;color:var(--text-primary);">admin-gruessing</span>
|
||||
<span class="role-badge">Super Admin</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ================================================================
|
||||
MAIN CONTENT — DASHBOARD
|
||||
================================================================ -->
|
||||
<div class="app-main">
|
||||
<div class="page">
|
||||
|
||||
<!-- Page Header -->
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h1 class="page-title">Dashboard</h1>
|
||||
<div class="page-subtitle">Willkommen zurück, Simon · Montag, 11. Mai 2026</div>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button class="btn btn-ghost">📊 Berichte</button>
|
||||
<button class="btn btn-primary">+ Neues Ticket</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Stats -->
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card teal">
|
||||
<div class="stat-icon teal">🎫</div>
|
||||
<div>
|
||||
<div class="stat-value">47</div>
|
||||
<div class="stat-label">Offene Tickets</div>
|
||||
<div class="stat-delta delta-up">↑ 8 diese Woche</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card green">
|
||||
<div class="stat-icon green">💻</div>
|
||||
<div>
|
||||
<div class="stat-value">312</div>
|
||||
<div class="stat-label">Aktive Assets</div>
|
||||
<div class="stat-delta delta-up">↑ 3 neu</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card orange">
|
||||
<div class="stat-icon orange">📡</div>
|
||||
<div>
|
||||
<div class="stat-value">41</div>
|
||||
<div class="stat-label">Monitored Devices</div>
|
||||
<div class="stat-delta delta-down">↓ 2 offline</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card blue">
|
||||
<div class="stat-icon blue">🛡️</div>
|
||||
<div>
|
||||
<div class="stat-value">98%</div>
|
||||
<div class="stat-label">System-Gesundheit</div>
|
||||
<div class="stat-delta delta-up">↑ Alle grün</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Grid -->
|
||||
<div class="dashboard-grid">
|
||||
|
||||
<!-- Left Column -->
|
||||
<div>
|
||||
<!-- Recent Tickets -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-title">🎫 Letzte Tickets</span>
|
||||
<button class="btn btn-ghost" style="padding:6px 12px;font-size:12px;">Alle anzeigen →</button>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Betreff</th>
|
||||
<th>Ersteller</th>
|
||||
<th>Priorität</th>
|
||||
<th>Status</th>
|
||||
<th>Erstellt</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="color:var(--text-muted);font-size:12px;">#1042</td>
|
||||
<td style="font-weight:500;">VPN Verbindung bricht ab</td>
|
||||
<td>
|
||||
<div style="display:flex;align-items:center;gap:6px;">
|
||||
<div style="width:22px;height:22px;border-radius:6px;background:linear-gradient(135deg,#3fa3a3,#008487);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:#fff;flex-shrink:0;">KM</div>
|
||||
k.müller
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge badge-high">🔴 Hoch</span></td>
|
||||
<td><span class="badge badge-open">Offen</span></td>
|
||||
<td style="color:var(--text-muted);font-size:12px;">vor 12 Min</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="color:var(--text-muted);font-size:12px;">#1041</td>
|
||||
<td style="font-weight:500;">Drucker 3. OG nicht erreichbar</td>
|
||||
<td>
|
||||
<div style="display:flex;align-items:center;gap:6px;">
|
||||
<div style="width:22px;height:22px;border-radius:6px;background:linear-gradient(135deg,#7c5cf6,#5a32f5);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:#fff;flex-shrink:0;">SL</div>
|
||||
s.lange
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge badge-medium">🟡 Mittel</span></td>
|
||||
<td><span class="badge badge-pending">In Arbeit</span></td>
|
||||
<td style="color:var(--text-muted);font-size:12px;">vor 1 Std</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="color:var(--text-muted);font-size:12px;">#1040</td>
|
||||
<td style="font-weight:500;">Outlook Kalender sync fehlerhaft</td>
|
||||
<td>
|
||||
<div style="display:flex;align-items:center;gap:6px;">
|
||||
<div style="width:22px;height:22px;border-radius:6px;background:linear-gradient(135deg,#f59e0b,#d97706);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:#fff;flex-shrink:0;">TK</div>
|
||||
t.krause
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge badge-low">🟢 Niedrig</span></td>
|
||||
<td><span class="badge badge-pending">In Arbeit</span></td>
|
||||
<td style="color:var(--text-muted);font-size:12px;">vor 3 Std</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="color:var(--text-muted);font-size:12px;">#1039</td>
|
||||
<td style="font-weight:500;">Neuer Mitarbeiter Onboarding IT</td>
|
||||
<td>
|
||||
<div style="display:flex;align-items:center;gap:6px;">
|
||||
<div style="width:22px;height:22px;border-radius:6px;background:linear-gradient(135deg,#10b981,#059669);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:#fff;flex-shrink:0;">HR</div>
|
||||
hr-team
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge badge-medium">🟡 Mittel</span></td>
|
||||
<td><span class="badge badge-done">✓ Erledigt</span></td>
|
||||
<td style="color:var(--text-muted);font-size:12px;">gestern</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="color:var(--text-muted);font-size:12px;">#1038</td>
|
||||
<td style="font-weight:500;">Windows 11 Update schlägt fehl</td>
|
||||
<td>
|
||||
<div style="display:flex;align-items:center;gap:6px;">
|
||||
<div style="width:22px;height:22px;border-radius:6px;background:linear-gradient(135deg,#ef4444,#dc2626);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:#fff;flex-shrink:0;">BH</div>
|
||||
b.hedderich
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge badge-high">🔴 Hoch</span></td>
|
||||
<td><span class="badge badge-open">Offen</span></td>
|
||||
<td style="color:var(--text-muted);font-size:12px;">gestern</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Monitoring -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-title">📡 Monitoring — Geräte</span>
|
||||
<span class="badge badge-teal">41 Geräte</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="device-row">
|
||||
<div class="device-status online"></div>
|
||||
<div style="flex:1;">
|
||||
<div class="device-name">IT-NB-02 <span style="font-size:11px;color:var(--cereda-primary);">v2.0.0</span></div>
|
||||
<div class="device-meta">Windows 11 Pro · 192.168.0.45 · vor 1 Min</div>
|
||||
</div>
|
||||
<div style="text-align:right;">
|
||||
<div style="font-size:11px;color:var(--text-muted);">CPU 14% · RAM 8.2/31 GB</div>
|
||||
<div style="font-size:11px;color:#10b981;">🔒 BitLocker ✓ 🛡 Defender ✓</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<div class="device-status online"></div>
|
||||
<div style="flex:1;">
|
||||
<div class="device-name">TBO-NB-02 <span style="font-size:11px;color:var(--cereda-primary);">v2.0.0</span></div>
|
||||
<div class="device-meta">Windows 11 Pro · 192.168.0.52 · vor 2 Min</div>
|
||||
</div>
|
||||
<div style="text-align:right;">
|
||||
<div style="font-size:11px;color:var(--text-muted);">CPU 6% · RAM 4.1/16 GB</div>
|
||||
<div style="font-size:11px;color:#10b981;">🔒 BitLocker ✓ 🛡 Defender ✓</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<div class="device-status warn"></div>
|
||||
<div style="flex:1;">
|
||||
<div class="device-name">WT-NB-05 <span style="font-size:11px;color:var(--text-muted);">v1.2.4</span></div>
|
||||
<div class="device-meta">Windows 10 Pro · 192.168.0.67 · vor 8 Min</div>
|
||||
</div>
|
||||
<div style="text-align:right;">
|
||||
<div style="font-size:11px;color:var(--text-muted);">CPU 45% · RAM 14/16 GB</div>
|
||||
<div style="font-size:11px;color:#f59e0b;">⚠️ 12 Updates ausstehend</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="device-row">
|
||||
<div class="device-status offline"></div>
|
||||
<div style="flex:1;">
|
||||
<div class="device-name">FAM-NB-01 <span style="font-size:11px;color:var(--text-muted);">v1.3.0</span></div>
|
||||
<div class="device-meta">Windows 10 Pro · 192.168.0.78 · vor 2 Std</div>
|
||||
</div>
|
||||
<div style="text-align:right;">
|
||||
<div style="font-size:11px;color:#ef4444;">● Offline</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column -->
|
||||
<div>
|
||||
<!-- System Health -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-title">💚 System Health</span>
|
||||
<span class="badge badge-done">90 Tage</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div style="font-size:13px;color:var(--text-muted);margin-bottom:8px;">Letzte 30 Tage</div>
|
||||
<div class="health-strip">
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day warn"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
<div class="health-day"></div><div class="health-day"></div><div class="health-day"></div>
|
||||
</div>
|
||||
<div style="display:flex;justify-content:space-between;margin-top:8px;font-size:11px;color:var(--text-muted);">
|
||||
<span>12. Apr</span><span>Heute</span>
|
||||
</div>
|
||||
<div style="margin-top:14px;display:flex;flex-direction:column;gap:10px;">
|
||||
<div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:12px;margin-bottom:4px;">
|
||||
<span>API Response</span><span style="color:#10b981;">148ms</span>
|
||||
</div>
|
||||
<div class="progress-bar"><div class="progress-fill" style="width:15%;background:#10b981;"></div></div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:12px;margin-bottom:4px;">
|
||||
<span>Datenbank</span><span style="color:#10b981;">OK</span>
|
||||
</div>
|
||||
<div class="progress-bar"><div class="progress-fill" style="width:8%;background:#10b981;"></div></div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:12px;margin-bottom:4px;">
|
||||
<span>Storage</span><span style="color:#f59e0b;">67%</span>
|
||||
</div>
|
||||
<div class="progress-bar"><div class="progress-fill" style="width:67%;background:#f59e0b;"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-title">⚡ Schnellzugriff</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="quick-actions">
|
||||
<div class="quick-action">
|
||||
<div class="quick-action-icon">🎫</div>
|
||||
<div class="quick-action-label">Ticket erstellen</div>
|
||||
</div>
|
||||
<div class="quick-action">
|
||||
<div class="quick-action-icon">💻</div>
|
||||
<div class="quick-action-label">Asset erfassen</div>
|
||||
</div>
|
||||
<div class="quick-action">
|
||||
<div class="quick-action-icon">🔔</div>
|
||||
<div class="quick-action-label">Ankündigung</div>
|
||||
</div>
|
||||
<div class="quick-action">
|
||||
<div class="quick-action-icon">📊</div>
|
||||
<div class="quick-action-label">Proxmox</div>
|
||||
</div>
|
||||
<div class="quick-action">
|
||||
<div class="quick-action-icon">🔗</div>
|
||||
<div class="quick-action-label">Sicherer Link</div>
|
||||
</div>
|
||||
<div class="quick-action">
|
||||
<div class="quick-action-icon">🛡️</div>
|
||||
<div class="quick-action-label">Security Report</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Patch Status -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-title">🔧 Patch Status</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div style="display:flex;flex-direction:column;gap:12px;">
|
||||
<div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:13px;margin-bottom:6px;">
|
||||
<span style="font-weight:500;">Test</span>
|
||||
<span style="color:var(--cereda-primary);">v2.0.0 ✓</span>
|
||||
</div>
|
||||
<div class="progress-bar"><div class="progress-fill" style="width:100%;"></div></div>
|
||||
<div style="font-size:11px;color:var(--text-muted);margin-top:3px;">3/3 Geräte aktuell</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:13px;margin-bottom:6px;">
|
||||
<span style="font-weight:500;">Pilot</span>
|
||||
<span style="color:var(--cereda-primary);">v2.0.0 ✓</span>
|
||||
</div>
|
||||
<div class="progress-bar"><div class="progress-fill" style="width:80%;"></div></div>
|
||||
<div style="font-size:11px;color:var(--text-muted);margin-top:3px;">8/10 Geräte aktuell</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:13px;margin-bottom:6px;">
|
||||
<span style="font-weight:500;">Produktion</span>
|
||||
<span style="color:#f59e0b;">v1.x → rollout</span>
|
||||
</div>
|
||||
<div class="progress-bar"><div class="progress-fill" style="width:18%;background:#f59e0b;"></div></div>
|
||||
<div style="font-size:11px;color:var(--text-muted);margin-top:3px;">5/28 Geräte aktuell</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Design Info Annotation -->
|
||||
<div class="annotation">
|
||||
<strong>📐 IT Nexus — Design Preview</strong>
|
||||
Dies ist ein statischer Mockup des aktuellen IT Nexus Designs von Cereda Systems GmbH für Claude Design.
|
||||
<br/><br/>
|
||||
<strong>Stack:</strong> React + CSS Custom Props<br/>
|
||||
<strong>Theme:</strong> Dark Mode (Standard)<br/>
|
||||
<strong>Primärfarbe:</strong> #3fa3a3 (Cereda Teal)<br/>
|
||||
<strong>Font:</strong> Inter
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
24
frontend/public/index.html
Normal file
24
frontend/public/index.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="IT Nexus - IT Management System by Simon Grüßing" />
|
||||
<title>IT Nexus</title>
|
||||
<script>
|
||||
(function() {
|
||||
try {
|
||||
var theme = localStorage.getItem('it-nexus-theme');
|
||||
if (theme && theme !== 'default') {
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
}
|
||||
} catch(e) {}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
27
frontend/public/logo-itnexus-dark.svg
Normal file
27
frontend/public/logo-itnexus-dark.svg
Normal file
@@ -0,0 +1,27 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 100" fill="none">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="420" y2="0" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#00C8C8"/>
|
||||
<stop offset="100%" stop-color="#40E0E0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<text x="0" y="68"
|
||||
font-family="Segoe UI, Helvetica Neue, Arial, sans-serif"
|
||||
font-size="72" font-weight="900"
|
||||
fill="#00C8C8" letter-spacing="-2">IT</text>
|
||||
|
||||
<circle cx="108" cy="42" r="5" fill="url(#g)"/>
|
||||
|
||||
<text x="124" y="68"
|
||||
font-family="Segoe UI, Helvetica Neue, Arial, sans-serif"
|
||||
font-size="72" font-weight="300"
|
||||
fill="url(#g)" letter-spacing="1">NEXUS</text>
|
||||
|
||||
<rect x="0" y="78" width="420" height="3" rx="1.5" fill="#00C8C8" opacity="0.2"/>
|
||||
|
||||
<text x="2" y="96"
|
||||
font-family="Segoe UI, Helvetica Neue, Arial, sans-serif"
|
||||
font-size="11" font-weight="400"
|
||||
fill="#00C8C8" opacity="0.5" letter-spacing="4">— CEREDA SYSTEMS —</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
22
frontend/public/logo-itnexus-icon.svg
Normal file
22
frontend/public/logo-itnexus-icon.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180" fill="none">
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="0" y1="0" x2="180" y2="180" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#00AAAA"/>
|
||||
<stop offset="100%" stop-color="#007878"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="180" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="white" stop-opacity="0.15"/>
|
||||
<stop offset="60%" stop-color="white" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<rect width="180" height="180" rx="38" fill="url(#bg)"/>
|
||||
<rect width="180" height="180" rx="38" fill="url(#shine)"/>
|
||||
|
||||
<text x="90" y="118"
|
||||
font-family="Segoe UI, Helvetica Neue, Arial, sans-serif"
|
||||
font-size="86" font-weight="900"
|
||||
fill="white" text-anchor="middle" letter-spacing="-3">IT</text>
|
||||
|
||||
<circle cx="90" cy="148" r="5" fill="white" opacity="0.4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 942 B |
27
frontend/public/logo-itnexus.svg
Normal file
27
frontend/public/logo-itnexus.svg
Normal file
@@ -0,0 +1,27 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 100" fill="none">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="420" y2="0" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#007E7E"/>
|
||||
<stop offset="100%" stop-color="#00B5B5"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<text x="0" y="68"
|
||||
font-family="Segoe UI, Helvetica Neue, Arial, sans-serif"
|
||||
font-size="72" font-weight="900"
|
||||
fill="#009B9A" letter-spacing="-2">IT</text>
|
||||
|
||||
<circle cx="108" cy="42" r="5" fill="url(#g)"/>
|
||||
|
||||
<text x="124" y="68"
|
||||
font-family="Segoe UI, Helvetica Neue, Arial, sans-serif"
|
||||
font-size="72" font-weight="300"
|
||||
fill="url(#g)" letter-spacing="1">NEXUS</text>
|
||||
|
||||
<rect x="0" y="78" width="420" height="3" rx="1.5" fill="#009B9A" opacity="0.2"/>
|
||||
|
||||
<text x="2" y="96"
|
||||
font-family="Segoe UI, Helvetica Neue, Arial, sans-serif"
|
||||
font-size="11" font-weight="400"
|
||||
fill="#009B9A" opacity="0.5" letter-spacing="4">— CEREDA SYSTEMS —</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
40
frontend/public/logo-preview.html
Normal file
40
frontend/public/logo-preview.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>IT Nexus Logo Preview</title>
|
||||
<style>
|
||||
body { margin: 0; font-family: Segoe UI, sans-serif; background: #111; color: white; }
|
||||
.section { padding: 60px; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 16px; }
|
||||
.section h2 { font-size: 12px; color: #555; letter-spacing: 2px; text-transform: uppercase; margin: 0; }
|
||||
.light { background: #ffffff; }
|
||||
.dark { background: #111113; }
|
||||
.icon { background: #f3f4f6; }
|
||||
img { max-width: 400px; }
|
||||
.icon img { max-width: 120px; }
|
||||
.divider { width: 100%; height: 1px; background: #222; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="section light">
|
||||
<h2 style="color:#aaa;">Hell — für weißen Hintergrund</h2>
|
||||
<img src="logo-itnexus.svg" alt="IT Nexus Logo Hell">
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="section dark">
|
||||
<h2>Dunkel — für dunklen Hintergrund</h2>
|
||||
<img src="logo-itnexus-dark.svg" alt="IT Nexus Logo Dunkel">
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="section icon">
|
||||
<h2 style="color:#aaa;">Icon / App-Symbol</h2>
|
||||
<img src="logo-itnexus-icon.svg" alt="IT Nexus Icon">
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1
frontend/public/logo.svg
Normal file
1
frontend/public/logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 11 KiB |
1751
frontend/public/share-tool.html
Normal file
1751
frontend/public/share-tool.html
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user