aboutsummaryrefslogtreecommitdiff
path: root/modules/dashboard/dashboard-template.nix
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2025-06-10 13:06:48 +0530
committerAkshay Nair <phenax5@gmail.com>2025-06-10 18:58:25 +0530
commit2a73a5899124fa15c3962b9bd385ebd415a0ccf9 (patch)
tree3b0c29a29cf9ef4c844afc90aafcd61ef8122d21 /modules/dashboard/dashboard-template.nix
parent279241632b566fd26011409672277ca02ed697d1 (diff)
downloadhomeserver-nixos-config-2a73a5899124fa15c3962b9bd385ebd415a0ccf9.tar.gz
homeserver-nixos-config-2a73a5899124fa15c3962b9bd385ebd415a0ccf9.zip
Add dashboard for linking services
Diffstat (limited to 'modules/dashboard/dashboard-template.nix')
-rw-r--r--modules/dashboard/dashboard-template.nix114
1 files changed, 114 insertions, 0 deletions
diff --git a/modules/dashboard/dashboard-template.nix b/modules/dashboard/dashboard-template.nix
new file mode 100644
index 0000000..a1df813
--- /dev/null
+++ b/modules/dashboard/dashboard-template.nix
@@ -0,0 +1,114 @@
+{ title, links, ... }:
+with builtins;
+let
+ withLinkAttr = link: attr: def: value:
+ if hasAttr attr link then value else def;
+
+ linkHTML = link: ''
+ <div>
+ <a href="${link.url}" class="card" style="${withLinkAttr link "color" "" "--color-card-accent: ${link.color}"}">
+ ${link.title} ${if hasAttr "key" link then "(${link.key})" else ""}
+ <div class="card-link">${link.url}</div>
+ </a>
+ </div>
+ '';
+
+ script = ''
+ window.addEventListener('keydown', (event) => {
+ const noMod = !event.ctrlKey && !event.altKey;
+ ${concatStringsSep "\n" (map (link:
+ withLinkAttr link "key" "" ''
+ if (event.key.toLowerCase() == ${toJSON link.key} && noMod) {
+ event.preventDefault();
+ if (event.shiftKey)
+ window.open(${toJSON link.url});
+ else
+ window.location.href = ${toJSON link.url};
+ return;
+ }
+ ''
+ ) links)}
+ });
+ '';
+
+ styles = ''
+ :root {
+ font-size: 16px;
+ color: #dbe0f9;
+ font-family: JetBrains Mono, monospace;
+ }
+ html, body {
+ background-color: #0f0c19;
+ padding: 0;
+ margin: 0;
+ }
+ body * { box-sizing: border-box; }
+ header {
+ padding: 1rem 2rem;
+ background-color: #000;
+ }
+ .links-container {
+ display: grid;
+ gap: 1rem;
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+ padding: 0 1rem;
+ width: 100%;
+ margin: 1rem auto;
+ max-width: 1200px
+ }
+ .card {
+ --color-card-accent: #8e7ae3;
+ display: block;
+ padding: 1rem 1.5rem;
+ font-size: 1.2rem;
+ color: var(--color-card-accent);
+ text-decoration: none;
+ border: 2px solid #1a1824;
+ position: relative;
+ }
+ .card::before {
+ content: " ";
+ position: absolute;
+ left: 0; top: 0;
+ width: 4px; height: 100%;
+ background-color: var(--color-card-accent);
+ }
+ .card:hover {
+ border-color: var(--color-card-accent);
+ background-color: rgba(255,255,255,0.05);
+ }
+ .card:focus {
+ border-color: var(--color-card-accent);
+ outline: none;
+ }
+ .card-link {
+ font-size: 0.5em;
+ padding-top: 1em;
+ color: gray;
+ }
+ '';
+
+ headerHTML = ''
+ <header>
+ ${title}
+ </header>
+ '';
+in
+''
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>${title}</title>
+ <style>${styles}</style>
+ </head>
+ <body>
+ ${headerHTML}
+ <section class="links-container">
+ ${concatStringsSep "" (map linkHTML links)}
+ </section>
+ <script>${script}</script>
+ </body>
+</html>
+''