Test custom.css
This commit is contained in:
+325
-293
@@ -1,42 +1,83 @@
|
|||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
HOMEPAGE CUSTOM CSS - OPTIMIZED
|
KalliLab — FINAL CUSTOM CSS
|
||||||
|
Header CSS removed completely / everything else kept
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* Theme colors */
|
--kl-bg: #071015;
|
||||||
--dominant-color: #1a3a3a;
|
--kl-panel: rgba(8, 14, 19, 0.78);
|
||||||
--accent-color: #00c8a0;
|
--kl-panel-2: rgba(11, 19, 24, 0.86);
|
||||||
--accent-color-dim: #00c8a050;
|
|
||||||
--bg-color: #18191a;
|
|
||||||
--bg-color-light: #1e2021;
|
|
||||||
--text-color: #ffffff;
|
|
||||||
|
|
||||||
/* Derived properties using dynamic colors */
|
--kl-card: rgba(11, 19, 25, 0.72);
|
||||||
--card-border: 3.5px solid var(--dominant-color);
|
--kl-card-hover: rgba(14, 24, 31, 0.78);
|
||||||
--card-border-hover: var(--accent-color);
|
--kl-tab: rgba(9, 16, 22, 0.78);
|
||||||
--card-border-focus: var(--accent-color);
|
--kl-tab-hover: rgba(12, 22, 28, 0.82);
|
||||||
--card-bg: var(--bg-color);
|
--kl-tab-active: rgba(10, 22, 26, 0.84);
|
||||||
--card-bg-hover: var(--accent-color-dim);
|
|
||||||
--text-shadow: 0 0 10px var(--bg-color);
|
--kl-border: rgba(118, 181, 187, 0.12);
|
||||||
--transition: background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
|
--kl-border-strong: rgba(0, 200, 160, 0.34);
|
||||||
--focus-ring: 0 0 8px var(--accent-color-dim);
|
--kl-border-active: rgba(74, 219, 196, 0.62);
|
||||||
--font-family-base: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
|
|
||||||
--base-font-size: 14px;
|
--kl-text: #e8fbfb;
|
||||||
--card-padding: 0;
|
--kl-text-soft: rgba(220, 243, 243, 0.74);
|
||||||
--card-margin: 0;
|
--kl-text-dim: rgba(182, 215, 215, 0.54);
|
||||||
--border-radius: 1.5rem;
|
|
||||||
|
--kl-shadow: 0 12px 30px rgba(0, 0, 0, 0.22);
|
||||||
|
--kl-glow: 0 0 18px rgba(0, 200, 160, 0.14);
|
||||||
|
--kl-glow-strong: 0 0 24px rgba(0, 200, 160, 0.22);
|
||||||
|
|
||||||
|
--kl-radius: 18px;
|
||||||
|
--kl-radius-sm: 14px;
|
||||||
|
|
||||||
|
--kl-font-ui: "Inter", "Segoe UI", system-ui, sans-serif;
|
||||||
|
--kl-font-tech: "JetBrains Mono", "Consolas", monospace;
|
||||||
|
|
||||||
|
--kl-transition: 180ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
NAVIGATION TABS
|
BASE
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
background: #050c10;
|
||||||
|
color: var(--kl-text);
|
||||||
|
font-family: var(--kl-font-ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
body::before {
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at top center, rgba(0, 200, 160, 0.06), transparent 32%),
|
||||||
|
linear-gradient(180deg, rgba(4, 10, 14, 0.18), rgba(4, 10, 14, 0.48));
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container,
|
||||||
|
main,
|
||||||
|
#page_container {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 94%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
TABS
|
||||||
|
============================================================================ */
|
||||||
|
|
||||||
#myTab {
|
#myTab {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 60px;
|
gap: 18px;
|
||||||
margin: 0 150px 30px;
|
margin: 0 24px 22px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font: 18px/2 var(--font-family-base);
|
background: transparent;
|
||||||
background: none;
|
|
||||||
backdrop-filter: none;
|
backdrop-filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,231 +89,183 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[id$="-tab"] {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 50px;
|
||||||
|
min-width: 180px;
|
||||||
|
padding: 0 22px;
|
||||||
|
border: 1px solid var(--kl-border);
|
||||||
|
border-radius: 16px;
|
||||||
|
background: linear-gradient(180deg, rgba(10, 18, 24, 0.72), rgba(7, 13, 18, 0.82));
|
||||||
|
color: var(--kl-text-soft);
|
||||||
|
font-family: var(--kl-font-ui);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
transition:
|
||||||
|
border-color var(--kl-transition),
|
||||||
|
background var(--kl-transition),
|
||||||
|
box-shadow var(--kl-transition),
|
||||||
|
color var(--kl-transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
[id$="-tab"]:hover {
|
||||||
|
color: var(--kl-text);
|
||||||
|
border-color: rgba(0, 200, 160, 0.28);
|
||||||
|
background: linear-gradient(180deg, var(--kl-tab-hover), rgba(8, 15, 20, 0.88));
|
||||||
|
box-shadow: var(--kl-glow);
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[id$="-tab"].tab-focused,
|
||||||
|
[id$="-tab"].active,
|
||||||
|
[id$="-tab"][aria-selected="true"] {
|
||||||
|
color: var(--kl-text);
|
||||||
|
border-color: var(--kl-border-active);
|
||||||
|
background: linear-gradient(180deg, var(--kl-tab-active), rgba(7, 14, 18, 0.9));
|
||||||
|
box-shadow: var(--kl-glow-strong);
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
.tabcontent {
|
.tabcontent {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
inset: 0;
|
|
||||||
display: none;
|
display: none;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
transition: opacity 220ms ease, visibility 220ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabcontent.active {
|
.tabcontent.active {
|
||||||
display: block;
|
display: block;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
margin: 12px 0 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
[id$="-tab"] {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: 60px;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: var(--card-border);
|
}
|
||||||
border-radius: var(--border-radius);
|
|
||||||
background-color: #18191a;
|
/* ============================================================================
|
||||||
text-align: center;
|
GROUP TITLES
|
||||||
text-shadow: var(--text-shadow);
|
============================================================================ */
|
||||||
text-transform: uppercase;
|
|
||||||
|
.service-group,
|
||||||
|
.services-group,
|
||||||
|
.bookmarks-group,
|
||||||
|
.widget-group {
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2,
|
||||||
|
.group-title,
|
||||||
|
.section-title {
|
||||||
|
color: var(--kl-text-soft);
|
||||||
|
font-family: var(--kl-font-ui);
|
||||||
|
font-size: 0.88rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
white-space: nowrap;
|
letter-spacing: 0.14em;
|
||||||
cursor: pointer;
|
text-transform: uppercase;
|
||||||
user-select: none;
|
|
||||||
transition: var(--transition);
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
contain: layout style paint;
|
|
||||||
will-change: background-color, border-color;
|
|
||||||
backface-visibility: hidden;
|
|
||||||
transform: translateZ(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
[id$="-tab"]::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: -5px;
|
|
||||||
background-color: var(--card-bg);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[id$="-tab"]:hover {
|
|
||||||
background-color: #1e2021;
|
|
||||||
border-color: var(--card-border-hover);
|
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[id$="-tab"].tab-focused,
|
|
||||||
[id$="-tab"].active {
|
|
||||||
background-color: #1e2021;
|
|
||||||
border-color: var(--card-border-focus);
|
|
||||||
outline: none;
|
|
||||||
box-shadow: var(--focus-ring);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
SERVICE CARDS
|
SERVICE CARDS
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
|
|
||||||
.service-card {
|
.service-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: var(--card-border);
|
border: 1px solid var(--kl-border);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--kl-radius);
|
||||||
background-color: #18191a;
|
background: linear-gradient(180deg, rgba(12, 20, 26, 0.72), rgba(8, 14, 18, 0.72));
|
||||||
text-shadow: var(--text-shadow);
|
box-shadow:
|
||||||
font-weight: 400;
|
inset 0 1px 0 rgba(255, 255, 255, 0.03),
|
||||||
white-space: nowrap;
|
var(--kl-shadow);
|
||||||
transition: var(--transition);
|
color: var(--kl-text);
|
||||||
contain: layout style paint;
|
text-shadow: none;
|
||||||
will-change: background-color, border-color;
|
font-weight: 500;
|
||||||
content-visibility: auto;
|
white-space: normal;
|
||||||
contain-intrinsic-size: auto 200px;
|
overflow: hidden;
|
||||||
backface-visibility: hidden;
|
transition:
|
||||||
transform: translateZ(0);
|
border-color var(--kl-transition),
|
||||||
|
background var(--kl-transition),
|
||||||
|
box-shadow var(--kl-transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-card::before {
|
.service-card::before {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: -5px;
|
inset: 0;
|
||||||
background-color: var(--card-bg);
|
background: linear-gradient(135deg, rgba(74, 219, 196, 0.03), transparent 36%);
|
||||||
border-radius: var(--border-radius);
|
pointer-events: none;
|
||||||
z-index: -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-card:hover {
|
.service-card:hover {
|
||||||
background-color: #1e2021;
|
border-color: var(--kl-border-strong);
|
||||||
border-color: var(--card-border-hover);
|
background: linear-gradient(180deg, rgba(14, 24, 31, 0.78), rgba(9, 16, 21, 0.78));
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.04),
|
||||||
|
0 14px 34px rgba(0, 0, 0, 0.26),
|
||||||
|
0 0 0 1px rgba(0, 200, 160, 0.05),
|
||||||
|
0 0 18px rgba(0, 200, 160, 0.1);
|
||||||
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-card > :is(div, span, h1, h2, h3, h4, h5, h6, p):first-child:not(.service-container),
|
.service-card a {
|
||||||
.bookmark,
|
color: inherit;
|
||||||
.widget-container {
|
text-decoration: none;
|
||||||
font-weight: 700;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-card > :first-child:not(.service-container),
|
.service-header,
|
||||||
.service-card > .service-header,
|
.service-title,
|
||||||
.service-card > .service-title {
|
.card-title {
|
||||||
margin-bottom: 1px;
|
color: var(--kl-text) !important;
|
||||||
|
font-family: var(--kl-font-ui);
|
||||||
|
font-weight: 700 !important;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-card > :nth-child(2):not(.service-header):not(.service-title),
|
.service-description,
|
||||||
.service-card > .service-body,
|
.card-description,
|
||||||
.service-card > .service-content {
|
.service-card p {
|
||||||
margin-top: 1px;
|
color: var(--kl-text-dim) !important;
|
||||||
}
|
|
||||||
|
|
||||||
.service-card:has(iframe) .service-container {
|
|
||||||
margin-top: 0;
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.service-card a:-moz-any-link {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.service-card :is(a:focus, a:hover, div[onclick]:hover) {
|
|
||||||
background-color: transparent;
|
|
||||||
outline: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-icon img {
|
.service-icon img {
|
||||||
width: 12px;
|
width: 18px;
|
||||||
height: 12px;
|
height: 18px;
|
||||||
vertical-align: middle;
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-container {
|
||||||
|
color: var(--kl-text-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-block {
|
.service-block {
|
||||||
position: relative;
|
position: relative;
|
||||||
border: 2px solid darkslategrey;
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.service-block:has(iframe) {
|
|
||||||
border: none;
|
border: none;
|
||||||
|
border-radius: var(--kl-radius);
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-block:has(.epl),
|
.service-card .status,
|
||||||
.service-block:has(.uptime),
|
.service-status,
|
||||||
.service-block:has(.todo) {
|
.card-status {
|
||||||
border-color: #191c1d;
|
font-family: var(--kl-font-tech);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--kl-text-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
INFORMATION WIDGETS
|
IFRAMES / SPECIALS
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
#information-widgets {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#information-widgets-right {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.information-widget-greeting {
|
|
||||||
flex-grow: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.information-widget-resources {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.information-widget-resource {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
#information-widgets > * {
|
|
||||||
position: relative;
|
|
||||||
border: none;
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
backdrop-filter: none;
|
|
||||||
text-shadow: var(--text-shadow);
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: 700;
|
|
||||||
white-space: nowrap;
|
|
||||||
transition: var(--transition);
|
|
||||||
contain: layout;
|
|
||||||
will-change: transform;
|
|
||||||
content-visibility: auto;
|
|
||||||
contain-intrinsic-size: auto 200px;
|
|
||||||
backface-visibility: hidden;
|
|
||||||
transform: translateZ(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#information-widgets > *::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#information-widgets > *:is(:hover, :focus) {
|
|
||||||
background-color: transparent !important;
|
|
||||||
border-color: transparent !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
backdrop-filter: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
IFRAME CONTAINERS
|
|
||||||
============================================================================ */
|
|
||||||
iframe {
|
iframe {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 0;
|
border: 0;
|
||||||
@@ -311,8 +304,9 @@ iframe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
CUSTOM LISTS - OPTIMIZED SELECTORS
|
CUSTOM LISTS
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
|
|
||||||
#upcominggames .flex.flex-row.text-right,
|
#upcominggames .flex.flex-row.text-right,
|
||||||
#tautulli_recent_movies .flex.flex-row.text-right,
|
#tautulli_recent_movies .flex.flex-row.text-right,
|
||||||
#tautulli_recent_shows .flex.flex-row.text-right {
|
#tautulli_recent_shows .flex.flex-row.text-right {
|
||||||
@@ -386,62 +380,14 @@ iframe {
|
|||||||
margin: 3px 3px 1px;
|
margin: 3px 3px 1px;
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
text-shadow: var(--text-shadow);
|
text-shadow: none;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
#headlessui-disclosure-panel-\:r6\: > ul:first-child > li:first-child > div:first-child > div:first-child {
|
|
||||||
margin: -100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
ANIMATIONS
|
UTILITIES
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
@keyframes updatePulse {
|
|
||||||
0%, 100% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes loadingBar {
|
|
||||||
0% {
|
|
||||||
width: 0;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
width: 100%;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.service-card.updating {
|
|
||||||
animation: updatePulse 0.5s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.service-card.loading::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 2px;
|
|
||||||
background: var(--card-border-hover);
|
|
||||||
animation: loadingBar 2s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
UTILITY CLASSES
|
|
||||||
============================================================================ */
|
|
||||||
.container {
|
|
||||||
max-width: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -477,54 +423,73 @@ iframe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
RESPONSIVE DESIGN
|
ANIMATIONS
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
@media (max-width: 768px) {
|
|
||||||
:root {
|
|
||||||
--card-padding: 10px;
|
|
||||||
--card-margin: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@keyframes updatePulse {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.74;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loadingBar {
|
||||||
|
0% {
|
||||||
|
width: 0;
|
||||||
|
opacity: 0.45;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
width: 100%;
|
||||||
|
opacity: 0.45;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card.updating {
|
||||||
|
animation: updatePulse 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card.loading::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(90deg, rgba(0, 200, 160, 0.2), rgba(74, 219, 196, 0.9));
|
||||||
|
animation: loadingBar 2s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
RESPONSIVE
|
||||||
|
============================================================================ */
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
#myTab {
|
#myTab {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 5px;
|
gap: 8px;
|
||||||
margin: 0;
|
margin: 0 12px 18px;
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[id$="-tab"] {
|
[id$="-tab"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 15px;
|
min-width: 0;
|
||||||
text-align: center;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabcontent {
|
.container {
|
||||||
margin: 0;
|
max-width: 100%;
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-card,
|
.service-card,
|
||||||
[id$="-tab"] {
|
[id$="-tab"] {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide-on-mobile {
|
|
||||||
display: none !important;
|
|
||||||
height: 0 !important;
|
|
||||||
min-height: 0 !important;
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
#myTab {
|
|
||||||
gap: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.service-card,
|
.service-card,
|
||||||
[id$="-tab"] {
|
[id$="-tab"] {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -546,23 +511,90 @@ iframe {
|
|||||||
transition-duration: 0.01ms !important;
|
transition-duration: 0.01ms !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
BOOKMARKS — gleicher Look wie Service Cards
|
BOOKMARKS — FINAL MATCH TO MAIN CARDS
|
||||||
Homepage rendert Bookmarks als <a> Tags mit Tailwind-Klassen
|
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
.service-block a[href],
|
|
||||||
#bookmarks a[href] {
|
/* Haupt-Balken */
|
||||||
border: var(--card-border);
|
#bookmarks a[href],
|
||||||
border-radius: var(--border-radius);
|
.service-block a[href] {
|
||||||
background-color: var(--bg-color-light);
|
position: relative;
|
||||||
text-shadow: var(--text-shadow);
|
|
||||||
transition: var(--transition);
|
border: 1px solid var(--kl-border) !important;
|
||||||
|
border-radius: 14px;
|
||||||
|
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(12, 20, 26, 0.72),
|
||||||
|
rgba(8, 14, 18, 0.72)
|
||||||
|
) !important;
|
||||||
|
|
||||||
|
backdrop-filter: blur(6px);
|
||||||
|
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.03),
|
||||||
|
var(--kl-shadow);
|
||||||
|
|
||||||
|
transition:
|
||||||
|
border-color var(--kl-transition),
|
||||||
|
background var(--kl-transition),
|
||||||
|
box-shadow var(--kl-transition);
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-block a[href]:hover,
|
/* leichter Glow Layer wie bei Cards */
|
||||||
#bookmarks a[href]:hover {
|
#bookmarks a[href]::before,
|
||||||
background-color: var(--bg-color);
|
.service-block a[href]::before {
|
||||||
border-color: var(--card-border-hover);
|
content: "";
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(74, 219, 196, 0.04),
|
||||||
|
transparent 40%
|
||||||
|
);
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover exakt wie Main Cards */
|
||||||
|
#bookmarks a[href]:hover,
|
||||||
|
.service-block a[href]:hover {
|
||||||
|
border-color: var(--kl-border-strong) !important;
|
||||||
|
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(14, 24, 31, 0.78),
|
||||||
|
rgba(9, 16, 21, 0.78)
|
||||||
|
) !important;
|
||||||
|
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.04),
|
||||||
|
0 14px 34px rgba(0, 0, 0, 0.26),
|
||||||
|
0 0 0 1px rgba(0, 200, 160, 0.05),
|
||||||
|
0 0 18px rgba(0, 200, 160, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text sauber wie oben */
|
||||||
|
#bookmarks a[href] * {
|
||||||
|
color: var(--kl-text-soft) !important;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bookmarks a[href]:hover * {
|
||||||
|
color: var(--kl-text) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icons etwas cleaner */
|
||||||
|
#bookmarks img {
|
||||||
|
border-radius: 6px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* leichte Separation zwischen Reihen */
|
||||||
|
#bookmarks .flex,
|
||||||
|
#bookmarks .grid {
|
||||||
|
gap: 10px;
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
KalliLab — CUSTOM JAVASCRIPT
|
KalliLab — CUSTOM JAVASCRIPT
|
||||||
Basiert auf LionCityGaming/homepage custom.js (MIT License)
|
Home / Media Tabs
|
||||||
Anpassungen: KalliLab Tab-Namen, keine HA/EPL/Glance iFrames
|
Reload-Button entfernen
|
||||||
|
Aktiven Tab merken
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
|
|
||||||
const CONFIG = {
|
const CONFIG = {
|
||||||
STORAGE: {
|
STORAGE: {
|
||||||
KEY: "lastFocusedTabId",
|
KEY: "kallilab-last-focused-tab-id",
|
||||||
},
|
},
|
||||||
TIMING: {
|
TIMING: {
|
||||||
RETRY_DELAY: 500,
|
RETRY_DELAY: 500,
|
||||||
STANDARD_REFRESH: 1800000, // 30 Minuten
|
STANDARD_REFRESH: 1800000,
|
||||||
QUICK_REFRESH: 60000, // 1 Minute
|
QUICK_REFRESH: 60000,
|
||||||
RETRY_ON_ERROR: 30000,
|
RETRY_ON_ERROR: 30000,
|
||||||
BATCH_DELAY: 100,
|
BATCH_DELAY: 100,
|
||||||
},
|
},
|
||||||
SERVICES: {
|
SERVICES: {
|
||||||
QUICK_REFRESH: [], // keine kritischen Quick-Refresh Widgets
|
QUICK_REFRESH: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,17 +29,10 @@ const RELOAD_BUTTON_SELECTORS = [
|
|||||||
'[role="button"][aria-label="Reload"]',
|
'[role="button"][aria-label="Reload"]',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Keine iFrame-Widgets in KalliLab
|
const TAB_HASH_MAP = {
|
||||||
const IFRAME_CONFIG = [];
|
"#home": "Home-tab",
|
||||||
|
"#media": "Media-tab",
|
||||||
// Tab-Mapping für KalliLab Tabs (5 Tabs)
|
"": "Home-tab",
|
||||||
const TAB_MAPPING = {
|
|
||||||
"#ueberblick": ["#Überblick-tab", "#Überblick"],
|
|
||||||
"#system": ["#System-tab", "#System"],
|
|
||||||
"#sicherheit": ["#Sicherheit-tab", "#Sicherheit"],
|
|
||||||
"#dienste": ["#Dienste-tab", "#Dienste"],
|
|
||||||
"#backends": ["#Backends-tab", "#Backends"],
|
|
||||||
"": ["#Überblick-tab", "#Überblick"],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
@@ -46,7 +40,6 @@ const state = {
|
|||||||
currentFocusedTab: null,
|
currentFocusedTab: null,
|
||||||
observers: {
|
observers: {
|
||||||
reloadButton: null,
|
reloadButton: null,
|
||||||
resize: null,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,7 +98,9 @@ function throttle(func, limit) {
|
|||||||
if (!inThrottle) {
|
if (!inThrottle) {
|
||||||
func.apply(this, args);
|
func.apply(this, args);
|
||||||
inThrottle = true;
|
inThrottle = true;
|
||||||
setTimeout(() => (inThrottle = false), limit);
|
setTimeout(() => {
|
||||||
|
inThrottle = false;
|
||||||
|
}, limit);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -141,6 +136,81 @@ function setupReloadButtonObserver() {
|
|||||||
return observer;
|
return observer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setTabFocus(tab) {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
if (state.currentFocusedTab) {
|
||||||
|
state.currentFocusedTab.classList.remove("tab-focused");
|
||||||
|
}
|
||||||
|
|
||||||
|
state.currentFocusedTab = tab;
|
||||||
|
|
||||||
|
if (state.currentFocusedTab) {
|
||||||
|
state.currentFocusedTab.classList.add("tab-focused");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showTabContent(contentElement) {
|
||||||
|
if (!contentElement || !domCache.tabContents) return;
|
||||||
|
|
||||||
|
domCache.tabContents.forEach((content) => {
|
||||||
|
content.classList.remove("active");
|
||||||
|
content.style.display = "none";
|
||||||
|
});
|
||||||
|
|
||||||
|
contentElement.classList.add("active");
|
||||||
|
contentElement.style.display = "block";
|
||||||
|
domCache.updateActiveTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveTabContentElement(tab) {
|
||||||
|
if (!tab) return null;
|
||||||
|
|
||||||
|
const ariaControls = tab.getAttribute("aria-controls");
|
||||||
|
if (ariaControls) {
|
||||||
|
return document.getElementById(ariaControls);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabText = (tab.textContent || "").trim().toLowerCase();
|
||||||
|
const directMatch = Array.from(document.querySelectorAll(".tabcontent")).find((content) => {
|
||||||
|
return content.id.toLowerCase() === tabText;
|
||||||
|
});
|
||||||
|
|
||||||
|
return directMatch || document.querySelector(".tabcontent.active");
|
||||||
|
}
|
||||||
|
|
||||||
|
function activateTab(tab, updateHash = true) {
|
||||||
|
if (!tab) return;
|
||||||
|
|
||||||
|
setTabFocus(tab);
|
||||||
|
storage.save(tab.id);
|
||||||
|
|
||||||
|
const contentToShow = resolveTabContentElement(tab);
|
||||||
|
showTabContent(contentToShow);
|
||||||
|
|
||||||
|
if (updateHash) {
|
||||||
|
const normalized = (tab.textContent || "").trim().toLowerCase();
|
||||||
|
if (normalized === "home") {
|
||||||
|
history.replaceState(null, "", "#home");
|
||||||
|
} else if (normalized === "media") {
|
||||||
|
history.replaceState(null, "", "#media");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTabFocusFromURL() {
|
||||||
|
const hash = window.location.hash.toLowerCase();
|
||||||
|
const tabId = TAB_HASH_MAP[hash] || TAB_HASH_MAP[""];
|
||||||
|
const tabToFocus = document.getElementById(tabId);
|
||||||
|
|
||||||
|
if (tabToFocus) {
|
||||||
|
activateTab(tabToFocus, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function updateServiceCard(card, data) {
|
function updateServiceCard(card, data) {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const titleElement = card.querySelector(".card-title");
|
const titleElement = card.querySelector(".card-title");
|
||||||
@@ -154,6 +224,7 @@ function updateServiceCard(card, data) {
|
|||||||
statusElement.textContent = Array.isArray(data)
|
statusElement.textContent = Array.isArray(data)
|
||||||
? `${data.length} items`
|
? `${data.length} items`
|
||||||
: (data.status ?? (typeof data === "object" ? "Data received" : ""));
|
: (data.status ?? (typeof data === "object" ? "Data received" : ""));
|
||||||
|
statusElement.style.color = "";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -165,7 +236,7 @@ function updateServiceCardError(card, error) {
|
|||||||
statusElement.textContent = error.message.includes("404")
|
statusElement.textContent = error.message.includes("404")
|
||||||
? "Service unavailable"
|
? "Service unavailable"
|
||||||
: "Error loading data";
|
: "Error loading data";
|
||||||
statusElement.style.color = "red";
|
statusElement.style.color = "#ff7b7b";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -221,53 +292,14 @@ async function batchUpdateServiceCards(cards) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTabFocusFromURL() {
|
|
||||||
const hash = window.location.hash.toLowerCase();
|
|
||||||
const mapping = TAB_MAPPING[hash] || TAB_MAPPING[""];
|
|
||||||
const [tabSelector, contentSelector] = mapping;
|
|
||||||
|
|
||||||
const tabToFocus = document.querySelector(tabSelector);
|
|
||||||
const contentToShow = document.querySelector(contentSelector);
|
|
||||||
|
|
||||||
if (tabToFocus) {
|
|
||||||
setTabFocus(tabToFocus);
|
|
||||||
storage.save(tabToFocus.id);
|
|
||||||
|
|
||||||
domCache.tabContents.forEach((content) => {
|
|
||||||
content.classList.remove("active");
|
|
||||||
content.style.display = "none";
|
|
||||||
});
|
|
||||||
|
|
||||||
if (contentToShow) {
|
|
||||||
showTabContent(contentToShow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTabFocus(tab) {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
if (state.currentFocusedTab) {
|
|
||||||
state.currentFocusedTab.classList.remove("tab-focused");
|
|
||||||
}
|
|
||||||
state.currentFocusedTab = tab;
|
|
||||||
state.currentFocusedTab.classList.add("tab-focused");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showTabContent(contentElement) {
|
|
||||||
if (!contentElement) return;
|
|
||||||
|
|
||||||
contentElement.classList.add("active");
|
|
||||||
contentElement.style.display = "block";
|
|
||||||
domCache.updateActiveTab();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function preloadAllTabs() {
|
async function preloadAllTabs() {
|
||||||
const tabContents = document.querySelectorAll(".tab-pane");
|
const tabContents = document.querySelectorAll(".tabcontent, .tab-pane");
|
||||||
const serviceCards = new Set();
|
const serviceCards = new Set();
|
||||||
|
|
||||||
tabContents.forEach((tab) => {
|
tabContents.forEach((tab) => {
|
||||||
tab.querySelectorAll(".service-card").forEach((card) => serviceCards.add(card));
|
tab.querySelectorAll(".service-card[data-api-endpoint]").forEach((card) => {
|
||||||
|
serviceCards.add(card);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
await batchUpdateServiceCards(Array.from(serviceCards));
|
await batchUpdateServiceCards(Array.from(serviceCards));
|
||||||
@@ -295,49 +327,45 @@ function setupPeriodicRefresh() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
domCache.myTab?.addEventListener("click", (event) => {
|
domCache.myTab?.addEventListener("click", (event) => {
|
||||||
if (event.target.matches('[id$="-tab"]')) {
|
const tab = event.target.closest('[id$="-tab"]');
|
||||||
|
if (tab) {
|
||||||
|
activateTab(tab);
|
||||||
debouncedRefresh();
|
debouncedRefresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeTabFocus() {
|
function initializeTabFocus() {
|
||||||
// KalliLab Tab-Selektoren
|
const tabs = document.querySelectorAll('#myTab [id$="-tab"]');
|
||||||
const tabs = document.querySelectorAll(
|
if (!tabs.length) return;
|
||||||
"#Überblick-tab, #System-tab, #Sicherheit-tab, #Dienste-tab, #Backends-tab",
|
|
||||||
);
|
|
||||||
|
|
||||||
handleTabFocusFromURL();
|
const handledByHash = handleTabFocusFromURL();
|
||||||
|
|
||||||
if (!window.location.hash) {
|
if (!handledByHash) {
|
||||||
const savedTabId = storage.get();
|
const savedTabId = storage.get();
|
||||||
const savedTab = savedTabId && document.getElementById(savedTabId);
|
const savedTab = savedTabId && document.getElementById(savedTabId);
|
||||||
|
|
||||||
if (savedTab) {
|
if (savedTab) {
|
||||||
setTabFocus(savedTab);
|
activateTab(savedTab, false);
|
||||||
} else {
|
} else {
|
||||||
const activeTab = document.querySelector(".tabcontent.active");
|
const activeTab = document.querySelector('#myTab [aria-selected="true"]');
|
||||||
const correspondingTab =
|
if (activeTab) {
|
||||||
activeTab && document.querySelector(`[aria-controls="${activeTab.id}"]`);
|
activateTab(activeTab, false);
|
||||||
if (correspondingTab) {
|
} else {
|
||||||
setTabFocus(correspondingTab);
|
activateTab(tabs[0], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tabs.forEach((tab) => {
|
tabs.forEach((tab) => {
|
||||||
const handleTabAction = function () {
|
tab.addEventListener("click", () => {
|
||||||
setTabFocus(this);
|
activateTab(tab);
|
||||||
storage.save(this.id);
|
});
|
||||||
};
|
|
||||||
|
|
||||||
tab.addEventListener("click", handleTabAction);
|
tab.addEventListener("keydown", (e) => {
|
||||||
|
|
||||||
tab.addEventListener("keydown", function (e) {
|
|
||||||
if (e.key === "Enter" || e.key === " ") {
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.click();
|
activateTab(tab);
|
||||||
handleTabAction.call(this);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -347,6 +375,10 @@ function initializeTabFocus() {
|
|||||||
storage.save(state.currentFocusedTab.id);
|
storage.save(state.currentFocusedTab.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.addEventListener("hashchange", () => {
|
||||||
|
handleTabFocusFromURL();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeEverything() {
|
function initializeEverything() {
|
||||||
@@ -368,14 +400,21 @@ function initializeEverything() {
|
|||||||
} else {
|
} else {
|
||||||
setTimeout(initializeEverything, CONFIG.TIMING.RETRY_DELAY);
|
setTimeout(initializeEverything, CONFIG.TIMING.RETRY_DELAY);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener("orientationchange", () => {
|
function cleanup() {
|
||||||
setTimeout(removeReloadButton, 100);
|
if (state.observers.reloadButton) {
|
||||||
});
|
state.observers.reloadButton.disconnect();
|
||||||
|
state.observers.reloadButton = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
domCache.clear();
|
||||||
|
state.currentFocusedTab = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", removeReloadButton);
|
document.addEventListener("DOMContentLoaded", removeReloadButton);
|
||||||
window.addEventListener("load", initializeEverything);
|
window.addEventListener("load", initializeEverything);
|
||||||
|
window.addEventListener("unload", cleanup);
|
||||||
|
|
||||||
if (typeof window.htmlLoaded === "function") {
|
if (typeof window.htmlLoaded === "function") {
|
||||||
const originalHtmlLoaded = window.htmlLoaded;
|
const originalHtmlLoaded = window.htmlLoaded;
|
||||||
@@ -386,22 +425,11 @@ if (typeof window.htmlLoaded === "function") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("ontouchstart" in window) {
|
if ("ontouchstart" in window) {
|
||||||
window.addEventListener("touchend", () => {
|
window.addEventListener(
|
||||||
|
"touchend",
|
||||||
|
() => {
|
||||||
setTimeout(removeReloadButton, 100);
|
setTimeout(removeReloadButton, 100);
|
||||||
}, { passive: true });
|
},
|
||||||
|
{ passive: true },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
|
||||||
if (state.observers.reloadButton) {
|
|
||||||
state.observers.reloadButton.disconnect();
|
|
||||||
state.observers.reloadButton = null;
|
|
||||||
}
|
|
||||||
if (state.observers.resize) {
|
|
||||||
state.observers.resize.disconnect();
|
|
||||||
state.observers.resize = null;
|
|
||||||
}
|
|
||||||
domCache.clear();
|
|
||||||
state.currentFocusedTab = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("unload", cleanup);
|
|
||||||
+12277
File diff suppressed because it is too large
Load Diff
+9
-15
@@ -176,7 +176,6 @@
|
|||||||
description: Fotos & Videos
|
description: Fotos & Videos
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: immich_server
|
container: immich_server
|
||||||
siteMonitor: http://192.168.178.58:2283
|
|
||||||
widget:
|
widget:
|
||||||
type: immich
|
type: immich
|
||||||
url: http://192.168.178.58:2283
|
url: http://192.168.178.58:2283
|
||||||
@@ -246,7 +245,6 @@
|
|||||||
description: Startseite
|
description: Startseite
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: homepage
|
container: homepage
|
||||||
siteMonitor: https://home.kaleschke.info
|
|
||||||
|
|
||||||
- Dozzle:
|
- Dozzle:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/dozzle.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/dozzle.webp
|
||||||
@@ -254,7 +252,6 @@
|
|||||||
description: Container-Logs
|
description: Container-Logs
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: Dozzle
|
container: Dozzle
|
||||||
siteMonitor: http://192.168.178.58:9888
|
|
||||||
|
|
||||||
- Tailscale:
|
- Tailscale:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/tailscale.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/tailscale.webp
|
||||||
@@ -269,7 +266,6 @@
|
|||||||
description: UI-Themes
|
description: UI-Themes
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: theme-park
|
container: theme-park
|
||||||
siteMonitor: http://192.168.178.58:8009
|
|
||||||
|
|
||||||
- DDNS Updater:
|
- DDNS Updater:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/ddns-updater.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/ddns-updater.webp
|
||||||
@@ -289,15 +285,13 @@
|
|||||||
description: Server-Dashboard
|
description: Server-Dashboard
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: dashdot
|
container: dashdot
|
||||||
siteMonitor: http://192.168.178.58:3002
|
|
||||||
|
|
||||||
- ntopng:
|
- ntopng:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/ntopng.webp
|
icon: mdi-chart-line
|
||||||
href: http://kallilabcore.local:3000
|
href: http://kallilabcore.local:3000
|
||||||
description: Netzwerktraffic
|
description: Netzwerktraffic
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: ntopng
|
container: ntopng
|
||||||
siteMonitor: http://192.168.178.58:3000
|
|
||||||
|
|
||||||
- NetAlertX:
|
- NetAlertX:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/netalertx.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/netalertx.webp
|
||||||
@@ -307,12 +301,11 @@
|
|||||||
container: netalertx
|
container: netalertx
|
||||||
|
|
||||||
- Code Server:
|
- Code Server:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/code-server.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/visual-studio-code.webp
|
||||||
href: https://code.kaleschke.info
|
href: https://code.kaleschke.info
|
||||||
description: Browser-IDE
|
description: Browser-IDE
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: code-server
|
container: code-server
|
||||||
siteMonitor: https://code.kaleschke.info
|
|
||||||
|
|
||||||
- Paperless-AI:
|
- Paperless-AI:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp
|
||||||
@@ -320,7 +313,6 @@
|
|||||||
description: KI-Dokumente
|
description: KI-Dokumente
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: Paperless-AI
|
container: Paperless-AI
|
||||||
siteMonitor: http://192.168.178.58:3236
|
|
||||||
|
|
||||||
- Vaultwarden:
|
- Vaultwarden:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/vaultwarden.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/vaultwarden.webp
|
||||||
@@ -328,7 +320,6 @@
|
|||||||
description: Passwortmanager
|
description: Passwortmanager
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: vaultwarden
|
container: vaultwarden
|
||||||
siteMonitor: https://kallilabcore.taild9fcf2.ts.net:4743
|
|
||||||
|
|
||||||
- Unbound:
|
- Unbound:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/unbound.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/unbound.webp
|
||||||
@@ -342,7 +333,6 @@
|
|||||||
description: Mail-Archiv
|
description: Mail-Archiv
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: mail-archiver
|
container: mail-archiver
|
||||||
siteMonitor: http://192.168.178.58:5000
|
|
||||||
|
|
||||||
- Scanopy:
|
- Scanopy:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp
|
||||||
@@ -350,15 +340,13 @@
|
|||||||
description: Scan-Workflow
|
description: Scan-Workflow
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: scanopy-server
|
container: scanopy-server
|
||||||
siteMonitor: http://192.168.178.58:60072
|
|
||||||
|
|
||||||
- luckyBackup:
|
- luckyBackup:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/luckybackup.webp
|
icon: mdi-backup-restore
|
||||||
href: http://kallilabcore.local:7675/vnc.html?autoconnect=true
|
href: http://kallilabcore.local:7675/vnc.html?autoconnect=true
|
||||||
description: Backup-GUI
|
description: Backup-GUI
|
||||||
server: my-docker
|
server: my-docker
|
||||||
container: luckyBackup
|
container: luckyBackup
|
||||||
siteMonitor: http://192.168.178.58:7675
|
|
||||||
|
|
||||||
- Scanopy Daemon:
|
- Scanopy Daemon:
|
||||||
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp
|
||||||
@@ -366,6 +354,12 @@
|
|||||||
server: my-docker
|
server: my-docker
|
||||||
container: scanopy-daemon
|
container: scanopy-daemon
|
||||||
|
|
||||||
|
- Filebrowser:
|
||||||
|
icon: mdi-folder-open
|
||||||
|
href: http://192.168.178.58:8085
|
||||||
|
description: Filesystem GUI
|
||||||
|
container: filebrowser
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# TAB: Home — BACKENDS MINI
|
# TAB: Home — BACKENDS MINI
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|||||||
+6
-6
@@ -5,14 +5,14 @@ disableCollapse: false
|
|||||||
|
|
||||||
background:
|
background:
|
||||||
image: /images/back10.jpg
|
image: /images/back10.jpg
|
||||||
saturate: 1
|
saturate: 0.95
|
||||||
brightness: 100
|
brightness: 78
|
||||||
opacity: 100
|
opacity: 100
|
||||||
|
|
||||||
cardBlur: 4xl
|
cardBlur: xl
|
||||||
theme: dark
|
theme: dark
|
||||||
color: emerald
|
color: emerald
|
||||||
headerStyle: underlined
|
headerStyle: clean
|
||||||
iconStyle: theme
|
iconStyle: theme
|
||||||
statusStyle: dot
|
statusStyle: dot
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ hideVersion: true
|
|||||||
hideErrors: false
|
hideErrors: false
|
||||||
fiveColumns: false
|
fiveColumns: false
|
||||||
useEqualHeights: true
|
useEqualHeights: true
|
||||||
preloadAllWidgets: true
|
preloadAllWidgets: false
|
||||||
target: _blank
|
target: _blank
|
||||||
|
|
||||||
language: de
|
language: de
|
||||||
@@ -52,7 +52,7 @@ layout:
|
|||||||
header: false
|
header: false
|
||||||
tab: Home
|
tab: Home
|
||||||
style: row
|
style: row
|
||||||
columns: 6
|
columns: 5
|
||||||
|
|
||||||
BACKENDS MINI:
|
BACKENDS MINI:
|
||||||
header: false
|
header: false
|
||||||
|
|||||||
+11
-36
@@ -1,49 +1,24 @@
|
|||||||
- logo:
|
|
||||||
icon: /images/icons/logo.png
|
|
||||||
href: https://home.kaleschke.info
|
|
||||||
target: _blank
|
|
||||||
|
|
||||||
- greeting:
|
- greeting:
|
||||||
text_size: 3xl
|
text_size: 2xl
|
||||||
text: KalliLab
|
text: KALLILAB CORE
|
||||||
href: https://home.kaleschke.info
|
href: https://home.kaleschke.info
|
||||||
target: _blank
|
target: _blank
|
||||||
|
|
||||||
- datetime:
|
|
||||||
locale: de-DE
|
|
||||||
text_size: 3xl
|
|
||||||
format:
|
|
||||||
dateStyle: full
|
|
||||||
hour12: false
|
|
||||||
timeStyle: short
|
|
||||||
|
|
||||||
# Jede Metrik = eigener Block = alle nebeneinander
|
|
||||||
- resources:
|
|
||||||
cpu: true
|
|
||||||
|
|
||||||
- resources:
|
|
||||||
memory: true
|
|
||||||
|
|
||||||
- resources:
|
|
||||||
cputemp: true
|
|
||||||
units: metric
|
|
||||||
|
|
||||||
- resources:
|
|
||||||
uptime: true
|
|
||||||
|
|
||||||
- resources:
|
|
||||||
label: KalliLab
|
|
||||||
disk: /
|
|
||||||
href: http://kallilabcore.local:61208
|
|
||||||
target: _blank
|
|
||||||
|
|
||||||
- search:
|
- search:
|
||||||
provider: google
|
provider: google
|
||||||
focus: false
|
focus: false
|
||||||
target: _blank
|
target: _blank
|
||||||
|
|
||||||
|
- datetime:
|
||||||
|
locale: de-DE
|
||||||
|
text_size: xl
|
||||||
|
format:
|
||||||
|
dateStyle: full
|
||||||
|
hour12: false
|
||||||
|
timeStyle: short
|
||||||
|
|
||||||
- openmeteo:
|
- openmeteo:
|
||||||
label: KalliLab
|
label: Horstmar
|
||||||
latitude: 52.1497
|
latitude: 52.1497
|
||||||
longitude: 7.5205
|
longitude: 7.5205
|
||||||
units: metric
|
units: metric
|
||||||
|
|||||||
Reference in New Issue
Block a user