snapshot: preserve shell cleanup and login/dashboard fixes
This commit is contained in:
45
backend/workflows/static/workflows/css/admin_tools.css
Normal file
45
backend/workflows/static/workflows/css/admin_tools.css
Normal file
@@ -0,0 +1,45 @@
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #0f172a; padding: 20px; }
|
||||
.shell { max-width: 1100px; margin: 0 auto; background: #fff; border: 1px solid #d8e3f0; border-radius: 14px; padding: 16px; }
|
||||
h1 { margin: 12px 0 6px; color: #000078; }
|
||||
.sub { margin: 0 0 12px; color: #54657c; }
|
||||
.flash, .msg { border-radius: 10px; padding: 10px 12px; margin: 0 0 12px; border: 1px solid #d6e1ef; background: #f8fbff; color: #1f3a5f; }
|
||||
.flash.error, .msg.error { border-color: #fecaca; background: #fff1f2; color: #991b1b; }
|
||||
.flash.success { border-color: #bfe6c9; background: #edf9f1; color: #116634; }
|
||||
.card { border: 1px solid #d8e3f0; border-radius: 12px; background: #fbfdff; padding: 12px; margin-bottom: 14px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(2, minmax(240px, 1fr)); gap: 10px; }
|
||||
label { display: block; margin-bottom: 4px; font-size: 12px; color: #334155; font-weight: 700; }
|
||||
input, select, textarea { width: 100%; box-sizing: border-box; border: 1px solid #cbd5e1; border-radius: 8px; padding: 8px 9px; background: #fff; }
|
||||
textarea { min-height: 120px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
|
||||
.actions { margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
.hint { margin-top: 6px; color: #64748b; font-size: 12px; }
|
||||
.toolbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
|
||||
.switch { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
|
||||
.switch .tab { border: 1px solid #c9d6e7; border-radius: 999px; padding: 8px 14px; text-decoration: none; color: #1f2f49; font-weight: 700; background: #f6f9ff; }
|
||||
.switch .tab.active { background: #000078; color: #fff; border-color: #000078; }
|
||||
.check-row { margin-top: 8px; display: flex; gap: 12px; flex-wrap: wrap; }
|
||||
.check-row label { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 13px; }
|
||||
.check-row input[type="checkbox"] { width: auto; }
|
||||
.table-wrap, .option-table-wrap { overflow-x: auto; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
||||
th, td { border: 1px solid #dce5f1; padding: 8px; text-align: left; vertical-align: top; }
|
||||
th { background: #f6f9ff; color: #334155; }
|
||||
.template-block { border: 1px solid #d8e3f0; border-radius: 10px; background: #fff; padding: 10px; margin-top: 10px; }
|
||||
.template-title, .rule-title { margin: 0 0 8px; color: #24344e; font-weight: 700; font-size: 14px; }
|
||||
.rule-card { margin-top: 12px; border: 1px solid #d8e3f0; border-radius: 12px; padding: 10px; background: #fff; }
|
||||
.badge { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 700; }
|
||||
.scheduled { background: #eff6ff; color: #1d4ed8; }
|
||||
.paused { background: #fef9c3; color: #854d0e; }
|
||||
.cancelled { background: #f1f5f9; color: #334155; }
|
||||
.sent { background: #ecfdf3; color: #166534; }
|
||||
.failed { background: #fff1f2; color: #991b1b; }
|
||||
.bulk-bar { margin: 0 0 10px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
||||
.bulk-bar select { width: auto; min-width: 180px; }
|
||||
.select-col { width: 42px; text-align: center; }
|
||||
.bulk-note { color: #64748b; font-size: 12px; }
|
||||
.field label { display: block; font-weight: 600; margin-bottom: 6px; }
|
||||
.field input, .field select { min-height: 40px; }
|
||||
.mini { color: #64748b; font-size: 12px; }
|
||||
.table-controls input[type="text"], .table-controls select { width: 100%; min-height: 36px; padding: 7px 9px; border: 1px solid #cfd9e8; border-radius: 8px; box-sizing: border-box; }
|
||||
.table-controls input[type="checkbox"] { transform: scale(1.1); width: auto; }
|
||||
.actions { white-space: nowrap; }
|
||||
@media (max-width: 760px) { .grid { grid-template-columns: 1fr; } }
|
||||
22
backend/workflows/static/workflows/css/docs_pages.css
Normal file
22
backend/workflows/static/workflows/css/docs_pages.css
Normal file
@@ -0,0 +1,22 @@
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 20px; }
|
||||
.shell { max-width: 1120px; margin: 0 auto; background: #fff; border: 1px solid #d7e0ea; border-radius: 14px; padding: 18px; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; margin: 0 0 10px; display: block; }
|
||||
.top { display: flex; justify-content: space-between; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
|
||||
h1 { margin: 0; color: #000078; font-size: 30px; }
|
||||
.sub { margin: 8px 0 16px; color: #5f6f85; }
|
||||
.toc { border: 1px solid #d7e0ea; border-radius: 10px; padding: 10px; background: #f7fbff; margin-bottom: 16px; }
|
||||
.toc a { color: #0b4da2; text-decoration: none; margin-right: 10px; white-space: nowrap; }
|
||||
h2 { margin: 20px 0 8px; color: #113a74; border-bottom: 1px solid #e1e8f2; padding-bottom: 4px; }
|
||||
h3 { margin: 14px 0 6px; color: #183f77; }
|
||||
ul { margin: 8px 0 12px 20px; }
|
||||
li { margin: 4px 0; }
|
||||
code { background: #f1f5fb; border: 1px solid #dce6f3; border-radius: 6px; padding: 2px 6px; }
|
||||
pre { background: #f7fbff; border: 1px solid #dce6f3; border-radius: 10px; padding: 10px; overflow-x: auto; }
|
||||
.box { border: 1px solid #d7e0ea; border-radius: 10px; padding: 10px; background: #fcfdff; margin: 8px 0 12px; }
|
||||
.note { border-left: 4px solid #000078; padding: 8px 10px; background: #f4f8ff; margin: 10px 0; }
|
||||
.grid { display: grid; grid-template-columns: repeat(3, minmax(260px, 1fr)); gap: 14px; }
|
||||
.card { border: 1px solid #d7e0ea; border-radius: 14px; background: #fcfdff; padding: 16px; }
|
||||
.eyebrow { display: inline-block; padding: 5px 10px; border-radius: 999px; background: #eef4ff; color: #244a8f; border: 1px solid #d5e2f9; font-size: 12px; font-weight: 700; margin-bottom: 10px; }
|
||||
p { margin: 0 0 14px; color: #5f6f85; }
|
||||
.actions { display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
@media (max-width: 760px) { .grid { grid-template-columns: 1fr; } }
|
||||
432
backend/workflows/static/workflows/css/home.css
Normal file
432
backend/workflows/static/workflows/css/home.css
Normal file
@@ -0,0 +1,432 @@
|
||||
:root {
|
||||
--brand-blue: #000078;
|
||||
--brand-red: #8c1d1d;
|
||||
--ink: #102039;
|
||||
--muted: #5f6f85;
|
||||
--line: #d8e1ee;
|
||||
--panel: #ffffff;
|
||||
--bg-soft: #eff4ff;
|
||||
--ok-bg: #effaf2;
|
||||
--ok-ink: #166534;
|
||||
--warn-bg: #fff6ea;
|
||||
--warn-ink: #8a4f00;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
||||
color: var(--ink);
|
||||
background:
|
||||
radial-gradient(80% 120% at 85% 8%, rgba(0, 0, 120, 0.12), rgba(0, 0, 120, 0)),
|
||||
radial-gradient(70% 90% at 8% 92%, rgba(140, 29, 29, 0.10), rgba(140, 29, 29, 0)),
|
||||
linear-gradient(165deg, #eef3ff, #f7f9ff 48%, #f0f5ff);
|
||||
min-height: 100vh;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.shell {
|
||||
width: min(1380px, 100%);
|
||||
margin: 0 auto;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 20px 44px rgba(16, 32, 57, 0.13);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
padding: 18px 22px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.brand-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
flex: 0 0 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
width: 210px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.lang-switch { display:flex; gap:6px; }
|
||||
.lang-btn { border:1px solid var(--line); background:#f8fbff; color:#1f3a5f; border-radius:999px; padding:6px 10px; font-size:12px; font-weight:700; cursor:pointer; }
|
||||
.lang-btn.active { background:var(--brand-blue); border-color:var(--brand-blue); color:#fff; }
|
||||
|
||||
.hero {
|
||||
padding: 24px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(0, 0, 120, 0.08), rgba(0, 0, 120, 0) 44%),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.96), rgba(246,250,255,0.92));
|
||||
}
|
||||
|
||||
.hero-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 18px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.hero-card,
|
||||
.hero-sidecard {
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
background: rgba(255,255,255,0.92);
|
||||
border-radius: 22px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.hero-card {
|
||||
padding: 24px;
|
||||
background:
|
||||
radial-gradient(100% 140% at 10% 10%, rgba(31,79,214,0.12), rgba(31,79,214,0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.98), rgba(247,250,255,0.95));
|
||||
}
|
||||
|
||||
.hero-sidecard {
|
||||
padding: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background:
|
||||
radial-gradient(120% 120% at 100% 0%, rgba(163,32,32,0.10), rgba(163,32,32,0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.98), rgba(253,247,247,0.96));
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(0,0,120,0.12);
|
||||
background: rgba(0,0,120,0.05);
|
||||
color: var(--brand-blue);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
margin: 14px 0 8px;
|
||||
font-size: clamp(30px, 5vw, 46px);
|
||||
line-height: 1;
|
||||
letter-spacing: -0.04em;
|
||||
color: var(--brand-blue);
|
||||
}
|
||||
|
||||
.hero p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
max-width: 720px;
|
||||
font-size: 15px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.status-row {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.status-pill {
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--line);
|
||||
background: #fff;
|
||||
color: #30445f;
|
||||
padding: 8px 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.status-pill.ok {
|
||||
background: var(--ok-bg);
|
||||
color: var(--ok-ink);
|
||||
border-color: #c7ecd2;
|
||||
}
|
||||
|
||||
.status-pill.warn {
|
||||
background: var(--warn-bg);
|
||||
color: var(--warn-ink);
|
||||
border-color: #f7dfbb;
|
||||
}
|
||||
|
||||
.hero-sidecard h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #1a3359;
|
||||
}
|
||||
|
||||
.hero-sidecard p {
|
||||
margin: 8px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.hero-metrics {
|
||||
margin-top: 18px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.hero-metric {
|
||||
padding: 12px 14px;
|
||||
border-radius: 16px;
|
||||
background: rgba(255,255,255,0.86);
|
||||
border: 1px solid rgba(217, 227, 238, 0.95);
|
||||
}
|
||||
|
||||
.hero-metric-label {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.hero-metric-value {
|
||||
margin-top: 5px;
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
color: var(--brand-blue);
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 20px 22px 24px;
|
||||
}
|
||||
|
||||
.section-head {
|
||||
margin: 0 0 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
align-items: flex-end;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.section-head h2 {
|
||||
margin: 0;
|
||||
font-size: 19px;
|
||||
color: #172b4a;
|
||||
}
|
||||
|
||||
.section-head p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.apps-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.app-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
border-radius: 22px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(247,250,255,0.95));
|
||||
padding: 18px;
|
||||
min-height: 222px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.app-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: auto -24px -38px auto;
|
||||
width: 118px;
|
||||
height: 118px;
|
||||
border-radius: 50%;
|
||||
background: rgba(31, 79, 214, 0.08);
|
||||
}
|
||||
|
||||
.app-card.primary {
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(242,247,255,0.97));
|
||||
}
|
||||
|
||||
.app-card.red {
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(255,245,245,0.97));
|
||||
}
|
||||
|
||||
.app-card.red::before { background: rgba(163, 32, 32, 0.08); }
|
||||
|
||||
.app-card .top-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.accent {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 14px;
|
||||
background: rgba(0, 0, 120, 0.06);
|
||||
color: var(--brand-blue);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.04em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.accent.red {
|
||||
background: rgba(163, 32, 32, 0.08);
|
||||
color: var(--brand-red);
|
||||
}
|
||||
|
||||
.app-title {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.03em;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.app-text {
|
||||
margin: 10px 0 12px;
|
||||
color: #5a6a81;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
max-width: 34ch;
|
||||
}
|
||||
|
||||
.tag-row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
border: 1px solid rgba(217, 227, 238, 0.96);
|
||||
border-radius: 14px;
|
||||
padding: 7px 10px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(248,251,255,0.96));
|
||||
color: #486183;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.admin-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.admin-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
border-radius: 18px;
|
||||
padding: 14px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(247,250,255,0.96));
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.admin-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: auto -18px -30px auto;
|
||||
width: 84px;
|
||||
height: 84px;
|
||||
border-radius: 50%;
|
||||
background: rgba(31, 79, 214, 0.06);
|
||||
}
|
||||
|
||||
.admin-card h3 {
|
||||
margin: 0 0 7px;
|
||||
font-size: 15px;
|
||||
color: #18345f;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.admin-card p {
|
||||
margin: 0 0 11px;
|
||||
font-size: 12px;
|
||||
color: #607088;
|
||||
min-height: 34px;
|
||||
line-height: 1.45;
|
||||
max-width: 26ch;
|
||||
}
|
||||
|
||||
.msg {
|
||||
border-radius: 10px;
|
||||
padding: 10px 12px;
|
||||
margin: 0 0 14px;
|
||||
border: 1px solid #d6e1ef;
|
||||
background: #f8fbff;
|
||||
color: #1f3a5f;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.msg.error {
|
||||
border-color: #fecaca;
|
||||
background: #fff1f2;
|
||||
color: #991b1b;
|
||||
}
|
||||
|
||||
.footer-note {
|
||||
margin-top: 16px;
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 12px;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
.hero-grid { grid-template-columns: 1fr; }
|
||||
.apps-grid { grid-template-columns: 1fr 1fr; }
|
||||
.admin-grid { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
body { padding: 12px; }
|
||||
.topbar, .hero, .main { padding-left: 14px; padding-right: 14px; }
|
||||
.hero h1 { font-size: 28px; }
|
||||
.apps-grid, .admin-grid { grid-template-columns: 1fr; }
|
||||
.quick-actions { justify-content: flex-start; }
|
||||
}
|
||||
99
backend/workflows/static/workflows/css/login.css
Normal file
99
backend/workflows/static/workflows/css/login.css
Normal file
@@ -0,0 +1,99 @@
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
||||
background:
|
||||
radial-gradient(70% 90% at 8% 8%, rgba(0, 0, 120, 0.14), rgba(0, 0, 120, 0)),
|
||||
radial-gradient(60% 85% at 92% 88%, rgba(163, 32, 32, 0.12), rgba(163, 32, 32, 0)),
|
||||
linear-gradient(160deg, #eef3ff 0%, #f9fbff 48%, #edf4ff 100%);
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.shell {
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(217, 227, 238, 0.9);
|
||||
border-radius: 28px;
|
||||
box-shadow: 0 22px 48px rgba(18, 34, 56, 0.14);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.login-shell-body {
|
||||
padding: 24px;
|
||||
background:
|
||||
radial-gradient(90% 120% at 10% 0%, rgba(31, 79, 214, 0.06), rgba(31, 79, 214, 0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.72), rgba(248,251,255,0.48));
|
||||
}
|
||||
|
||||
.login-card {
|
||||
width: min(440px, 100%);
|
||||
margin: 0 auto;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
border: 1px solid #d9e3f0;
|
||||
border-radius: 20px;
|
||||
padding: 22px;
|
||||
box-shadow: 0 14px 32px rgba(28, 45, 79, 0.10), inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.login-card h1 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 24px;
|
||||
color: #132238;
|
||||
}
|
||||
|
||||
.login-card p {
|
||||
margin: 0 0 14px;
|
||||
color: #607086;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.field label {
|
||||
display: block;
|
||||
font-weight: 700;
|
||||
margin-bottom: 6px;
|
||||
color: #132238;
|
||||
}
|
||||
|
||||
.field input {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 10px;
|
||||
min-height: 44px;
|
||||
font: inherit;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.errorlist {
|
||||
color: #b91c1c;
|
||||
margin: 0 0 10px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #f0c8c8;
|
||||
background: #fff3f3;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
body {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.login-shell-body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
width: 100%;
|
||||
padding: 18px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
:root {
|
||||
--brand-blue: #000078;
|
||||
--ink: #17253b;
|
||||
--muted: #607087;
|
||||
--line: #d7e0ea;
|
||||
--panel: #ffffff;
|
||||
--soft: #f4f8ff;
|
||||
--soft-strong: #eef4ff;
|
||||
--ok-bg: #edf9f1;
|
||||
--ok-ink: #116634;
|
||||
--warn-bg: #fff8ea;
|
||||
--warn-ink: #8a5a00;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; font-family: "Segoe UI", Arial, sans-serif; background: linear-gradient(180deg, #eef4ff, #f8fbff); color: var(--ink); padding: 24px; }
|
||||
.shell { width: min(var(--app-shell-width), 100%); margin: 0 auto; background: var(--panel); border: 1px solid var(--line); border-radius: 28px; box-shadow: 0 22px 48px rgba(18,34,56,.14); overflow: hidden; }
|
||||
.hero { padding: 20px 22px 18px; border-bottom: 1px solid var(--line); background: linear-gradient(135deg, rgba(0,0,120,.06), rgba(0,0,120,0) 48%), linear-gradient(180deg, #ffffff, #f8fbff); }
|
||||
.hero h1 { margin: 0; font-size: 32px; line-height: 1.08; color: var(--brand-blue); }
|
||||
.sub { margin: 8px 0 0; color: var(--muted); max-width: 780px; }
|
||||
.content { padding: 20px 22px 24px; }
|
||||
.flash { margin: 0 0 12px; padding: 10px 12px; border-radius: 10px; border: 1px solid #bfe6c9; background: var(--ok-bg); color: var(--ok-ink); }
|
||||
.meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-bottom: 16px; }
|
||||
.card { border: 1px solid var(--line); border-radius: 14px; background: #fff; padding: 14px; }
|
||||
.card h2 { margin: 0 0 10px; font-size: 16px; color: #1b3764; }
|
||||
.progress-block { border: 1px solid var(--line); border-radius: 14px; background: linear-gradient(180deg, #ffffff, #f9fbff); padding: 14px; margin-bottom: 16px; }
|
||||
.progress-top { display: flex; justify-content: space-between; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
|
||||
.progress-label { font-size: 15px; font-weight: 700; color: #18345f; }
|
||||
.progress-meta { color: var(--muted); font-size: 13px; }
|
||||
.progress-bar { width: 100%; height: 12px; border-radius: 999px; overflow: hidden; background: #e7eefb; border: 1px solid #d6e1f5; }
|
||||
.progress-fill { height: 100%; background: linear-gradient(90deg, #3056a3, #0f5fcf); }
|
||||
.meta-grid { display: grid; grid-template-columns: 170px 1fr; gap: 8px 10px; font-size: 14px; }
|
||||
.meta-grid strong { color: #334155; }
|
||||
.status-pill { display: inline-block; padding: 4px 10px; border-radius: 999px; border: 1px solid #d7e0ea; background: #f8fbff; color: #486183; font-size: 12px; font-weight: 700; }
|
||||
.status-pill.done { background: var(--ok-bg); color: var(--ok-ink); border-color: #bfe6c9; }
|
||||
.status-pill.draft { background: var(--warn-bg); color: var(--warn-ink); border-color: #f5d8a8; }
|
||||
.section { border: 1px solid var(--line); border-radius: 14px; overflow: hidden; margin-bottom: 14px; background: #fff; }
|
||||
.section-head { padding: 11px 14px; font-weight: 700; color: #1f376b; background: var(--soft-strong); border-bottom: 1px solid #d5e2f9; }
|
||||
.items { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; padding: 6px 14px 10px; }
|
||||
.item { display: flex; align-items: flex-start; gap: 12px; padding: 10px 0; border-bottom: 1px solid #eef3f8; }
|
||||
.item:nth-last-child(-n+2) { border-bottom: 0; }
|
||||
.item input { margin-top: 2px; width: 18px; height: 18px; accent-color: var(--brand-blue); }
|
||||
.item span { line-height: 1.45; }
|
||||
textarea { width: 100%; min-height: 150px; border: 1px solid #cfd9e8; border-radius: 10px; padding: 11px 12px; font: inherit; resize: vertical; }
|
||||
.help { color: var(--muted); font-size: 13px; margin-top: 8px; }
|
||||
.actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
|
||||
@media (max-width: 900px) { .meta, .items { grid-template-columns: 1fr; } .meta-grid { grid-template-columns: 1fr; } .item:nth-last-child(-n+2) { border-bottom: 1px solid #eef3f8; } .item:last-child { border-bottom: 0; } }
|
||||
20
backend/workflows/static/workflows/css/release_checklist.css
Normal file
20
backend/workflows/static/workflows/css/release_checklist.css
Normal file
@@ -0,0 +1,20 @@
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 20px; }
|
||||
.shell { max-width: 1120px; margin: 0 auto; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; margin: 0 0 10px; display: block; }
|
||||
.hero, .panel { background: #fff; border: 1px solid #d7e0ea; border-radius: 16px; box-shadow: 0 20px 40px rgba(17, 58, 116, 0.08); }
|
||||
.hero { padding: 20px; margin-bottom: 18px; }
|
||||
.top { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
|
||||
.eyebrow { display: inline-block; padding: 5px 10px; border-radius: 999px; background: #eef4ff; color: #244a8f; border: 1px solid #d5e2f9; font-size: 12px; font-weight: 700; margin-bottom: 10px; }
|
||||
h1 { margin: 0; color: #000078; font-size: 30px; }
|
||||
.sub { margin: 8px 0 0; color: #5f6f85; max-width: 820px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(2, minmax(320px, 1fr)); gap: 16px; }
|
||||
.panel { padding: 18px; }
|
||||
h2 { margin: 0 0 12px; color: #113a74; font-size: 20px; }
|
||||
ol, ul { margin: 0; padding-left: 20px; }
|
||||
li { margin: 8px 0; color: #334155; }
|
||||
.checklist li { list-style: none; position: relative; padding-left: 28px; }
|
||||
.checklist li::before { content: '\25A1'; position: absolute; left: 0; top: 0; color: #66758c; font-size: 16px; }
|
||||
pre { margin: 12px 0 0; padding: 14px; border-radius: 12px; background: #f7faff; border: 1px solid #dfe8f4; overflow-x: auto; color: #16345f; }
|
||||
code { font-family: Menlo, Monaco, Consolas, monospace; font-size: 13px; }
|
||||
.note { margin-top: 16px; padding: 14px 16px; border-radius: 12px; background: #f7faff; border: 1px solid #dfe8f4; color: #355175; }
|
||||
@media (max-width: 820px) { .grid { grid-template-columns: 1fr; } }
|
||||
863
backend/workflows/static/workflows/css/requests_dashboard.css
Normal file
863
backend/workflows/static/workflows/css/requests_dashboard.css
Normal file
@@ -0,0 +1,863 @@
|
||||
:root {
|
||||
--brand-blue: #000078;
|
||||
--brand-blue-soft: #1f4fd6;
|
||||
--brand-red: #a32020;
|
||||
--ink: #132238;
|
||||
--muted: #607086;
|
||||
--line: #d9e3ee;
|
||||
--line-strong: #c8d5e5;
|
||||
--panel: rgba(255, 255, 255, 0.9);
|
||||
--panel-strong: #ffffff;
|
||||
--bg-soft: #eef3ff;
|
||||
--ok-bg: #ecf9f0;
|
||||
--ok-ink: #1f7a3f;
|
||||
--warn-bg: #fff6e5;
|
||||
--warn-ink: #9a6400;
|
||||
--danger-bg: #fff1f1;
|
||||
--danger-ink: #982222;
|
||||
--shadow: 0 22px 48px rgba(18, 34, 56, 0.14);
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
||||
color: var(--ink);
|
||||
min-height: 100vh;
|
||||
background:
|
||||
radial-gradient(70% 90% at 8% 8%, rgba(0, 0, 120, 0.14), rgba(0, 0, 120, 0)),
|
||||
radial-gradient(60% 85% at 92% 88%, rgba(163, 32, 32, 0.12), rgba(163, 32, 32, 0)),
|
||||
linear-gradient(160deg, #eef3ff 0%, #f9fbff 48%, #edf4ff 100%);
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.shell {
|
||||
width: min(1380px, 100%);
|
||||
margin: 0 auto;
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(217, 227, 238, 0.9);
|
||||
border-radius: 28px;
|
||||
box-shadow: var(--shadow);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 18px;
|
||||
padding: 22px 24px 18px;
|
||||
border-bottom: 1px solid rgba(217, 227, 238, 0.9);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.95), rgba(248,251,255,0.84));
|
||||
}
|
||||
|
||||
.brand-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
width: 212px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.lang-switch { display:flex; gap:6px; }
|
||||
.lang-btn { border:1px solid var(--line); background:#f8fbff; color:#1f3a5f; border-radius:999px; padding:6px 10px; font-size:12px; font-weight:700; cursor:pointer; }
|
||||
.lang-btn.active { background:var(--brand-blue); border-color:var(--brand-blue); color:#fff; }
|
||||
|
||||
.hero {
|
||||
padding: 0;
|
||||
border-bottom: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hero-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.4fr) minmax(320px, 0.8fr);
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.hero-card,
|
||||
.pulse-card,
|
||||
.controls-card,
|
||||
.table-card,
|
||||
.chart-card,
|
||||
.stat-card {
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
background: var(--panel);
|
||||
border-radius: 22px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.hero-card {
|
||||
padding: 14px;
|
||||
background:
|
||||
radial-gradient(100% 140% at 10% 10%, rgba(31,79,214,0.10), rgba(31,79,214,0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.99), rgba(248,251,255,0.97));
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(0,0,120,0.12);
|
||||
background: rgba(0,0,120,0.05);
|
||||
color: var(--brand-blue);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
margin: 8px 0 4px;
|
||||
font-size: clamp(24px, 3.6vw, 34px);
|
||||
line-height: 1;
|
||||
letter-spacing: -0.04em;
|
||||
color: var(--brand-blue);
|
||||
}
|
||||
|
||||
.hero p {
|
||||
margin: 0;
|
||||
max-width: 760px;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.hero-pills {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.hero-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-height: 34px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid rgba(217, 227, 238, 0.96);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(248,251,255,0.96));
|
||||
color: #294465;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.94);
|
||||
}
|
||||
|
||||
.pulse-card {
|
||||
padding: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
min-height: 100%;
|
||||
background:
|
||||
radial-gradient(120% 120% at 100% 0%, rgba(163,32,32,0.10), rgba(163,32,32,0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.98), rgba(253,247,247,0.96));
|
||||
}
|
||||
|
||||
.activity-card {
|
||||
padding: 18px;
|
||||
background: rgba(255,255,255,0.95);
|
||||
}
|
||||
|
||||
.activity-card .chart {
|
||||
min-height: 150px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.activity-card .bar-wrap {
|
||||
min-height: 104px;
|
||||
}
|
||||
|
||||
.pulse-card h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #1a3359;
|
||||
}
|
||||
|
||||
.pulse-card p {
|
||||
margin: 8px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.pulse-metrics {
|
||||
margin-top: 18px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.pulse-metric {
|
||||
padding: 12px 14px;
|
||||
border-radius: 16px;
|
||||
background: rgba(255,255,255,0.86);
|
||||
border: 1px solid rgba(217, 227, 238, 0.95);
|
||||
}
|
||||
|
||||
.pulse-label {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.pulse-value {
|
||||
margin-top: 5px;
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
color: var(--brand-blue);
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.metrics-grid {
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
padding: 14px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 110px;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 10px 24px rgba(18, 33, 56, 0.04), inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.stat-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: auto -24px -36px auto;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
border-radius: 50%;
|
||||
background: rgba(31, 79, 214, 0.08);
|
||||
}
|
||||
|
||||
.stat-card.red::before { background: rgba(163, 32, 32, 0.08); }
|
||||
.stat-card.gold::before { background: rgba(194, 137, 26, 0.10); }
|
||||
.stat-card.ink::before { background: rgba(19, 34, 56, 0.08); }
|
||||
|
||||
.stat-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.stat-title {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.stat-kicker {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 12px;
|
||||
background: rgba(0, 0, 120, 0.06);
|
||||
color: var(--brand-blue);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.stat-card.red .stat-kicker {
|
||||
background: rgba(163, 32, 32, 0.08);
|
||||
color: var(--brand-red);
|
||||
}
|
||||
|
||||
.stat-card.gold .stat-kicker {
|
||||
background: rgba(194, 137, 26, 0.10);
|
||||
color: #9a6400;
|
||||
}
|
||||
|
||||
.stat-card.ink .stat-kicker {
|
||||
background: rgba(19, 34, 56, 0.08);
|
||||
color: #132238;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
margin-top: 12px;
|
||||
font-size: clamp(24px, 2.6vw, 30px);
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.05em;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.stat-foot {
|
||||
margin-top: 5px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
max-width: 220px;
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
padding: 18px 24px 24px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.top-stack {
|
||||
padding: 12px 24px 0;
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
|
||||
.top-content-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.5fr) minmax(320px, 1fr);
|
||||
gap: 16px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.chart-card,
|
||||
.controls-card,
|
||||
.table-card {
|
||||
padding: 14px;
|
||||
background: rgba(255,255,255,0.94);
|
||||
border-radius: 22px;
|
||||
box-shadow: 0 12px 28px rgba(18, 33, 56, 0.045), inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.section-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.section-head h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #18345f;
|
||||
}
|
||||
|
||||
.section-head p {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.chart {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(14, minmax(0, 1fr));
|
||||
gap: 6px;
|
||||
align-items: end;
|
||||
min-height: 180px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.chart-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bar-wrap {
|
||||
width: 100%;
|
||||
min-height: 124px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.bar {
|
||||
width: 100%;
|
||||
max-width: 34px;
|
||||
background: linear-gradient(180deg, #2b5bda, #071f7d);
|
||||
border-radius: 14px 14px 6px 6px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.28);
|
||||
}
|
||||
|
||||
.bar-value {
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
color: #294465;
|
||||
}
|
||||
|
||||
.bar-label {
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.controls-card {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
width: 100%;
|
||||
border: 1px solid var(--line-strong);
|
||||
border-radius: 16px;
|
||||
padding: 14px 16px;
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
background: rgba(255,255,255,0.98);
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.98);
|
||||
}
|
||||
|
||||
.search-box input:focus {
|
||||
outline: none;
|
||||
border-color: rgba(0, 0, 120, 0.3);
|
||||
box-shadow: 0 0 0 4px rgba(0, 0, 120, 0.08);
|
||||
}
|
||||
|
||||
.search-help {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.55;
|
||||
max-width: 70ch;
|
||||
}
|
||||
|
||||
.control-panel {
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--line);
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.bulk-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin: 0;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.bulk-info {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.table-card {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 26px;
|
||||
box-shadow: 0 16px 48px rgba(18, 33, 56, 0.06), inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.table-controls {
|
||||
padding: 14px 18px 14px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(244,248,255,0.96));
|
||||
}
|
||||
|
||||
.table-controls-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 14px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.control-stack {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
padding: 14px;
|
||||
border: 1px solid rgba(217, 227, 238, 0.95);
|
||||
border-radius: 18px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(249,251,255,0.95));
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.9);
|
||||
}
|
||||
|
||||
.search-card {
|
||||
padding: 18px;
|
||||
background: rgba(255,255,255,0.92);
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
border-radius: 22px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.table-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 16px 18px 14px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(245,249,255,0.96));
|
||||
}
|
||||
|
||||
.table-head h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
color: #18345f;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.table-head p {
|
||||
margin: 5px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.table-head-meta {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(0, 0, 120, 0.10);
|
||||
background: rgba(0, 0, 120, 0.05);
|
||||
color: var(--brand-blue);
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.table-wrap {
|
||||
overflow-x: auto;
|
||||
padding: 0 18px 18px;
|
||||
background: linear-gradient(180deg, rgba(249,251,255,0.72), rgba(255,255,255,0));
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 12px;
|
||||
font-size: 14px;
|
||||
min-width: 980px;
|
||||
}
|
||||
|
||||
thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
background: rgba(245,248,252,0.94);
|
||||
color: #5b6b7f;
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 800;
|
||||
padding: 12px 14px;
|
||||
border-top: 1px solid var(--line);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
thead th:first-child {
|
||||
border-left: 1px solid var(--line);
|
||||
border-radius: 14px 0 0 14px;
|
||||
}
|
||||
|
||||
thead th:last-child {
|
||||
border-right: 1px solid var(--line);
|
||||
border-radius: 0 14px 14px 0;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
background: rgba(255,255,255,0.98);
|
||||
border-top: 1px solid var(--line);
|
||||
border-bottom: 1px solid var(--line);
|
||||
padding: 15px 14px;
|
||||
vertical-align: middle;
|
||||
box-shadow: 0 8px 22px rgba(26, 51, 89, 0.035);
|
||||
}
|
||||
|
||||
tbody td:first-child {
|
||||
border-left: 1px solid var(--line);
|
||||
border-radius: 18px 0 0 18px;
|
||||
}
|
||||
|
||||
tbody td:last-child {
|
||||
border-right: 1px solid var(--line);
|
||||
border-radius: 0 18px 18px 0;
|
||||
}
|
||||
|
||||
tbody tr:hover td {
|
||||
background: #fbfdff;
|
||||
border-color: #cad7e8;
|
||||
box-shadow: 0 12px 26px rgba(26, 51, 89, 0.06);
|
||||
}
|
||||
|
||||
.select-col {
|
||||
width: 42px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
th.select-col,
|
||||
td.select-col {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
td.actions-cell {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
td.intro-panel {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.select-col input[type="checkbox"] {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.kind-pill,
|
||||
.status-badge,
|
||||
.doc-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
min-height: 38px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 14px;
|
||||
font-weight: 800;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.01em;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
border: 1px solid rgba(217, 227, 238, 0.96);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(248,251,255,0.96));
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.94);
|
||||
}
|
||||
|
||||
.kind-pill {
|
||||
color: #294465;
|
||||
}
|
||||
|
||||
.kind-pill.onboarding {
|
||||
background: linear-gradient(180deg, rgba(245,247,255,0.98), rgba(236,241,255,0.98));
|
||||
border-color: rgba(0, 0, 120, 0.12);
|
||||
color: var(--brand-blue);
|
||||
}
|
||||
|
||||
.kind-pill.offboarding {
|
||||
background: linear-gradient(180deg, rgba(255,247,247,0.98), rgba(255,240,240,0.98));
|
||||
border-color: rgba(163, 32, 32, 0.14);
|
||||
color: var(--brand-red);
|
||||
}
|
||||
|
||||
.name-cell {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.person-name {
|
||||
font-weight: 800;
|
||||
color: var(--ink);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.person-meta {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mail-link {
|
||||
color: #294465;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.mail-link:hover { text-decoration: underline; }
|
||||
|
||||
.status-badge.ok {
|
||||
background: linear-gradient(180deg, #f3fcf6, #e8f8ee);
|
||||
color: var(--ok-ink);
|
||||
border-color: #cdeed8;
|
||||
}
|
||||
|
||||
.status-badge.pending {
|
||||
background: linear-gradient(180deg, #fffaf0, #fff3dc);
|
||||
color: var(--warn-ink);
|
||||
border-color: #f3dfb5;
|
||||
}
|
||||
|
||||
.doc-link {
|
||||
color: var(--brand-blue);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(244,248,255,0.98));
|
||||
border-color: rgba(0, 0, 120, 0.12);
|
||||
}
|
||||
|
||||
.doc-link:hover {
|
||||
background: linear-gradient(180deg, rgba(248,251,255,0.99), rgba(238,244,255,0.98));
|
||||
border-color: rgba(0, 0, 120, 0.18);
|
||||
}
|
||||
|
||||
.actions-cell { white-space: normal; }
|
||||
.inline-form { display: inline; margin: 0; }
|
||||
.inline-delete { display: inline-flex; align-items: center; }
|
||||
.inline-delete .btn { min-height: 38px; display: inline-flex; align-items: center; justify-content: center; }
|
||||
.intro-panel { min-width: 260px; }
|
||||
|
||||
details {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(180deg, #ffffff, #f8fbff);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
details[open] {
|
||||
border-color: #cad7e8;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.95);
|
||||
}
|
||||
|
||||
.intro-toggle {
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
padding: 12px 14px;
|
||||
font-weight: 800;
|
||||
color: #18345f;
|
||||
background: rgba(255,255,255,0.65);
|
||||
}
|
||||
|
||||
.intro-toggle::after {
|
||||
content: "+";
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
color: var(--brand-blue);
|
||||
}
|
||||
|
||||
details[open] .intro-toggle::after { content: "−"; }
|
||||
.intro-toggle::-webkit-details-marker { display: none; }
|
||||
|
||||
.intro-menu {
|
||||
padding: 0 14px 14px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.intro-group {
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.intro-group:first-child {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.intro-group-title {
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.intro-actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.intro-meta {
|
||||
padding: 0 14px 14px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.flash {
|
||||
margin: 0 24px 14px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(217, 227, 238, 0.9);
|
||||
background: rgba(248, 251, 255, 0.95);
|
||||
}
|
||||
|
||||
.flash.success { border-color: #bfe6c9; background: #edf9f1; color: #116634; }
|
||||
.flash.warning { border-color: #f5d8a8; background: #fff8ea; color: #8a5a00; }
|
||||
.flash.error { border-color: #f4c7c7; background: #fff1f1; color: #8e1e1e; }
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
padding: 26px 14px;
|
||||
}
|
||||
|
||||
.footer-bar {
|
||||
padding: 0 24px 24px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.footer-note {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
.hero-grid,
|
||||
.metrics-grid,
|
||||
.top-content-grid,
|
||||
.table-controls-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
body { padding: 14px; }
|
||||
.topbar,
|
||||
.hero,
|
||||
.metrics-grid,
|
||||
.content-grid,
|
||||
.footer-bar { padding-left: 16px; padding-right: 16px; }
|
||||
.topbar { flex-direction: column; }
|
||||
.quick-actions { justify-content: flex-start; }
|
||||
.table-wrap { padding-left: 12px; padding-right: 12px; }
|
||||
}
|
||||
6
backend/workflows/static/workflows/css/success_pages.css
Normal file
6
backend/workflows/static/workflows/css/success_pages.css
Normal file
@@ -0,0 +1,6 @@
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 24px; }
|
||||
.shell { background: #fff; border: 1px solid #d7e0ea; border-radius: 16px; padding: 20px; box-shadow: 0 16px 36px rgba(18,34,56,0.10); }
|
||||
h1 { margin: 0 0 10px; color: #000078; }
|
||||
p { margin: 0 0 10px; }
|
||||
code { background: #f4f6fa; padding: 2px 6px; border-radius: 6px; }
|
||||
.actions { display:flex; gap:8px; flex-wrap:wrap; margin-top: 14px; }
|
||||
51
backend/workflows/static/workflows/js/offboarding_form.js
Normal file
51
backend/workflows/static/workflows/js/offboarding_form.js
Normal file
@@ -0,0 +1,51 @@
|
||||
(function () {
|
||||
function byName(name) {
|
||||
return document.querySelector('[name="' + name + '"]');
|
||||
}
|
||||
|
||||
function slugifyForEmail(value) {
|
||||
const map = { 'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'ß': 'ss' };
|
||||
const lower = (value || '').toLowerCase();
|
||||
const mapped = lower.replace(/[äöüß]/g, function (m) { return map[m] || m; });
|
||||
return mapped
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/[^a-z0-9]+/g, '.')
|
||||
.replace(/^\.+|\.+$/g, '')
|
||||
.replace(/\.{2,}/g, '.');
|
||||
}
|
||||
|
||||
function extractLastName(fullName) {
|
||||
const parts = (fullName || '').trim().split(/\s+/).filter(Boolean);
|
||||
return parts.length ? parts[parts.length - 1] : '';
|
||||
}
|
||||
|
||||
const fullName = byName('full_name');
|
||||
const workEmail = byName('work_email');
|
||||
if (!fullName || !workEmail) return;
|
||||
|
||||
let lastSuggested = '';
|
||||
let userEditedEmail = false;
|
||||
|
||||
function suggestEmail() {
|
||||
const lastName = extractLastName(fullName.value);
|
||||
const slug = slugifyForEmail(lastName);
|
||||
if (!slug) return;
|
||||
const suggestion = slug + '@tub.co';
|
||||
const current = (workEmail.value || '').trim();
|
||||
if (!userEditedEmail || current === '' || current === lastSuggested) {
|
||||
workEmail.value = suggestion;
|
||||
lastSuggested = suggestion;
|
||||
}
|
||||
}
|
||||
|
||||
workEmail.addEventListener('input', function () {
|
||||
const current = (workEmail.value || '').trim();
|
||||
userEditedEmail = current !== '' && current !== lastSuggested;
|
||||
});
|
||||
|
||||
fullName.addEventListener('input', suggestEmail);
|
||||
fullName.addEventListener('change', suggestEmail);
|
||||
fullName.addEventListener('blur', suggestEmail);
|
||||
suggestEmail();
|
||||
}());
|
||||
253
backend/workflows/static/workflows/js/onboarding_form.js
Normal file
253
backend/workflows/static/workflows/js/onboarding_form.js
Normal file
@@ -0,0 +1,253 @@
|
||||
(function () {
|
||||
const pages = Array.from(document.querySelectorAll('.page'));
|
||||
const navItems = Array.from(document.querySelectorAll('.step-item'));
|
||||
const btnPrev = document.getElementById('btn-prev');
|
||||
const btnNext = document.getElementById('btn-next');
|
||||
const btnSubmit = document.getElementById('btn-submit');
|
||||
const form = document.getElementById('onboarding-form');
|
||||
let current = 0;
|
||||
form.setAttribute('novalidate', 'novalidate');
|
||||
|
||||
function byName(name) { return document.querySelector('[name="' + name + '"]'); }
|
||||
function toggle(id, state) {
|
||||
const el = document.getElementById(id);
|
||||
if (!el) return;
|
||||
el.classList.toggle('hidden', !state);
|
||||
}
|
||||
|
||||
function syncConditionals() {
|
||||
const orderCards = byName('order_business_cards');
|
||||
toggle('business-card-box', orderCards && orderCards.checked);
|
||||
|
||||
const employmentType = byName('employment_type');
|
||||
toggle('employment-end-box', employmentType && employmentType.value === 'befristet');
|
||||
|
||||
const groupMailbox = byName('group_mailboxes_required_choice');
|
||||
toggle('group-mailboxes-box', groupMailbox && groupMailbox.value === 'ja');
|
||||
|
||||
const extraHardware = byName('additional_hardware_needed_choice');
|
||||
toggle('extra-hardware-box', extraHardware && extraHardware.value === 'ja');
|
||||
|
||||
const extraSoftware = byName('additional_software_needed_choice');
|
||||
toggle('extra-software-box', extraSoftware && extraSoftware.value === 'ja');
|
||||
|
||||
const extraAccess = byName('additional_access_needed_choice');
|
||||
toggle('extra-access-box', extraAccess && extraAccess.value === 'ja');
|
||||
|
||||
const successor = byName('successor_required_choice');
|
||||
const showSuccessor = successor && successor.value === 'ja';
|
||||
toggle('successor-box', showSuccessor);
|
||||
|
||||
const inheritPhone = byName('inherit_phone_number_choice');
|
||||
const hidePhone = showSuccessor && inheritPhone && inheritPhone.value === 'ja';
|
||||
toggle('phone-box', !hidePhone);
|
||||
|
||||
// Hidden conditional groups must not block submit with invisible required fields.
|
||||
document.querySelectorAll('.field-group').forEach(function (group) {
|
||||
const hidden = group.classList.contains('hidden');
|
||||
group.querySelectorAll('input, select, textarea').forEach(function (el) {
|
||||
if (el.type === 'hidden' || el.disabled) return;
|
||||
if (hidden) {
|
||||
if (el.required) {
|
||||
el.dataset.requiredOriginal = '1';
|
||||
el.required = false;
|
||||
}
|
||||
} else if (el.dataset.requiredOriginal === '1') {
|
||||
el.required = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function slugifyForEmail(value) {
|
||||
const map = { 'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'ß': 'ss' };
|
||||
const lower = (value || '').toLowerCase();
|
||||
const mapped = lower.replace(/[äöüß]/g, function (m) { return map[m] || m; });
|
||||
return mapped
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/[^a-z0-9]+/g, '.')
|
||||
.replace(/^\.+|\.+$/g, '')
|
||||
.replace(/\.{2,}/g, '.');
|
||||
}
|
||||
|
||||
function setupWorkEmailAutofill() {
|
||||
const lastName = byName('last_name');
|
||||
const workEmail = byName('work_email');
|
||||
if (!lastName || !workEmail) return;
|
||||
|
||||
let lastSuggested = '';
|
||||
let userEditedEmail = !!(workEmail.value && workEmail.value.trim());
|
||||
|
||||
function suggestEmail() {
|
||||
const slug = slugifyForEmail(lastName.value);
|
||||
if (!slug) return;
|
||||
const suggestion = slug + '@tub.co';
|
||||
if (!userEditedEmail || workEmail.value === '' || workEmail.value === lastSuggested) {
|
||||
workEmail.value = suggestion;
|
||||
lastSuggested = suggestion;
|
||||
}
|
||||
}
|
||||
|
||||
workEmail.addEventListener('input', function () {
|
||||
const current = (workEmail.value || '').trim();
|
||||
userEditedEmail = current !== '' && current !== lastSuggested;
|
||||
});
|
||||
|
||||
lastName.addEventListener('input', suggestEmail);
|
||||
suggestEmail();
|
||||
}
|
||||
|
||||
function setupBusinessCardAutofill() {
|
||||
const checkbox = byName('order_business_cards');
|
||||
const firstName = byName('first_name');
|
||||
const lastName = byName('last_name');
|
||||
const jobTitle = byName('job_title');
|
||||
const workEmail = byName('work_email');
|
||||
const cardName = byName('business_card_name');
|
||||
const cardTitle = byName('business_card_title');
|
||||
const cardEmail = byName('business_card_email');
|
||||
if (!checkbox || !cardName || !cardTitle || !cardEmail) return;
|
||||
const cardBox = document.getElementById('business-card-box');
|
||||
|
||||
function suggestionName() {
|
||||
const first = (firstName && firstName.value || '').trim();
|
||||
const last = (lastName && lastName.value || '').trim();
|
||||
return [first, last].filter(Boolean).join(' ').trim();
|
||||
}
|
||||
|
||||
function setField(field, value, force) {
|
||||
if (!field || !value) return;
|
||||
const current = (field.value || '').trim();
|
||||
const autoMarked = field.dataset.autofilled === '1';
|
||||
if (force || !current || autoMarked) {
|
||||
field.value = value;
|
||||
field.dataset.autofilled = '1';
|
||||
}
|
||||
}
|
||||
|
||||
function applyDefaults(force) {
|
||||
if (!checkbox.checked) return;
|
||||
const name = suggestionName();
|
||||
const title = (jobTitle && jobTitle.value || '').trim();
|
||||
const email = (workEmail && workEmail.value || '').trim();
|
||||
setField(cardName, name, force);
|
||||
setField(cardTitle, title, force);
|
||||
setField(cardEmail, email, force);
|
||||
}
|
||||
|
||||
[cardName, cardTitle, cardEmail].forEach(function (field) {
|
||||
field.addEventListener('input', function () {
|
||||
field.dataset.autofilled = '0';
|
||||
});
|
||||
});
|
||||
|
||||
if (cardBox) {
|
||||
const grid = cardBox.querySelector('.grid-2');
|
||||
if (grid && !document.getElementById('business-card-autofill-btn')) {
|
||||
const actionWrap = document.createElement('div');
|
||||
actionWrap.className = 'field field-full';
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.id = 'business-card-autofill-btn';
|
||||
btn.className = 'btn btn-secondary';
|
||||
btn.textContent = 'Visitenkarten-Felder automatisch ausfüllen';
|
||||
btn.addEventListener('click', function () {
|
||||
applyDefaults(true);
|
||||
});
|
||||
actionWrap.appendChild(btn);
|
||||
grid.insertBefore(actionWrap, grid.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
// Manual-only behavior: fill only when button is clicked.
|
||||
}
|
||||
|
||||
function setupChecklistToggles() {
|
||||
document.querySelectorAll('[data-checklist-toggle]').forEach(function (button) {
|
||||
const panel = button.closest('.itsetup-checklist-panel');
|
||||
if (!panel) return;
|
||||
|
||||
const getCheckboxes = function () {
|
||||
return Array.from(panel.querySelectorAll('input[type="checkbox"]'));
|
||||
};
|
||||
|
||||
const refreshButtonLabel = function () {
|
||||
const checkboxes = getCheckboxes();
|
||||
if (!checkboxes.length) return;
|
||||
const allChecked = checkboxes.every(function (box) { return box.checked; });
|
||||
button.textContent = allChecked ? (button.dataset.labelClear || 'Auswahl aufheben') : (button.dataset.labelSelect || 'Alle auswählen');
|
||||
};
|
||||
|
||||
button.addEventListener('click', function () {
|
||||
const checkboxes = getCheckboxes();
|
||||
if (!checkboxes.length) return;
|
||||
const shouldCheck = checkboxes.some(function (box) { return !box.checked; });
|
||||
checkboxes.forEach(function (box) {
|
||||
box.checked = shouldCheck;
|
||||
box.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
});
|
||||
refreshButtonLabel();
|
||||
});
|
||||
|
||||
getCheckboxes().forEach(function (box) {
|
||||
box.addEventListener('change', refreshButtonLabel);
|
||||
});
|
||||
|
||||
refreshButtonLabel();
|
||||
});
|
||||
}
|
||||
|
||||
function setupChecklistColumns() {
|
||||
document.querySelectorAll('.itsetup-checklist-body > [id^="id_"]').forEach(function (container) {
|
||||
const itemCount = container.querySelectorAll(':scope > div').length;
|
||||
container.classList.toggle('cols-3', itemCount > 8);
|
||||
});
|
||||
}
|
||||
|
||||
function updateStep() {
|
||||
pages.forEach((p, i) => p.classList.toggle('active', i === current));
|
||||
navItems.forEach((n, i) => n.classList.toggle('active', i === current));
|
||||
btnPrev.disabled = current === 0;
|
||||
const last = current === pages.length - 1;
|
||||
btnNext.classList.toggle('hidden', last);
|
||||
btnSubmit.classList.toggle('hidden', !last);
|
||||
}
|
||||
|
||||
function jumpToFirstErrorPage() {
|
||||
const firstError = document.querySelector('.errorlist');
|
||||
if (!firstError) return;
|
||||
const page = firstError.closest('.page');
|
||||
if (!page) return;
|
||||
const step = Number(page.getAttribute('data-step') || '1') - 1;
|
||||
current = Math.max(0, step);
|
||||
}
|
||||
|
||||
document.addEventListener('change', syncConditionals);
|
||||
navItems.forEach((n, idx) => {
|
||||
n.addEventListener('click', function () { current = idx; updateStep(); });
|
||||
n.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
current = idx;
|
||||
updateStep();
|
||||
}
|
||||
});
|
||||
});
|
||||
btnPrev.addEventListener('click', function () { if (current > 0) { current -= 1; updateStep(); } });
|
||||
btnNext.addEventListener('click', function () { if (current < pages.length - 1) { current += 1; updateStep(); } });
|
||||
btnSubmit.addEventListener('click', function () {
|
||||
syncConditionals();
|
||||
btnSubmit.disabled = true;
|
||||
btnSubmit.textContent = btnSubmit.dataset.loadingLabel || 'Wird gesendet...';
|
||||
form.submit();
|
||||
});
|
||||
|
||||
syncConditionals();
|
||||
setupWorkEmailAutofill();
|
||||
setupBusinessCardAutofill();
|
||||
setupChecklistToggles();
|
||||
setupChecklistColumns();
|
||||
jumpToFirstErrorPage();
|
||||
updateStep();
|
||||
})();
|
||||
20
backend/workflows/static/workflows/js/requests_dashboard.js
Normal file
20
backend/workflows/static/workflows/js/requests_dashboard.js
Normal file
@@ -0,0 +1,20 @@
|
||||
(function () {
|
||||
const selectAll = document.getElementById('select-all');
|
||||
const rowChecks = Array.from(document.querySelectorAll('.row-select'));
|
||||
const selectedCount = document.getElementById('selected-count');
|
||||
if (!selectAll || !selectedCount || !rowChecks.length) return;
|
||||
|
||||
function updateCount() {
|
||||
const checked = rowChecks.filter((c) => c.checked).length;
|
||||
selectedCount.textContent = String(checked);
|
||||
selectAll.checked = checked > 0 && checked === rowChecks.length;
|
||||
selectAll.indeterminate = checked > 0 && checked < rowChecks.length;
|
||||
}
|
||||
|
||||
selectAll.addEventListener('change', function () {
|
||||
rowChecks.forEach((c) => { c.checked = selectAll.checked; });
|
||||
updateCount();
|
||||
});
|
||||
rowChecks.forEach((c) => c.addEventListener('change', updateCount));
|
||||
updateCount();
|
||||
})();
|
||||
52
backend/workflows/static/workflows/js/welcome_emails.js
Normal file
52
backend/workflows/static/workflows/js/welcome_emails.js
Normal file
@@ -0,0 +1,52 @@
|
||||
(function () {
|
||||
const selectAll = document.getElementById('select-all-welcome');
|
||||
const rowChecks = Array.from(document.querySelectorAll('.welcome-select'));
|
||||
const selectedCount = document.getElementById('selected-count');
|
||||
const selectedIds = document.getElementById('selected_ids');
|
||||
const bulkForm = document.getElementById('welcome-bulk-form');
|
||||
const bulkAction = document.getElementById('bulk_action');
|
||||
|
||||
function currentSelected() {
|
||||
return rowChecks.filter((c) => c.checked).map((c) => c.value);
|
||||
}
|
||||
|
||||
function syncState() {
|
||||
const ids = currentSelected();
|
||||
selectedCount.textContent = String(ids.length);
|
||||
selectedIds.value = ids.join(',');
|
||||
if (!rowChecks.length) {
|
||||
selectAll.checked = false;
|
||||
selectAll.indeterminate = false;
|
||||
return;
|
||||
}
|
||||
selectAll.checked = ids.length > 0 && ids.length === rowChecks.length;
|
||||
selectAll.indeterminate = ids.length > 0 && ids.length < rowChecks.length;
|
||||
}
|
||||
|
||||
selectAll.addEventListener('change', function () {
|
||||
rowChecks.forEach((c) => { c.checked = selectAll.checked; });
|
||||
syncState();
|
||||
});
|
||||
|
||||
rowChecks.forEach((c) => c.addEventListener('change', syncState));
|
||||
bulkForm.addEventListener('submit', syncState);
|
||||
|
||||
window.confirmBulkAction = function () {
|
||||
syncState();
|
||||
const count = currentSelected().length;
|
||||
if (!count) {
|
||||
alert(bulkForm.dataset.alertEmpty || 'Bitte mindestens einen Welcome-Eintrag auswählen.');
|
||||
return false;
|
||||
}
|
||||
const action = bulkAction.value;
|
||||
if (action === 'delete') {
|
||||
return confirm(bulkForm.dataset.confirmDelete || 'Ausgewählte Welcome-Einträge wirklich löschen?');
|
||||
}
|
||||
if (action === 'pause') {
|
||||
return confirm(bulkForm.dataset.confirmPause || 'Ausgewählte Welcome-Einträge pausieren?');
|
||||
}
|
||||
return confirm(bulkForm.dataset.confirmSend || 'Ausgewählte Welcome-Einträge sofort senden?');
|
||||
};
|
||||
|
||||
syncState();
|
||||
})();
|
||||
@@ -3,26 +3,20 @@
|
||||
|
||||
{% block title %}{% trans "Anmeldung" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; min-height: 100vh; background: linear-gradient(160deg, #eef6ff, #fff3f3); padding: 24px; }
|
||||
.card { width: min(420px, calc(100% - 28px)); margin: 0 auto; background: #fff; border: 1px solid #d9e3f0; border-radius: 14px; padding: 20px; box-shadow: 0 12px 30px rgba(28, 45, 79, 0.12); }
|
||||
h1 { margin: 0 0 8px; font-size: 24px; }
|
||||
p { margin: 0 0 14px; color: #607086; }
|
||||
.field { margin-bottom: 12px; }
|
||||
label { display: block; font-weight: 600; margin-bottom: 6px; }
|
||||
input { width: 100%; padding: 10px; box-sizing: border-box; border: 1px solid #cbd5e1; border-radius: 8px; }
|
||||
.btn { width: 100%; }
|
||||
.errorlist { color: #b91c1c; margin: 6px 0; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block shell_header %}
|
||||
{% include 'workflows/includes/app_header.html' %}
|
||||
{% include 'workflows/includes/app_header.html' with header_inside_shell=1 %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/login.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
<div class="card"><h1>{% trans "Anmeldung" %}</h1>
|
||||
<section class="login-shell-body">
|
||||
<div class="login-card">
|
||||
<h1>{% trans "Anmeldung" %}</h1>
|
||||
<p>{% trans "Bitte melden Sie sich mit Ihrem Benutzerkonto an." %}</p>
|
||||
|
||||
<form method="post" action="/accounts/login/">
|
||||
@@ -35,6 +29,5 @@
|
||||
<button class="btn btn-primary" type="submit">{% trans "Anmelden" %}</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -3,25 +3,10 @@
|
||||
|
||||
{% block title %}Developer Handbook{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 20px; }
|
||||
.shell { max-width: 1120px; margin: 0 auto; background: #fff; border: 1px solid #d7e0ea; border-radius: 14px; padding: 18px; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; margin: 0 0 10px; display: block; }
|
||||
.top { display: flex; justify-content: space-between; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
|
||||
h1 { margin: 0; color: #000078; font-size: 30px; }
|
||||
.sub { margin: 8px 0 16px; color: #5f6f85; }
|
||||
.toc { border: 1px solid #d7e0ea; border-radius: 10px; padding: 10px; background: #f7fbff; margin-bottom: 16px; }
|
||||
.toc a { color: #0b4da2; text-decoration: none; margin-right: 10px; white-space: nowrap; }
|
||||
h2 { margin: 20px 0 8px; color: #113a74; border-bottom: 1px solid #e1e8f2; padding-bottom: 4px; }
|
||||
h3 { margin: 14px 0 6px; color: #183f77; }
|
||||
ul { margin: 8px 0 12px 20px; }
|
||||
li { margin: 4px 0; }
|
||||
code { background: #f1f5fb; border: 1px solid #dce6f3; border-radius: 6px; padding: 2px 6px; }
|
||||
pre { background: #f7fbff; border: 1px solid #dce6f3; border-radius: 10px; padding: 10px; overflow-x: auto; }
|
||||
.box { border: 1px solid #d7e0ea; border-radius: 10px; padding: 10px; background: #fcfdff; margin: 8px 0 12px; }
|
||||
.note { border-left: 4px solid #000078; padding: 8px 10px; background: #f4f8ff; margin: 10px 0; }
|
||||
</style>
|
||||
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/docs_pages.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
|
||||
@@ -3,24 +3,10 @@
|
||||
|
||||
{% block title %}{% trans "Handbook" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 20px; }
|
||||
.shell { max-width: 1120px; margin: 0 auto; background: #fff; border: 1px solid #d7e0ea; border-radius: 14px; padding: 18px; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; margin: 0 0 10px; display: block; }
|
||||
.top { display: flex; justify-content: space-between; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
|
||||
h1 { margin: 0; color: #000078; font-size: 30px; }
|
||||
.sub { margin: 8px 0 18px; color: #5f6f85; max-width: 760px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(3, minmax(260px, 1fr)); gap: 14px; }
|
||||
.card { border: 1px solid #d7e0ea; border-radius: 14px; background: #fcfdff; padding: 16px; }
|
||||
.eyebrow { display: inline-block; padding: 5px 10px; border-radius: 999px; background: #eef4ff; color: #244a8f; border: 1px solid #d5e2f9; font-size: 12px; font-weight: 700; margin-bottom: 10px; }
|
||||
h2 { margin: 0 0 8px; color: #113a74; }
|
||||
p { margin: 0 0 14px; color: #5f6f85; }
|
||||
ul { margin: 0 0 14px 18px; color: #334155; }
|
||||
li { margin: 4px 0; }
|
||||
.actions { display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
@media (max-width: 760px) { .grid { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/docs_pages.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
|
||||
@@ -3,441 +3,10 @@
|
||||
|
||||
{% block title %}{% trans "TUBCO Onboarding & Offboarding Portal" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
:root {
|
||||
--brand-blue: #000078;
|
||||
--brand-red: #8c1d1d;
|
||||
--ink: #102039;
|
||||
--muted: #5f6f85;
|
||||
--line: #d8e1ee;
|
||||
--panel: #ffffff;
|
||||
--bg-soft: #eff4ff;
|
||||
--ok-bg: #effaf2;
|
||||
--ok-ink: #166534;
|
||||
--warn-bg: #fff6ea;
|
||||
--warn-ink: #8a4f00;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
||||
color: var(--ink);
|
||||
background:
|
||||
radial-gradient(80% 120% at 85% 8%, rgba(0, 0, 120, 0.12), rgba(0, 0, 120, 0)),
|
||||
radial-gradient(70% 90% at 8% 92%, rgba(140, 29, 29, 0.10), rgba(140, 29, 29, 0)),
|
||||
linear-gradient(165deg, #eef3ff, #f7f9ff 48%, #f0f5ff);
|
||||
min-height: 100vh;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.shell {
|
||||
width: min(1380px, 100%);
|
||||
margin: 0 auto;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 20px 44px rgba(16, 32, 57, 0.13);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
padding: 18px 22px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.brand-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
flex: 0 0 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
width: 210px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.lang-switch { display:flex; gap:6px; }
|
||||
.lang-btn { border:1px solid var(--line); background:#f8fbff; color:#1f3a5f; border-radius:999px; padding:6px 10px; font-size:12px; font-weight:700; cursor:pointer; }
|
||||
.lang-btn.active { background:var(--brand-blue); border-color:var(--brand-blue); color:#fff; }
|
||||
|
||||
.hero {
|
||||
padding: 24px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(0, 0, 120, 0.08), rgba(0, 0, 120, 0) 44%),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.96), rgba(246,250,255,0.92));
|
||||
}
|
||||
|
||||
.hero-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 18px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.hero-card,
|
||||
.hero-sidecard {
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
background: rgba(255,255,255,0.92);
|
||||
border-radius: 22px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.hero-card {
|
||||
padding: 24px;
|
||||
background:
|
||||
radial-gradient(100% 140% at 10% 10%, rgba(31,79,214,0.12), rgba(31,79,214,0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.98), rgba(247,250,255,0.95));
|
||||
}
|
||||
|
||||
.hero-sidecard {
|
||||
padding: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background:
|
||||
radial-gradient(120% 120% at 100% 0%, rgba(163,32,32,0.10), rgba(163,32,32,0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.98), rgba(253,247,247,0.96));
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(0,0,120,0.12);
|
||||
background: rgba(0,0,120,0.05);
|
||||
color: var(--brand-blue);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
margin: 14px 0 8px;
|
||||
font-size: clamp(30px, 5vw, 46px);
|
||||
line-height: 1;
|
||||
letter-spacing: -0.04em;
|
||||
color: var(--brand-blue);
|
||||
}
|
||||
|
||||
.hero p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
max-width: 720px;
|
||||
font-size: 15px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.status-row {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.status-pill {
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--line);
|
||||
background: #fff;
|
||||
color: #30445f;
|
||||
padding: 8px 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.status-pill.ok {
|
||||
background: var(--ok-bg);
|
||||
color: var(--ok-ink);
|
||||
border-color: #c7ecd2;
|
||||
}
|
||||
|
||||
.status-pill.warn {
|
||||
background: var(--warn-bg);
|
||||
color: var(--warn-ink);
|
||||
border-color: #f7dfbb;
|
||||
}
|
||||
|
||||
.hero-sidecard h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #1a3359;
|
||||
}
|
||||
|
||||
.hero-sidecard p {
|
||||
margin: 8px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.hero-metrics {
|
||||
margin-top: 18px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.hero-metric {
|
||||
padding: 12px 14px;
|
||||
border-radius: 16px;
|
||||
background: rgba(255,255,255,0.86);
|
||||
border: 1px solid rgba(217, 227, 238, 0.95);
|
||||
}
|
||||
|
||||
.hero-metric-label {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.hero-metric-value {
|
||||
margin-top: 5px;
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
color: var(--brand-blue);
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 20px 22px 24px;
|
||||
}
|
||||
|
||||
.section-head {
|
||||
margin: 0 0 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
align-items: flex-end;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.section-head h2 {
|
||||
margin: 0;
|
||||
font-size: 19px;
|
||||
color: #172b4a;
|
||||
}
|
||||
|
||||
.section-head p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.apps-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.app-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
border-radius: 22px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(247,250,255,0.95));
|
||||
padding: 18px;
|
||||
min-height: 222px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.app-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: auto -24px -38px auto;
|
||||
width: 118px;
|
||||
height: 118px;
|
||||
border-radius: 50%;
|
||||
background: rgba(31, 79, 214, 0.08);
|
||||
}
|
||||
|
||||
.app-card.primary {
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(242,247,255,0.97));
|
||||
}
|
||||
|
||||
.app-card.red {
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(255,245,245,0.97));
|
||||
}
|
||||
|
||||
.app-card.red::before { background: rgba(163, 32, 32, 0.08); }
|
||||
|
||||
.app-card .top-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.accent {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 14px;
|
||||
background: rgba(0, 0, 120, 0.06);
|
||||
color: var(--brand-blue);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.04em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.accent.red {
|
||||
background: rgba(163, 32, 32, 0.08);
|
||||
color: var(--brand-red);
|
||||
}
|
||||
|
||||
.app-title {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.03em;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.app-text {
|
||||
margin: 10px 0 12px;
|
||||
color: #5a6a81;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
max-width: 34ch;
|
||||
}
|
||||
|
||||
.tag-row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
border: 1px solid rgba(217, 227, 238, 0.96);
|
||||
border-radius: 14px;
|
||||
padding: 7px 10px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(248,251,255,0.96));
|
||||
color: #486183;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.admin-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.admin-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
border-radius: 18px;
|
||||
padding: 14px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(247,250,255,0.96));
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.admin-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: auto -18px -30px auto;
|
||||
width: 84px;
|
||||
height: 84px;
|
||||
border-radius: 50%;
|
||||
background: rgba(31, 79, 214, 0.06);
|
||||
}
|
||||
|
||||
.admin-card h3 {
|
||||
margin: 0 0 7px;
|
||||
font-size: 15px;
|
||||
color: #18345f;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.admin-card p {
|
||||
margin: 0 0 11px;
|
||||
font-size: 12px;
|
||||
color: #607088;
|
||||
min-height: 34px;
|
||||
line-height: 1.45;
|
||||
max-width: 26ch;
|
||||
}
|
||||
|
||||
.msg {
|
||||
border-radius: 10px;
|
||||
padding: 10px 12px;
|
||||
margin: 0 0 14px;
|
||||
border: 1px solid #d6e1ef;
|
||||
background: #f8fbff;
|
||||
color: #1f3a5f;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.msg.error {
|
||||
border-color: #fecaca;
|
||||
background: #fff1f2;
|
||||
color: #991b1b;
|
||||
}
|
||||
|
||||
.footer-note {
|
||||
margin-top: 16px;
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 12px;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
.hero-grid { grid-template-columns: 1fr; }
|
||||
.apps-grid { grid-template-columns: 1fr 1fr; }
|
||||
.admin-grid { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
body { padding: 12px; }
|
||||
.topbar, .hero, .main { padding-left: 14px; padding-right: 14px; }
|
||||
.hero h1 { font-size: 28px; }
|
||||
.apps-grid, .admin-grid { grid-template-columns: 1fr; }
|
||||
.quick-actions { justify-content: flex-start; }
|
||||
}
|
||||
</style>
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/home.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
|
||||
@@ -3,70 +3,10 @@
|
||||
|
||||
{% block title %}{% trans "Integrationen Setup" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #0f172a; padding: 20px; }
|
||||
.shell { max-width: 980px; margin: 0 auto; background: #fff; border: 1px solid #d8e3f0; border-radius: 14px; padding: 16px; }
|
||||
.topbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; display: block; }
|
||||
h1 { margin: 12px 0 6px; color: #000078; }
|
||||
.sub { margin: 0 0 12px; color: #54657c; }
|
||||
.switch { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
|
||||
.switch .tab {
|
||||
border: 1px solid #c9d6e7; border-radius: 999px; padding: 8px 14px; text-decoration: none;
|
||||
color: #1f2f49; font-weight: 700; background: #f6f9ff;
|
||||
}
|
||||
.switch .tab.active { background: #000078; color: #fff; border-color: #000078; }
|
||||
.msg { border-radius: 10px; padding: 10px 12px; margin: 0 0 12px; border: 1px solid #d6e1ef; background: #f8fbff; color: #1f3a5f; }
|
||||
.msg.error { border-color: #fecaca; background: #fff1f2; color: #991b1b; }
|
||||
.card { border: 1px solid #d8e3f0; border-radius: 12px; background: #fbfdff; padding: 12px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(2, minmax(240px, 1fr)); gap: 10px; }
|
||||
label { display: block; margin-bottom: 4px; font-size: 12px; color: #334155; font-weight: 700; }
|
||||
input { width: 100%; box-sizing: border-box; border: 1px solid #cbd5e1; border-radius: 8px; padding: 8px 9px; }
|
||||
select { width: 100%; box-sizing: border-box; border: 1px solid #cbd5e1; border-radius: 8px; padding: 8px 9px; background: #fff; }
|
||||
.check-row { margin-top: 8px; display: flex; gap: 12px; flex-wrap: wrap; }
|
||||
.check-row label { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 13px; }
|
||||
.check-row input[type="checkbox"] { width: auto; }
|
||||
.actions { margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
.hint { margin-top: 6px; color: #64748b; font-size: 12px; }
|
||||
.template-block {
|
||||
border: 1px solid #d8e3f0;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.template-title {
|
||||
margin: 0 0 8px;
|
||||
color: #24344e;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
.rule-card {
|
||||
margin-top: 12px;
|
||||
border: 1px solid #d8e3f0;
|
||||
border-radius: 12px;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
}
|
||||
.rule-title {
|
||||
margin: 0 0 8px;
|
||||
color: #23344f;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 8px;
|
||||
padding: 8px 9px;
|
||||
min-height: 120px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
@media (max-width: 760px) { .grid { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/admin_tools.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
|
||||
@@ -3,32 +3,10 @@
|
||||
|
||||
{% block title %}{% trans "Einweisungs-Builder" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 20px; }
|
||||
.shell { max-width: 1180px; margin: 0 auto; background: #fff; border: 1px solid #d7e0ea; border-radius: 14px; padding: 18px; }
|
||||
.topbar { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; display: block; }
|
||||
h1 { margin: 0; color: #000078; font-size: 28px; }
|
||||
.sub { margin: 8px 0 14px; color: #5f6f85; }
|
||||
.flash { margin: 0 0 12px; padding: 10px; border-radius: 8px; border: 1px solid #dbe5f2; background: #f8fbff; }
|
||||
.flash.error { border-color: #f4c7c7; background: #fff1f1; color: #8e1e1e; }
|
||||
.flash.success { border-color: #bfe6c9; background: #edf9f1; color: #116634; }
|
||||
.card { border: 1px solid #d7e0ea; border-radius: 12px; padding: 14px; background: #fcfdff; margin-bottom: 14px; }
|
||||
.grid { display: grid; grid-template-columns: 1.1fr 1.4fr 1fr 1fr 1fr auto; gap: 10px; align-items: end; }
|
||||
.field label { display: block; font-weight: 600; margin-bottom: 6px; }
|
||||
.field input, .field select { width: 100%; min-height: 40px; padding: 8px 10px; border: 1px solid #cfd9e8; border-radius: 8px; box-sizing: border-box; }
|
||||
.table-wrap { overflow-x: auto; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
th, td { border: 1px solid #e2e8f0; padding: 8px; text-align: left; vertical-align: top; }
|
||||
th { background: #f6f8fb; color: #334155; }
|
||||
.mini { color: #64748b; font-size: 12px; }
|
||||
.hint { margin-top: 6px; color: #5f6f85; font-size: 13px; }
|
||||
.table-controls input[type="text"], .table-controls select { width: 100%; min-height: 36px; padding: 7px 9px; border: 1px solid #cfd9e8; border-radius: 8px; box-sizing: border-box; }
|
||||
.table-controls input[type="checkbox"] { transform: scale(1.1); }
|
||||
.actions { white-space: nowrap; }
|
||||
.toolbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
|
||||
</style>
|
||||
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/admin_tools.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
|
||||
@@ -69,57 +69,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script>(function () {
|
||||
function byName(name) {
|
||||
return document.querySelector('[name="' + name + '"]');
|
||||
}
|
||||
|
||||
function slugifyForEmail(value) {
|
||||
const map = { 'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'ß': 'ss' };
|
||||
const lower = (value || '').toLowerCase();
|
||||
const mapped = lower.replace(/[äöüß]/g, function (m) { return map[m] || m; });
|
||||
return mapped
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/[^a-z0-9]+/g, '.')
|
||||
.replace(/^\.+|\.+$/g, '')
|
||||
.replace(/\.{2,}/g, '.');
|
||||
}
|
||||
|
||||
function extractLastName(fullName) {
|
||||
const parts = (fullName || '').trim().split(/\s+/).filter(Boolean);
|
||||
return parts.length ? parts[parts.length - 1] : '';
|
||||
}
|
||||
|
||||
const fullName = byName('full_name');
|
||||
const workEmail = byName('work_email');
|
||||
if (!fullName || !workEmail) return;
|
||||
|
||||
let lastSuggested = '';
|
||||
let userEditedEmail = false;
|
||||
|
||||
function suggestEmail() {
|
||||
const lastName = extractLastName(fullName.value);
|
||||
const slug = slugifyForEmail(lastName);
|
||||
if (!slug) return;
|
||||
const suggestion = slug + '@tub.co';
|
||||
const current = (workEmail.value || '').trim();
|
||||
if (!userEditedEmail || current === '' || current === lastSuggested) {
|
||||
workEmail.value = suggestion;
|
||||
lastSuggested = suggestion;
|
||||
}
|
||||
}
|
||||
|
||||
workEmail.addEventListener('input', function () {
|
||||
const current = (workEmail.value || '').trim();
|
||||
userEditedEmail = current !== '' && current !== lastSuggested;
|
||||
});
|
||||
|
||||
fullName.addEventListener('input', suggestEmail);
|
||||
fullName.addEventListener('change', suggestEmail);
|
||||
fullName.addEventListener('blur', suggestEmail);
|
||||
suggestEmail();
|
||||
}());
|
||||
</script>
|
||||
<script src="{% static 'workflows/js/offboarding_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -3,21 +3,16 @@
|
||||
|
||||
{% block title %}{% trans "Offboarding gespeichert" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 24px; }
|
||||
.shell { background: #fff; border: 1px solid #d7e0ea; border-radius: 16px; padding: 20px; box-shadow: 0 16px 36px rgba(18,34,56,0.10); }
|
||||
h1 { margin: 0 0 10px; color: #000078; }
|
||||
p { margin: 0 0 10px; }
|
||||
code { background: #f4f6fa; padding: 2px 6px; border-radius: 6px; }
|
||||
.actions { display:flex; gap:8px; flex-wrap:wrap; margin-top: 14px; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block shell_header %}
|
||||
{% include 'workflows/includes/app_header.html' with header_show_home=1 %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/success_pages.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
<h1>{% trans "Offboarding gespeichert" %}</h1>
|
||||
<p>{% trans "Vorgangs-ID:" %} <code>{{ obj.id }}</code></p>
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
<div class="actions">
|
||||
<button class="btn btn-secondary" type="button" id="btn-prev">{% trans "Zurück" %}</button>
|
||||
<button class="btn btn-primary" type="button" id="btn-next">{% trans "Weiter" %}</button>
|
||||
<button type="submit" id="btn-submit" class="btn btn-primary hidden">{% trans "Onboarding-Anfrage absenden" %}</button>
|
||||
<button type="submit" id="btn-submit" class="btn btn-primary hidden" data-loading-label="{% trans 'Wird gesendet...' %}">{% trans "Onboarding-Anfrage absenden" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
@@ -163,259 +163,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script>(function () {
|
||||
const pages = Array.from(document.querySelectorAll('.page'));
|
||||
const navItems = Array.from(document.querySelectorAll('.step-item'));
|
||||
const btnPrev = document.getElementById('btn-prev');
|
||||
const btnNext = document.getElementById('btn-next');
|
||||
const btnSubmit = document.getElementById('btn-submit');
|
||||
const form = document.getElementById('onboarding-form');
|
||||
let current = 0;
|
||||
form.setAttribute('novalidate', 'novalidate');
|
||||
|
||||
function byName(name) { return document.querySelector('[name="' + name + '"]'); }
|
||||
function toggle(id, state) {
|
||||
const el = document.getElementById(id);
|
||||
if (!el) return;
|
||||
el.classList.toggle('hidden', !state);
|
||||
}
|
||||
|
||||
function syncConditionals() {
|
||||
const orderCards = byName('order_business_cards');
|
||||
toggle('business-card-box', orderCards && orderCards.checked);
|
||||
|
||||
const employmentType = byName('employment_type');
|
||||
toggle('employment-end-box', employmentType && employmentType.value === 'befristet');
|
||||
|
||||
const groupMailbox = byName('group_mailboxes_required_choice');
|
||||
toggle('group-mailboxes-box', groupMailbox && groupMailbox.value === 'ja');
|
||||
|
||||
const extraHardware = byName('additional_hardware_needed_choice');
|
||||
toggle('extra-hardware-box', extraHardware && extraHardware.value === 'ja');
|
||||
|
||||
const extraSoftware = byName('additional_software_needed_choice');
|
||||
toggle('extra-software-box', extraSoftware && extraSoftware.value === 'ja');
|
||||
|
||||
const extraAccess = byName('additional_access_needed_choice');
|
||||
toggle('extra-access-box', extraAccess && extraAccess.value === 'ja');
|
||||
|
||||
const successor = byName('successor_required_choice');
|
||||
const showSuccessor = successor && successor.value === 'ja';
|
||||
toggle('successor-box', showSuccessor);
|
||||
|
||||
const inheritPhone = byName('inherit_phone_number_choice');
|
||||
const hidePhone = showSuccessor && inheritPhone && inheritPhone.value === 'ja';
|
||||
toggle('phone-box', !hidePhone);
|
||||
|
||||
// Hidden conditional groups must not block submit with invisible required fields.
|
||||
document.querySelectorAll('.field-group').forEach(function (group) {
|
||||
const hidden = group.classList.contains('hidden');
|
||||
group.querySelectorAll('input, select, textarea').forEach(function (el) {
|
||||
if (el.type === 'hidden' || el.disabled) return;
|
||||
if (hidden) {
|
||||
if (el.required) {
|
||||
el.dataset.requiredOriginal = '1';
|
||||
el.required = false;
|
||||
}
|
||||
} else if (el.dataset.requiredOriginal === '1') {
|
||||
el.required = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function slugifyForEmail(value) {
|
||||
const map = { 'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'ß': 'ss' };
|
||||
const lower = (value || '').toLowerCase();
|
||||
const mapped = lower.replace(/[äöüß]/g, function (m) { return map[m] || m; });
|
||||
return mapped
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/[^a-z0-9]+/g, '.')
|
||||
.replace(/^\.+|\.+$/g, '')
|
||||
.replace(/\.{2,}/g, '.');
|
||||
}
|
||||
|
||||
function setupWorkEmailAutofill() {
|
||||
const lastName = byName('last_name');
|
||||
const workEmail = byName('work_email');
|
||||
if (!lastName || !workEmail) return;
|
||||
|
||||
let lastSuggested = '';
|
||||
let userEditedEmail = !!(workEmail.value && workEmail.value.trim());
|
||||
|
||||
function suggestEmail() {
|
||||
const slug = slugifyForEmail(lastName.value);
|
||||
if (!slug) return;
|
||||
const suggestion = slug + '@tub.co';
|
||||
if (!userEditedEmail || workEmail.value === '' || workEmail.value === lastSuggested) {
|
||||
workEmail.value = suggestion;
|
||||
lastSuggested = suggestion;
|
||||
}
|
||||
}
|
||||
|
||||
workEmail.addEventListener('input', function () {
|
||||
const current = (workEmail.value || '').trim();
|
||||
userEditedEmail = current !== '' && current !== lastSuggested;
|
||||
});
|
||||
|
||||
lastName.addEventListener('input', suggestEmail);
|
||||
suggestEmail();
|
||||
}
|
||||
|
||||
function setupBusinessCardAutofill() {
|
||||
const checkbox = byName('order_business_cards');
|
||||
const firstName = byName('first_name');
|
||||
const lastName = byName('last_name');
|
||||
const jobTitle = byName('job_title');
|
||||
const workEmail = byName('work_email');
|
||||
const cardName = byName('business_card_name');
|
||||
const cardTitle = byName('business_card_title');
|
||||
const cardEmail = byName('business_card_email');
|
||||
if (!checkbox || !cardName || !cardTitle || !cardEmail) return;
|
||||
const cardBox = document.getElementById('business-card-box');
|
||||
|
||||
function suggestionName() {
|
||||
const first = (firstName && firstName.value || '').trim();
|
||||
const last = (lastName && lastName.value || '').trim();
|
||||
return [first, last].filter(Boolean).join(' ').trim();
|
||||
}
|
||||
|
||||
function setField(field, value, force) {
|
||||
if (!field || !value) return;
|
||||
const current = (field.value || '').trim();
|
||||
const autoMarked = field.dataset.autofilled === '1';
|
||||
if (force || !current || autoMarked) {
|
||||
field.value = value;
|
||||
field.dataset.autofilled = '1';
|
||||
}
|
||||
}
|
||||
|
||||
function applyDefaults(force) {
|
||||
if (!checkbox.checked) return;
|
||||
const name = suggestionName();
|
||||
const title = (jobTitle && jobTitle.value || '').trim();
|
||||
const email = (workEmail && workEmail.value || '').trim();
|
||||
setField(cardName, name, force);
|
||||
setField(cardTitle, title, force);
|
||||
setField(cardEmail, email, force);
|
||||
}
|
||||
|
||||
[cardName, cardTitle, cardEmail].forEach(function (field) {
|
||||
field.addEventListener('input', function () {
|
||||
field.dataset.autofilled = '0';
|
||||
});
|
||||
});
|
||||
|
||||
if (cardBox) {
|
||||
const grid = cardBox.querySelector('.grid-2');
|
||||
if (grid && !document.getElementById('business-card-autofill-btn')) {
|
||||
const actionWrap = document.createElement('div');
|
||||
actionWrap.className = 'field field-full';
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.id = 'business-card-autofill-btn';
|
||||
btn.className = 'btn btn-secondary';
|
||||
btn.textContent = 'Visitenkarten-Felder automatisch ausfüllen';
|
||||
btn.addEventListener('click', function () {
|
||||
applyDefaults(true);
|
||||
});
|
||||
actionWrap.appendChild(btn);
|
||||
grid.insertBefore(actionWrap, grid.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
// Manual-only behavior: fill only when button is clicked.
|
||||
}
|
||||
|
||||
function setupChecklistToggles() {
|
||||
document.querySelectorAll('[data-checklist-toggle]').forEach(function (button) {
|
||||
const panel = button.closest('.itsetup-checklist-panel');
|
||||
if (!panel) return;
|
||||
|
||||
const getCheckboxes = function () {
|
||||
return Array.from(panel.querySelectorAll('input[type="checkbox"]'));
|
||||
};
|
||||
|
||||
const refreshButtonLabel = function () {
|
||||
const checkboxes = getCheckboxes();
|
||||
if (!checkboxes.length) return;
|
||||
const allChecked = checkboxes.every(function (box) { return box.checked; });
|
||||
button.textContent = allChecked ? (button.dataset.labelClear || 'Auswahl aufheben') : (button.dataset.labelSelect || 'Alle auswählen');
|
||||
};
|
||||
|
||||
button.addEventListener('click', function () {
|
||||
const checkboxes = getCheckboxes();
|
||||
if (!checkboxes.length) return;
|
||||
const shouldCheck = checkboxes.some(function (box) { return !box.checked; });
|
||||
checkboxes.forEach(function (box) {
|
||||
box.checked = shouldCheck;
|
||||
box.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
});
|
||||
refreshButtonLabel();
|
||||
});
|
||||
|
||||
getCheckboxes().forEach(function (box) {
|
||||
box.addEventListener('change', refreshButtonLabel);
|
||||
});
|
||||
|
||||
refreshButtonLabel();
|
||||
});
|
||||
}
|
||||
|
||||
function setupChecklistColumns() {
|
||||
document.querySelectorAll('.itsetup-checklist-body > [id^="id_"]').forEach(function (container) {
|
||||
const itemCount = container.querySelectorAll(':scope > div').length;
|
||||
container.classList.toggle('cols-3', itemCount > 8);
|
||||
});
|
||||
}
|
||||
|
||||
function updateStep() {
|
||||
pages.forEach((p, i) => p.classList.toggle('active', i === current));
|
||||
navItems.forEach((n, i) => n.classList.toggle('active', i === current));
|
||||
btnPrev.disabled = current === 0;
|
||||
const last = current === pages.length - 1;
|
||||
btnNext.classList.toggle('hidden', last);
|
||||
btnSubmit.classList.toggle('hidden', !last);
|
||||
}
|
||||
|
||||
function jumpToFirstErrorPage() {
|
||||
const firstError = document.querySelector('.errorlist');
|
||||
if (!firstError) return;
|
||||
const page = firstError.closest('.page');
|
||||
if (!page) return;
|
||||
const step = Number(page.getAttribute('data-step') || '1') - 1;
|
||||
current = Math.max(0, step);
|
||||
}
|
||||
|
||||
document.addEventListener('change', syncConditionals);
|
||||
navItems.forEach((n, idx) => {
|
||||
n.addEventListener('click', function () { current = idx; updateStep(); });
|
||||
n.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
current = idx;
|
||||
updateStep();
|
||||
}
|
||||
});
|
||||
});
|
||||
btnPrev.addEventListener('click', function () { if (current > 0) { current -= 1; updateStep(); } });
|
||||
btnNext.addEventListener('click', function () { if (current < pages.length - 1) { current += 1; updateStep(); } });
|
||||
btnSubmit.addEventListener('click', function () {
|
||||
syncConditionals();
|
||||
btnSubmit.disabled = true;
|
||||
btnSubmit.textContent = 'Wird gesendet...';
|
||||
form.submit();
|
||||
});
|
||||
|
||||
syncConditionals();
|
||||
setupWorkEmailAutofill();
|
||||
setupBusinessCardAutofill();
|
||||
setupChecklistToggles();
|
||||
setupChecklistColumns();
|
||||
jumpToFirstErrorPage();
|
||||
updateStep();
|
||||
})();
|
||||
</script>
|
||||
<script src="{% static 'workflows/js/onboarding_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -3,55 +3,10 @@
|
||||
|
||||
{% block title %}{% trans "Einweisung durchführen" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
:root {
|
||||
--brand-blue: #000078;
|
||||
--ink: #17253b;
|
||||
--muted: #607087;
|
||||
--line: #d7e0ea;
|
||||
--panel: #ffffff;
|
||||
--soft: #f4f8ff;
|
||||
--soft-strong: #eef4ff;
|
||||
--ok-bg: #edf9f1;
|
||||
--ok-ink: #116634;
|
||||
--warn-bg: #fff8ea;
|
||||
--warn-ink: #8a5a00;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; font-family: "Segoe UI", Arial, sans-serif; background: linear-gradient(180deg, #eef4ff, #f8fbff); color: var(--ink); padding: 24px; }
|
||||
.shell { width: min(var(--app-shell-width), 100%); margin: 0 auto; background: var(--panel); border: 1px solid var(--line); border-radius: 28px; box-shadow: 0 22px 48px rgba(18,34,56,.14); overflow: hidden; }
|
||||
.hero { padding: 20px 22px 18px; border-bottom: 1px solid var(--line); background: linear-gradient(135deg, rgba(0,0,120,.06), rgba(0,0,120,0) 48%), linear-gradient(180deg, #ffffff, #f8fbff); }
|
||||
.hero h1 { margin: 0; font-size: 32px; line-height: 1.08; color: var(--brand-blue); }
|
||||
.sub { margin: 8px 0 0; color: var(--muted); max-width: 780px; }
|
||||
.content { padding: 20px 22px 24px; }
|
||||
.flash { margin: 0 0 12px; padding: 10px 12px; border-radius: 10px; border: 1px solid #bfe6c9; background: var(--ok-bg); color: var(--ok-ink); }
|
||||
.meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-bottom: 16px; }
|
||||
.card { border: 1px solid var(--line); border-radius: 14px; background: #fff; padding: 14px; }
|
||||
.card h2 { margin: 0 0 10px; font-size: 16px; color: #1b3764; }
|
||||
.progress-block { border: 1px solid var(--line); border-radius: 14px; background: linear-gradient(180deg, #ffffff, #f9fbff); padding: 14px; margin-bottom: 16px; }
|
||||
.progress-top { display: flex; justify-content: space-between; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
|
||||
.progress-label { font-size: 15px; font-weight: 700; color: #18345f; }
|
||||
.progress-meta { color: var(--muted); font-size: 13px; }
|
||||
.progress-bar { width: 100%; height: 12px; border-radius: 999px; overflow: hidden; background: #e7eefb; border: 1px solid #d6e1f5; }
|
||||
.progress-fill { height: 100%; background: linear-gradient(90deg, #3056a3, #0f5fcf); }
|
||||
.meta-grid { display: grid; grid-template-columns: 170px 1fr; gap: 8px 10px; font-size: 14px; }
|
||||
.meta-grid strong { color: #334155; }
|
||||
.status-pill { display: inline-block; padding: 4px 10px; border-radius: 999px; border: 1px solid #d7e0ea; background: #f8fbff; color: #486183; font-size: 12px; font-weight: 700; }
|
||||
.status-pill.done { background: var(--ok-bg); color: var(--ok-ink); border-color: #bfe6c9; }
|
||||
.status-pill.draft { background: var(--warn-bg); color: var(--warn-ink); border-color: #f5d8a8; }
|
||||
.section { border: 1px solid var(--line); border-radius: 14px; overflow: hidden; margin-bottom: 14px; background: #fff; }
|
||||
.section-head { padding: 11px 14px; font-weight: 700; color: #1f376b; background: var(--soft-strong); border-bottom: 1px solid #d5e2f9; }
|
||||
.items { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; padding: 6px 14px 10px; }
|
||||
.item { display: flex; align-items: flex-start; gap: 12px; padding: 10px 0; border-bottom: 1px solid #eef3f8; }
|
||||
.item:nth-last-child(-n+2) { border-bottom: 0; }
|
||||
.item input { margin-top: 2px; width: 18px; height: 18px; accent-color: var(--brand-blue); }
|
||||
.item span { line-height: 1.45; }
|
||||
textarea { width: 100%; min-height: 150px; border: 1px solid #cfd9e8; border-radius: 10px; padding: 11px 12px; font: inherit; resize: vertical; }
|
||||
.help { color: var(--muted); font-size: 13px; margin-top: 8px; }
|
||||
.actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
|
||||
@media (max-width: 900px) { .meta, .items { grid-template-columns: 1fr; } .meta-grid { grid-template-columns: 1fr; } .item:nth-last-child(-n+2) { border-bottom: 1px solid #eef3f8; } .item:last-child { border-bottom: 0; } }
|
||||
</style>
|
||||
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/onboarding_intro_session.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
|
||||
@@ -3,21 +3,16 @@
|
||||
|
||||
{% block title %}{% trans "Onboarding gespeichert" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 24px; }
|
||||
.shell { background: #fff; border: 1px solid #d7e0ea; border-radius: 16px; padding: 20px; box-shadow: 0 16px 36px rgba(18,34,56,0.10); }
|
||||
h1 { margin: 0 0 10px; color: #000078; }
|
||||
p { margin: 0 0 10px; }
|
||||
code { background: #f4f6fa; padding: 2px 6px; border-radius: 6px; }
|
||||
.actions { display:flex; gap:8px; flex-wrap:wrap; margin-top: 14px; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block shell_header %}
|
||||
{% include 'workflows/includes/app_header.html' with header_show_home=1 %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/success_pages.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
<h1>{% trans "Anfrage erfolgreich gespeichert" %}</h1>
|
||||
<p>{% trans "Vorgangs-ID:" %} <code>{{ obj.id }}</code></p>
|
||||
|
||||
@@ -3,24 +3,10 @@
|
||||
|
||||
{% block title %}Project Wiki{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 20px; }
|
||||
.shell { max-width: 1120px; margin: 0 auto; background: #fff; border: 1px solid #d7e0ea; border-radius: 14px; padding: 18px; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; margin: 0 0 10px; display: block; }
|
||||
.top { display: flex; justify-content: space-between; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
|
||||
h1 { margin: 0; color: #000078; font-size: 30px; }
|
||||
.sub { margin: 8px 0 16px; color: #5f6f85; }
|
||||
.toc { border: 1px solid #d7e0ea; border-radius: 10px; padding: 10px; background: #f7fbff; margin-bottom: 16px; }
|
||||
.toc a { color: #0b4da2; text-decoration: none; margin-right: 10px; white-space: nowrap; }
|
||||
h2 { margin: 20px 0 8px; color: #113a74; border-bottom: 1px solid #e1e8f2; padding-bottom: 4px; }
|
||||
h3 { margin: 14px 0 6px; color: #183f77; }
|
||||
ul { margin: 8px 0 12px 20px; }
|
||||
li { margin: 4px 0; }
|
||||
code { background: #f1f5fb; border: 1px solid #dce6f3; border-radius: 6px; padding: 2px 6px; }
|
||||
.box { border: 1px solid #d7e0ea; border-radius: 10px; padding: 10px; background: #fcfdff; margin: 8px 0 12px; }
|
||||
.note { border-left: 4px solid #000078; padding: 8px 10px; background: #f4f8ff; margin: 10px 0; }
|
||||
</style>
|
||||
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/docs_pages.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
|
||||
@@ -3,29 +3,10 @@
|
||||
|
||||
{% block title %}{% trans "Release Checklist" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 20px; }
|
||||
.shell { max-width: 1120px; margin: 0 auto; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; margin: 0 0 10px; display: block; }
|
||||
.hero, .panel { background: #fff; border: 1px solid #d7e0ea; border-radius: 16px; box-shadow: 0 20px 40px rgba(17, 58, 116, 0.08); }
|
||||
.hero { padding: 20px; margin-bottom: 18px; }
|
||||
.top { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
|
||||
.eyebrow { display: inline-block; padding: 5px 10px; border-radius: 999px; background: #eef4ff; color: #244a8f; border: 1px solid #d5e2f9; font-size: 12px; font-weight: 700; margin-bottom: 10px; }
|
||||
h1 { margin: 0; color: #000078; font-size: 30px; }
|
||||
.sub { margin: 8px 0 0; color: #5f6f85; max-width: 820px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(2, minmax(320px, 1fr)); gap: 16px; }
|
||||
.panel { padding: 18px; }
|
||||
h2 { margin: 0 0 12px; color: #113a74; font-size: 20px; }
|
||||
ol, ul { margin: 0; padding-left: 20px; }
|
||||
li { margin: 8px 0; color: #334155; }
|
||||
.checklist li { list-style: none; position: relative; padding-left: 28px; }
|
||||
.checklist li::before { content: '\25A1'; position: absolute; left: 0; top: 0; color: #66758c; font-size: 16px; }
|
||||
pre { margin: 12px 0 0; padding: 14px; border-radius: 12px; background: #f7faff; border: 1px solid #dfe8f4; overflow-x: auto; color: #16345f; }
|
||||
code { font-family: Menlo, Monaco, Consolas, monospace; font-size: 13px; }
|
||||
.note { margin-top: 16px; padding: 14px 16px; border-radius: 12px; background: #f7faff; border: 1px solid #dfe8f4; color: #355175; }
|
||||
@media (max-width: 820px) { .grid { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/release_checklist.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
|
||||
@@ -3,872 +3,10 @@
|
||||
|
||||
{% block title %}{% trans "Anfragen Dashboard" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
:root {
|
||||
--brand-blue: #000078;
|
||||
--brand-blue-soft: #1f4fd6;
|
||||
--brand-red: #a32020;
|
||||
--ink: #132238;
|
||||
--muted: #607086;
|
||||
--line: #d9e3ee;
|
||||
--line-strong: #c8d5e5;
|
||||
--panel: rgba(255, 255, 255, 0.9);
|
||||
--panel-strong: #ffffff;
|
||||
--bg-soft: #eef3ff;
|
||||
--ok-bg: #ecf9f0;
|
||||
--ok-ink: #1f7a3f;
|
||||
--warn-bg: #fff6e5;
|
||||
--warn-ink: #9a6400;
|
||||
--danger-bg: #fff1f1;
|
||||
--danger-ink: #982222;
|
||||
--shadow: 0 22px 48px rgba(18, 34, 56, 0.14);
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
||||
color: var(--ink);
|
||||
min-height: 100vh;
|
||||
background:
|
||||
radial-gradient(70% 90% at 8% 8%, rgba(0, 0, 120, 0.14), rgba(0, 0, 120, 0)),
|
||||
radial-gradient(60% 85% at 92% 88%, rgba(163, 32, 32, 0.12), rgba(163, 32, 32, 0)),
|
||||
linear-gradient(160deg, #eef3ff 0%, #f9fbff 48%, #edf4ff 100%);
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.shell {
|
||||
width: min(1380px, 100%);
|
||||
margin: 0 auto;
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(217, 227, 238, 0.9);
|
||||
border-radius: 28px;
|
||||
box-shadow: var(--shadow);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 18px;
|
||||
padding: 22px 24px 18px;
|
||||
border-bottom: 1px solid rgba(217, 227, 238, 0.9);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.95), rgba(248,251,255,0.84));
|
||||
}
|
||||
|
||||
.brand-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
width: 212px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.lang-switch { display:flex; gap:6px; }
|
||||
.lang-btn { border:1px solid var(--line); background:#f8fbff; color:#1f3a5f; border-radius:999px; padding:6px 10px; font-size:12px; font-weight:700; cursor:pointer; }
|
||||
.lang-btn.active { background:var(--brand-blue); border-color:var(--brand-blue); color:#fff; }
|
||||
|
||||
.hero {
|
||||
padding: 0;
|
||||
border-bottom: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hero-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.4fr) minmax(320px, 0.8fr);
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.hero-card,
|
||||
.pulse-card,
|
||||
.controls-card,
|
||||
.table-card,
|
||||
.chart-card,
|
||||
.stat-card {
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
background: var(--panel);
|
||||
border-radius: 22px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.hero-card {
|
||||
padding: 14px;
|
||||
background:
|
||||
radial-gradient(100% 140% at 10% 10%, rgba(31,79,214,0.10), rgba(31,79,214,0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.99), rgba(248,251,255,0.97));
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(0,0,120,0.12);
|
||||
background: rgba(0,0,120,0.05);
|
||||
color: var(--brand-blue);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
margin: 8px 0 4px;
|
||||
font-size: clamp(24px, 3.6vw, 34px);
|
||||
line-height: 1;
|
||||
letter-spacing: -0.04em;
|
||||
color: var(--brand-blue);
|
||||
}
|
||||
|
||||
.hero p {
|
||||
margin: 0;
|
||||
max-width: 760px;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.hero-pills {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.hero-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-height: 34px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid rgba(217, 227, 238, 0.96);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(248,251,255,0.96));
|
||||
color: #294465;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.94);
|
||||
}
|
||||
|
||||
.pulse-card {
|
||||
padding: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
min-height: 100%;
|
||||
background:
|
||||
radial-gradient(120% 120% at 100% 0%, rgba(163,32,32,0.10), rgba(163,32,32,0)),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.98), rgba(253,247,247,0.96));
|
||||
}
|
||||
|
||||
.activity-card {
|
||||
padding: 18px;
|
||||
background: rgba(255,255,255,0.95);
|
||||
}
|
||||
|
||||
.activity-card .chart {
|
||||
min-height: 150px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.activity-card .bar-wrap {
|
||||
min-height: 104px;
|
||||
}
|
||||
|
||||
.pulse-card h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #1a3359;
|
||||
}
|
||||
|
||||
.pulse-card p {
|
||||
margin: 8px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.pulse-metrics {
|
||||
margin-top: 18px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.pulse-metric {
|
||||
padding: 12px 14px;
|
||||
border-radius: 16px;
|
||||
background: rgba(255,255,255,0.86);
|
||||
border: 1px solid rgba(217, 227, 238, 0.95);
|
||||
}
|
||||
|
||||
.pulse-label {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.pulse-value {
|
||||
margin-top: 5px;
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
color: var(--brand-blue);
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.metrics-grid {
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
padding: 14px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 110px;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 10px 24px rgba(18, 33, 56, 0.04), inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.stat-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: auto -24px -36px auto;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
border-radius: 50%;
|
||||
background: rgba(31, 79, 214, 0.08);
|
||||
}
|
||||
|
||||
.stat-card.red::before { background: rgba(163, 32, 32, 0.08); }
|
||||
.stat-card.gold::before { background: rgba(194, 137, 26, 0.10); }
|
||||
.stat-card.ink::before { background: rgba(19, 34, 56, 0.08); }
|
||||
|
||||
.stat-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.stat-title {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.stat-kicker {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 12px;
|
||||
background: rgba(0, 0, 120, 0.06);
|
||||
color: var(--brand-blue);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.stat-card.red .stat-kicker {
|
||||
background: rgba(163, 32, 32, 0.08);
|
||||
color: var(--brand-red);
|
||||
}
|
||||
|
||||
.stat-card.gold .stat-kicker {
|
||||
background: rgba(194, 137, 26, 0.10);
|
||||
color: #9a6400;
|
||||
}
|
||||
|
||||
.stat-card.ink .stat-kicker {
|
||||
background: rgba(19, 34, 56, 0.08);
|
||||
color: #132238;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
margin-top: 12px;
|
||||
font-size: clamp(24px, 2.6vw, 30px);
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.05em;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.stat-foot {
|
||||
margin-top: 5px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
max-width: 220px;
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
padding: 18px 24px 24px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.top-stack {
|
||||
padding: 12px 24px 0;
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
|
||||
.top-content-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.5fr) minmax(320px, 1fr);
|
||||
gap: 16px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.chart-card,
|
||||
.controls-card,
|
||||
.table-card {
|
||||
padding: 14px;
|
||||
background: rgba(255,255,255,0.94);
|
||||
border-radius: 22px;
|
||||
box-shadow: 0 12px 28px rgba(18, 33, 56, 0.045), inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.section-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.section-head h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #18345f;
|
||||
}
|
||||
|
||||
.section-head p {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.chart {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(14, minmax(0, 1fr));
|
||||
gap: 6px;
|
||||
align-items: end;
|
||||
min-height: 180px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.chart-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bar-wrap {
|
||||
width: 100%;
|
||||
min-height: 124px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.bar {
|
||||
width: 100%;
|
||||
max-width: 34px;
|
||||
background: linear-gradient(180deg, #2b5bda, #071f7d);
|
||||
border-radius: 14px 14px 6px 6px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.28);
|
||||
}
|
||||
|
||||
.bar-value {
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
color: #294465;
|
||||
}
|
||||
|
||||
.bar-label {
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.controls-card {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
width: 100%;
|
||||
border: 1px solid var(--line-strong);
|
||||
border-radius: 16px;
|
||||
padding: 14px 16px;
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
background: rgba(255,255,255,0.98);
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.98);
|
||||
}
|
||||
|
||||
.search-box input:focus {
|
||||
outline: none;
|
||||
border-color: rgba(0, 0, 120, 0.3);
|
||||
box-shadow: 0 0 0 4px rgba(0, 0, 120, 0.08);
|
||||
}
|
||||
|
||||
.search-help {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.55;
|
||||
max-width: 70ch;
|
||||
}
|
||||
|
||||
.control-panel {
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--line);
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.bulk-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin: 0;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.bulk-info {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.table-card {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 26px;
|
||||
box-shadow: 0 16px 48px rgba(18, 33, 56, 0.06), inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
}
|
||||
|
||||
.table-controls {
|
||||
padding: 14px 18px 14px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(244,248,255,0.96));
|
||||
}
|
||||
|
||||
.table-controls-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 14px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.control-stack {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
padding: 14px;
|
||||
border: 1px solid rgba(217, 227, 238, 0.95);
|
||||
border-radius: 18px;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(249,251,255,0.95));
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.9);
|
||||
}
|
||||
|
||||
.search-card {
|
||||
padding: 18px;
|
||||
background: rgba(255,255,255,0.92);
|
||||
border: 1px solid rgba(217, 227, 238, 0.94);
|
||||
border-radius: 22px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.table-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 16px 18px 14px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(245,249,255,0.96));
|
||||
}
|
||||
|
||||
.table-head h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
color: #18345f;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.table-head p {
|
||||
margin: 5px 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.table-head-meta {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(0, 0, 120, 0.10);
|
||||
background: rgba(0, 0, 120, 0.05);
|
||||
color: var(--brand-blue);
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.table-wrap {
|
||||
overflow-x: auto;
|
||||
padding: 0 18px 18px;
|
||||
background: linear-gradient(180deg, rgba(249,251,255,0.72), rgba(255,255,255,0));
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 12px;
|
||||
font-size: 14px;
|
||||
min-width: 980px;
|
||||
}
|
||||
|
||||
thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
background: rgba(245,248,252,0.94);
|
||||
color: #5b6b7f;
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 800;
|
||||
padding: 12px 14px;
|
||||
border-top: 1px solid var(--line);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
thead th:first-child {
|
||||
border-left: 1px solid var(--line);
|
||||
border-radius: 14px 0 0 14px;
|
||||
}
|
||||
|
||||
thead th:last-child {
|
||||
border-right: 1px solid var(--line);
|
||||
border-radius: 0 14px 14px 0;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
background: rgba(255,255,255,0.98);
|
||||
border-top: 1px solid var(--line);
|
||||
border-bottom: 1px solid var(--line);
|
||||
padding: 15px 14px;
|
||||
vertical-align: middle;
|
||||
box-shadow: 0 8px 22px rgba(26, 51, 89, 0.035);
|
||||
}
|
||||
|
||||
tbody td:first-child {
|
||||
border-left: 1px solid var(--line);
|
||||
border-radius: 18px 0 0 18px;
|
||||
}
|
||||
|
||||
tbody td:last-child {
|
||||
border-right: 1px solid var(--line);
|
||||
border-radius: 0 18px 18px 0;
|
||||
}
|
||||
|
||||
tbody tr:hover td {
|
||||
background: #fbfdff;
|
||||
border-color: #cad7e8;
|
||||
box-shadow: 0 12px 26px rgba(26, 51, 89, 0.06);
|
||||
}
|
||||
|
||||
.select-col {
|
||||
width: 42px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
th.select-col,
|
||||
td.select-col {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
td.actions-cell {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
td.intro-panel {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.select-col input[type="checkbox"] {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.kind-pill,
|
||||
.status-badge,
|
||||
.doc-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
min-height: 38px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 14px;
|
||||
font-weight: 800;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.01em;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
border: 1px solid rgba(217, 227, 238, 0.96);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(248,251,255,0.96));
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.94);
|
||||
}
|
||||
|
||||
.kind-pill {
|
||||
color: #294465;
|
||||
}
|
||||
|
||||
.kind-pill.onboarding {
|
||||
background: linear-gradient(180deg, rgba(245,247,255,0.98), rgba(236,241,255,0.98));
|
||||
border-color: rgba(0, 0, 120, 0.12);
|
||||
color: var(--brand-blue);
|
||||
}
|
||||
|
||||
.kind-pill.offboarding {
|
||||
background: linear-gradient(180deg, rgba(255,247,247,0.98), rgba(255,240,240,0.98));
|
||||
border-color: rgba(163, 32, 32, 0.14);
|
||||
color: var(--brand-red);
|
||||
}
|
||||
|
||||
.name-cell {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.person-name {
|
||||
font-weight: 800;
|
||||
color: var(--ink);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.person-meta {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.mail-link {
|
||||
color: #294465;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.mail-link:hover { text-decoration: underline; }
|
||||
|
||||
.status-badge.ok {
|
||||
background: linear-gradient(180deg, #f3fcf6, #e8f8ee);
|
||||
color: var(--ok-ink);
|
||||
border-color: #cdeed8;
|
||||
}
|
||||
|
||||
.status-badge.pending {
|
||||
background: linear-gradient(180deg, #fffaf0, #fff3dc);
|
||||
color: var(--warn-ink);
|
||||
border-color: #f3dfb5;
|
||||
}
|
||||
|
||||
.doc-link {
|
||||
color: var(--brand-blue);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.99), rgba(244,248,255,0.98));
|
||||
border-color: rgba(0, 0, 120, 0.12);
|
||||
}
|
||||
|
||||
.doc-link:hover {
|
||||
background: linear-gradient(180deg, rgba(248,251,255,0.99), rgba(238,244,255,0.98));
|
||||
border-color: rgba(0, 0, 120, 0.18);
|
||||
}
|
||||
|
||||
.actions-cell { white-space: normal; }
|
||||
.inline-form { display: inline; margin: 0; }
|
||||
.inline-delete { display: inline-flex; align-items: center; }
|
||||
.inline-delete .btn { min-height: 38px; display: inline-flex; align-items: center; justify-content: center; }
|
||||
.intro-panel { min-width: 260px; }
|
||||
|
||||
details {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(180deg, #ffffff, #f8fbff);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
details[open] {
|
||||
border-color: #cad7e8;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.95);
|
||||
}
|
||||
|
||||
.intro-toggle {
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
padding: 12px 14px;
|
||||
font-weight: 800;
|
||||
color: #18345f;
|
||||
background: rgba(255,255,255,0.65);
|
||||
}
|
||||
|
||||
.intro-toggle::after {
|
||||
content: "+";
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
color: var(--brand-blue);
|
||||
}
|
||||
|
||||
details[open] .intro-toggle::after { content: "−"; }
|
||||
.intro-toggle::-webkit-details-marker { display: none; }
|
||||
|
||||
.intro-menu {
|
||||
padding: 0 14px 14px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.intro-group {
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.intro-group:first-child {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.intro-group-title {
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.intro-actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.intro-meta {
|
||||
padding: 0 14px 14px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.flash {
|
||||
margin: 0 24px 14px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(217, 227, 238, 0.9);
|
||||
background: rgba(248, 251, 255, 0.95);
|
||||
}
|
||||
|
||||
.flash.success { border-color: #bfe6c9; background: #edf9f1; color: #116634; }
|
||||
.flash.warning { border-color: #f5d8a8; background: #fff8ea; color: #8a5a00; }
|
||||
.flash.error { border-color: #f4c7c7; background: #fff1f1; color: #8e1e1e; }
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
padding: 26px 14px;
|
||||
}
|
||||
|
||||
.footer-bar {
|
||||
padding: 0 24px 24px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.footer-note {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
.hero-grid,
|
||||
.metrics-grid,
|
||||
.top-content-grid,
|
||||
.table-controls-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
body { padding: 14px; }
|
||||
.topbar,
|
||||
.hero,
|
||||
.metrics-grid,
|
||||
.content-grid,
|
||||
.footer-bar { padding-left: 16px; padding-right: 16px; }
|
||||
.topbar { flex-direction: column; }
|
||||
.quick-actions { justify-content: flex-start; }
|
||||
.table-wrap { padding-left: 12px; padding-right: 12px; }
|
||||
}
|
||||
</style>
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/requests_dashboard.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
@@ -997,10 +135,9 @@
|
||||
</div>
|
||||
</form>
|
||||
<div class="search-help">{% trans "Datensätze können direkt in der Tabelle gefiltert, geöffnet, geprüft oder gelöscht werden." %}</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
{% if request.user.is_staff %}<div class="control-stack">
|
||||
</div>
|
||||
{% if request.user.is_staff %}
|
||||
<div class="control-stack">
|
||||
<form method="post" action="/requests/" id="bulk-delete-form" onsubmit="return confirm('Ausgewählte Einträge wirklich löschen?');">
|
||||
{% csrf_token %}
|
||||
<div class="bulk-toolbar">
|
||||
@@ -1116,30 +253,8 @@
|
||||
<div class="footer-note">{% trans "TUBCO Onboarding & Offboarding Portal" %}</div>
|
||||
<a class="btn btn-secondary" href="/">{% trans "Zur Startseite" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% if request.user.is_staff %}
|
||||
<script>
|
||||
(function () {
|
||||
const selectAll = document.getElementById('select-all');
|
||||
const rowChecks = Array.from(document.querySelectorAll('.row-select'));
|
||||
const selectedCount = document.getElementById('selected-count');
|
||||
if (!selectAll || !selectedCount || !rowChecks.length) return;
|
||||
|
||||
function updateCount() {
|
||||
const checked = rowChecks.filter((c) => c.checked).length;
|
||||
selectedCount.textContent = String(checked);
|
||||
selectAll.checked = checked > 0 && checked === rowChecks.length;
|
||||
selectAll.indeterminate = checked > 0 && checked < rowChecks.length;
|
||||
}
|
||||
|
||||
selectAll.addEventListener('change', function () {
|
||||
rowChecks.forEach((c) => { c.checked = selectAll.checked; });
|
||||
updateCount();
|
||||
});
|
||||
rowChecks.forEach((c) => c.addEventListener('change', updateCount));
|
||||
updateCount();
|
||||
})();
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script src="{% static 'workflows/js/requests_dashboard.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,41 +3,10 @@
|
||||
|
||||
{% block title %}{% trans "Welcome E-Mails" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<style>
|
||||
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #0f172a; padding: 20px; }
|
||||
.shell { max-width: 1100px; margin: 0 auto; background: #fff; border: 1px solid #d8e3f0; border-radius: 14px; padding: 16px; }
|
||||
.topbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }
|
||||
.brand-logo { width: 190px; max-width: 100%; height: auto; display: block; }
|
||||
h1 { margin: 12px 0 6px; color: #000078; }
|
||||
.sub { margin: 0 0 12px; color: #54657c; }
|
||||
.msg { border-radius: 10px; padding: 10px 12px; margin: 0 0 12px; border: 1px solid #d6e1ef; background: #f8fbff; color: #1f3a5f; }
|
||||
.msg.error { border-color: #fecaca; background: #fff1f2; color: #991b1b; }
|
||||
.card { border: 1px solid #d8e3f0; border-radius: 12px; background: #fbfdff; padding: 12px; margin-bottom: 14px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(2, minmax(260px, 1fr)); gap: 10px; }
|
||||
label { display: block; margin-bottom: 4px; font-size: 12px; color: #334155; font-weight: 700; }
|
||||
input, textarea { width: 100%; box-sizing: border-box; border: 1px solid #cbd5e1; border-radius: 8px; padding: 8px 9px; }
|
||||
textarea { min-height: 120px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
|
||||
.check-row { margin-top: 8px; display: flex; gap: 12px; flex-wrap: wrap; }
|
||||
.check-row label { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 13px; }
|
||||
.check-row input[type="checkbox"] { width: auto; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
||||
th, td { border: 1px solid #dce5f1; padding: 8px; text-align: left; vertical-align: top; }
|
||||
th { background: #f6f9ff; }
|
||||
.badge { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 700; }
|
||||
.scheduled { background: #eff6ff; color: #1d4ed8; }
|
||||
.paused { background: #fef9c3; color: #854d0e; }
|
||||
.cancelled { background: #f1f5f9; color: #334155; }
|
||||
.sent { background: #ecfdf3; color: #166534; }
|
||||
.failed { background: #fff1f2; color: #991b1b; }
|
||||
.actions { margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
.table-actions { display: flex; gap: 6px; flex-wrap: wrap; }
|
||||
.hint { margin-top: 6px; color: #64748b; font-size: 12px; }
|
||||
.bulk-bar { margin: 0 0 10px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
||||
.bulk-bar select { width: auto; min-width: 180px; }
|
||||
.select-col { width: 42px; text-align: center; }
|
||||
.bulk-note { color: #64748b; font-size: 12px; }
|
||||
</style>
|
||||
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'workflows/css/admin_tools.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block shell_body %}
|
||||
@@ -93,7 +62,7 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="bulk-bar" id="welcome-bulk-form" method="post" action="/admin-tools/welcome-emails/bulk-action/" onsubmit="return confirmBulkAction();">
|
||||
<form class="bulk-bar" id="welcome-bulk-form" method="post" action="/admin-tools/welcome-emails/bulk-action/" onsubmit="return confirmBulkAction();" data-alert-empty="{% trans 'Bitte mindestens einen Welcome-Eintrag auswählen.' %}" data-confirm-delete="{% trans 'Ausgewählte Welcome-Einträge wirklich löschen?' %}" data-confirm-pause="{% trans 'Ausgewählte Welcome-Einträge pausieren?' %}" data-confirm-send="{% trans 'Ausgewählte Welcome-Einträge sofort senden?' %}">
|
||||
{% csrf_token %}
|
||||
<label style="display:inline-flex; align-items:center; gap:6px; margin:0;">
|
||||
<input type="checkbox" id="select-all-welcome" />
|
||||
@@ -180,58 +149,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
<script>(function () {
|
||||
const selectAll = document.getElementById('select-all-welcome');
|
||||
const rowChecks = Array.from(document.querySelectorAll('.welcome-select'));
|
||||
const selectedCount = document.getElementById('selected-count');
|
||||
const selectedIds = document.getElementById('selected_ids');
|
||||
const bulkForm = document.getElementById('welcome-bulk-form');
|
||||
const bulkAction = document.getElementById('bulk_action');
|
||||
|
||||
function currentSelected() {
|
||||
return rowChecks.filter((c) => c.checked).map((c) => c.value);
|
||||
}
|
||||
|
||||
function syncState() {
|
||||
const ids = currentSelected();
|
||||
selectedCount.textContent = String(ids.length);
|
||||
selectedIds.value = ids.join(',');
|
||||
if (!rowChecks.length) {
|
||||
selectAll.checked = false;
|
||||
selectAll.indeterminate = false;
|
||||
return;
|
||||
}
|
||||
selectAll.checked = ids.length > 0 && ids.length === rowChecks.length;
|
||||
selectAll.indeterminate = ids.length > 0 && ids.length < rowChecks.length;
|
||||
}
|
||||
|
||||
selectAll.addEventListener('change', function () {
|
||||
rowChecks.forEach((c) => { c.checked = selectAll.checked; });
|
||||
syncState();
|
||||
});
|
||||
|
||||
rowChecks.forEach((c) => c.addEventListener('change', syncState));
|
||||
bulkForm.addEventListener('submit', syncState);
|
||||
|
||||
window.confirmBulkAction = function () {
|
||||
syncState();
|
||||
const count = currentSelected().length;
|
||||
if (!count) {
|
||||
alert('{% trans "Bitte mindestens einen Welcome-Eintrag auswählen." %}');
|
||||
return false;
|
||||
}
|
||||
const action = bulkAction.value;
|
||||
if (action === 'delete') {
|
||||
return confirm('{% trans "Ausgewählte Welcome-Einträge wirklich löschen?" %}');
|
||||
}
|
||||
if (action === 'pause') {
|
||||
return confirm('{% trans "Ausgewählte Welcome-Einträge pausieren?" %}');
|
||||
}
|
||||
return confirm('{% trans "Ausgewählte Welcome-Einträge sofort senden?" %}');
|
||||
};
|
||||
|
||||
syncState();
|
||||
})();
|
||||
</script>
|
||||
<script src="{% static 'workflows/js/welcome_emails.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user