clupilot/templates/akutell/Team.html

177 lines
12 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>CluPilot — Team</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="clupilot.css">
</head>
<body>
<div class="app">
<aside class="sidebar" data-screen-label="Sidebar">
<div class="brand"><div class="brand-mark" aria-hidden="true"></div><div class="brand-name">CluPilot<span>v2.4</span></div></div>
<button class="ws-switch" aria-label="Workspace wechseln">
<div class="ws-avatar">AC</div>
<div class="ws-meta"><div class="ws-name">Acme Cluster</div><div class="ws-plan">team · 14 user</div></div>
<svg class="ws-chev" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 9l4-4 4 4M8 15l4 4 4-4"/></svg>
</button>
<nav class="nav">
<a class="nav-item" href="CluPilot Dashboard Glass.html"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></svg><span>Dashboard</span></a>
<a class="nav-item" href="Server.html"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="4" width="18" height="7" rx="1.5"/><rect x="3" y="13" width="18" height="7" rx="1.5"/><circle cx="7" cy="7.5" r="0.7" fill="currentColor"/><circle cx="7" cy="16.5" r="0.7" fill="currentColor"/></svg><span>Server</span><span class="count">6</span></a>
<a class="nav-item" href="Sites.html"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"/></svg><span>Sites</span><span class="count">87</span></a>
<a class="nav-item" href="Backups.html"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M21 12c0 5-9 9-9 9s-9-4-9-9V5l9-3 9 3v7z"/><path d="M9 11l2 2 4-4"/></svg><span>Backups</span></a>
<a class="nav-item" href="Sicherheit.html"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M12 3l8 4v5c0 5-3.5 8-8 9-4.5-1-8-4-8-9V7l8-4z"/></svg><span>Sicherheit</span><span class="count" style="color:var(--warning);background:var(--warning-soft);border-color:rgba(194,130,15,0.3)">3</span></a>
<div class="nav-title">Konto</div>
<a class="nav-item active" href="Team.html"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8"/></svg><span>Team</span></a>
<a class="nav-item" href="Einstellungen.html"><svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1A1.7 1.7 0 0 0 4.6 9a1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg><span>Einstellungen</span></a>
</nav>
<div class="plan-box">
<div class="plan-row"><div class="plan-name">Team Plan</div><div class="plan-tag">PRO</div></div>
<div class="plan-meter"><span></span></div>
<div class="plan-stats"><span>87 / 140 sites</span><span>62%</span></div>
</div>
</aside>
<main class="main" data-screen-label="Team">
<div class="topbar">
<div>
<div class="page-title">Team</div>
<div class="page-sub">14 mitglieder · 2 einladungen offen</div>
</div>
<span class="status-chip"><span class="pulse-dot"></span> 6 gerade aktiv</span>
<div class="top-spacer"></div>
<div class="search">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>
<input placeholder="Mitglied suchen…" />
<span class="kbd">⌘K</span>
</div>
<button class="btn-primary">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M12 5v14M5 12h14"/></svg>
Einladen
</button>
</div>
<div class="content">
<div class="metrics">
<div class="metric">
<div class="metric-top"><div class="metric-label">Mitglieder</div><div class="m-ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg></div></div>
<div class="metric-value">14<span class="sub">/ 20</span></div>
<div class="metric-delta"><span class="chg up">6 sitze frei</span> im Team-Plan</div>
</div>
<div class="metric">
<div class="metric-top"><div class="metric-label">Admins</div><div class="m-ico success"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3l8 4v5c0 5-3.5 8-8 9-4.5-1-8-4-8-9V7l8-4z"/></svg></div></div>
<div class="metric-value">3</div>
<div class="metric-delta"><span class="chg">voller zugriff</span></div>
</div>
<div class="metric">
<div class="metric-top"><div class="metric-label">Einladungen offen</div><div class="m-ico warning"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16v16H4z"/><path d="M4 7l8 6 8-6"/></svg></div></div>
<div class="metric-value">2</div>
<div class="metric-delta"><span class="chg warn">ausstehend</span> · &gt; 2 tage</div>
</div>
<div class="metric">
<div class="metric-top"><div class="metric-label">2FA aktiv</div><div class="m-ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="10" width="16" height="11" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/></svg></div></div>
<div class="metric-value">11<span class="sub">/ 14</span></div>
<div class="metric-delta"><span class="chg warn">3 ohne 2FA</span></div>
</div>
</div>
<section class="card">
<div class="card-head">
<h3><svg class="hico" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg>Mitglieder</h3>
<div class="card-tabs"><button class="active">Alle</button><button>Admins</button><button>Developer</button><button>Nur Lesen</button></div>
</div>
<div class="scroll-x">
<table class="table">
<thead><tr><th>Mitglied</th><th>Rolle</th><th>Zugriff</th><th>2FA</th><th>Zuletzt aktiv</th><th class="num"></th></tr></thead>
<tbody id="team-body"></tbody>
</table>
</div>
</section>
<section class="card">
<div class="card-head"><h3><svg class="hico" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16v16H4z"/><path d="M4 7l8 6 8-6"/></svg>Offene Einladungen</h3></div>
<div class="scroll-x">
<table class="table">
<thead><tr><th>E-Mail</th><th>Rolle</th><th>Eingeladen von</th><th>Gesendet</th><th class="num"></th></tr></thead>
<tbody id="inv-body"></tbody>
</table>
</div>
</section>
<div class="foot">CluPilot · rollenbasierte zugriffskontrolle · audit-log aktiv</div>
</div>
</main>
</div>
<script>
const Icon = {
more:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="5" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="19" cy="12" r="1.5"/></svg>',
resend:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 12a9 9 0 1 0 3-6.7M3 4v4h4"/></svg>',
x:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 6l12 12M18 6L6 18"/></svg>',
};
const avColors = ['#3b6ff2','#15a06a','#7c5cff','#c2820f','#db3b3b','#0ea5b7','#c026d3','#0d9488','#e0772e','#2563eb'];
const roleMap = {
Owner: {cls:'accent'},
Admin: {cls:'success'},
Developer:{cls:''},
Editor: {cls:''},
'Nur Lesen':{cls:''},
};
const team = [
{name:'Julia Koch', email:'j.koch@acme.io', role:'Owner', scope:'Alle Server & Sites', tfa:true, last:'gerade eben'},
{name:'Marc Weber', email:'m.weber@acme.io', role:'Admin', scope:'Alle Server & Sites', tfa:true, last:'vor 4 min'},
{name:'Sina Brandt', email:'s.brandt@acme.io', role:'Admin', scope:'eu-prod-* · Sites', tfa:true, last:'vor 22 min'},
{name:'Tobias Reuter', email:'t.reuter@acme.io', role:'Developer', scope:'eu-prod-01, eu-prod-02', tfa:true, last:'vor 1 std'},
{name:'Nadine Frei', email:'n.frei@acme.io', role:'Developer', scope:'us-east-prod-01', tfa:false, last:'vor 3 std'},
{name:'Leon Hartmann', email:'l.hartmann@acme.io',role:'Editor', scope:'12 Sites (Content)', tfa:true, last:'vor 5 std'},
{name:'Petra Lang', email:'p.lang@acme.io', role:'Editor', scope:'shop.* Sites', tfa:false, last:'gestern'},
{name:'Ömer Yıldız', email:'o.yildiz@acme.io', role:'Developer', scope:'eu-edge-amsterdam', tfa:true, last:'gestern'},
{name:'Clara Voss', email:'c.voss@acme.io', role:'Nur Lesen', scope:'Reporting · alle', tfa:true, last:'vor 2 tagen'},
{name:'David Mertens', email:'d.mertens@acme.io', role:'Nur Lesen', scope:'Reporting · eu', tfa:false, last:'vor 4 tagen'},
];
const tbody = document.getElementById('team-body');
team.forEach((m,i)=>{
const initials = m.name.split(' ').map(w=>w[0]).join('').slice(0,2).toUpperCase();
const color = avColors[i % avColors.length];
const r = roleMap[m.role] || {cls:''};
tbody.insertAdjacentHTML('beforeend',`
<tr>
<td><div class="site-cell">
<div class="avatar" style="background:linear-gradient(135deg,${color},${color}cc)">${initials}</div>
<div style="min-width:0"><div class="site-name">${m.name}</div><div class="site-meta">${m.email}</div></div>
</div></td>
<td><span class="pill ${r.cls}">${m.role}</span></td>
<td><span class="health-label">${m.scope}</span></td>
<td>${m.tfa
? '<span class="health"><span class="health-dot ok"></span><span class="health-label">aktiv</span></span>'
: '<span class="health"><span class="health-dot warn"></span><span class="health-label">fehlt</span></span>'}</td>
<td><span class="site-meta">${m.last}</span></td>
<td class="num"><div class="row-actions"><button title="Mehr">${Icon.more}</button></div></td>
</tr>`);
});
const invites = [
{email:'a.schmidt@acme.io', role:'Developer', by:'Julia Koch', sent:'vor 3 tagen'},
{email:'freelance@studio-nord.de', role:'Editor', by:'Marc Weber', sent:'vor 2 tagen'},
];
const ibody = document.getElementById('inv-body');
invites.forEach(v=>{
ibody.insertAdjacentHTML('beforeend',`
<tr>
<td><div class="site-cell">
<div class="avatar sm" style="background:rgba(30,35,60,0.12);color:var(--muted)"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16v16H4z"/><path d="M4 7l8 6 8-6"/></svg></div>
<div class="site-name">${v.email}</div>
</div></td>
<td><span class="pill">${v.role}</span></td>
<td><span class="health-label">${v.by}</span></td>
<td><span class="site-meta">${v.sent}</span></td>
<td class="num"><div class="row-actions"><button title="Erneut senden">${Icon.resend}</button><button title="Zurückziehen">${Icon.x}</button></div></td>
</tr>`);
});
</script>
</body>
</html>