From c1d86146af68750d11c25ac8abc7d9c641d0f484 Mon Sep 17 00:00:00 2001 From: orosmatthew Date: Sat, 26 Aug 2023 11:41:37 -0400 Subject: [PATCH] Improve navbar and add dark theme --- web/package-lock.json | 32 +++++++++++ web/package.json | 3 ++ web/src/app.d.ts | 4 +- web/src/app.html | 2 +- web/src/hooks.server.ts | 7 ++- web/src/routes/+layout.server.ts | 5 ++ web/src/routes/+layout.svelte | 17 ++++++ web/src/routes/admin/+layout.svelte | 84 ++++++++++++++++++++--------- web/src/routes/stores.ts | 3 ++ 9 files changed, 130 insertions(+), 27 deletions(-) create mode 100644 web/src/routes/+layout.server.ts create mode 100644 web/src/routes/stores.ts diff --git a/web/package-lock.json b/web/package-lock.json index d189690..c487cbc 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -13,10 +13,12 @@ "@types/fs-extra": "^11.0.1", "bcrypt": "^5.1.1", "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", "diff": "^5.1.0", "diff2html": "^3.4.40", "eslint-plugin-svelte": "^2.33.0", "fs-extra": "^11.1.1", + "js-cookie": "^3.0.5", "node-git-server": "^1.0.0", "prisma": "^5.2.0", "simple-git": "^3.19.1", @@ -29,6 +31,7 @@ "@types/bcrypt": "^5.0.0", "@types/bootstrap": "^5.2.6", "@types/diff": "^5.0.3", + "@types/js-cookie": "^3.0.3", "@types/node": "^20.5.6", "@types/uuid": "^9.0.2", "@typescript-eslint/eslint-plugin": "^6.4.1", @@ -919,6 +922,12 @@ "@types/node": "*" } }, + "node_modules/@types/js-cookie": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz", + "integrity": "sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", @@ -1327,6 +1336,21 @@ "@popperjs/core": "^2.11.8" } }, + "node_modules/bootstrap-icons": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.10.5.tgz", + "integrity": "sha512-oSX26F37V7QV7NCE53PPEL45d7EGXmBgHG3pDpZvcRaKVzWMqIRL9wcqJUyEha1esFtM3NJzvmxFXDxjJYD0jQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ] + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2385,6 +2409,14 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", diff --git a/web/package.json b/web/package.json index 9e45630..2b3e5c5 100644 --- a/web/package.json +++ b/web/package.json @@ -17,6 +17,7 @@ "@types/bcrypt": "^5.0.0", "@types/bootstrap": "^5.2.6", "@types/diff": "^5.0.3", + "@types/js-cookie": "^3.0.3", "@types/node": "^20.5.6", "@types/uuid": "^9.0.2", "@typescript-eslint/eslint-plugin": "^6.4.1", @@ -38,10 +39,12 @@ "@types/fs-extra": "^11.0.1", "bcrypt": "^5.1.1", "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", "diff": "^5.1.0", "diff2html": "^3.4.40", "eslint-plugin-svelte": "^2.33.0", "fs-extra": "^11.1.1", + "js-cookie": "^3.0.5", "node-git-server": "^1.0.0", "prisma": "^5.2.0", "simple-git": "^3.19.1", diff --git a/web/src/app.d.ts b/web/src/app.d.ts index f59b884..5037988 100644 --- a/web/src/app.d.ts +++ b/web/src/app.d.ts @@ -3,7 +3,9 @@ declare global { namespace App { // interface Error {} - // interface Locals {} + interface Locals { + theme: 'light' | 'dark'; + } // interface PageData {} // interface Platform {} } diff --git a/web/src/app.html b/web/src/app.html index 77ec85d..86694a9 100644 --- a/web/src/app.html +++ b/web/src/app.html @@ -1,5 +1,5 @@ - + diff --git a/web/src/hooks.server.ts b/web/src/hooks.server.ts index 69d328c..1e05a9e 100644 --- a/web/src/hooks.server.ts +++ b/web/src/hooks.server.ts @@ -24,6 +24,9 @@ try { startGitServer(); export const handle = (async ({ event, resolve }) => { + const theme = event.cookies.get('theme') as 'light' | 'dark' | undefined; + event.locals.theme = theme ?? 'dark'; + if (event.request.method === 'OPTIONS') { return new Response('ok', { headers: { @@ -46,6 +49,8 @@ export const handle = (async ({ event, resolve }) => { throw redirect(302, '/login'); } } - const res = await resolve(event); + const res = await resolve(event, { + transformPageChunk: ({ html }) => html.replace('%theme%', event.locals.theme) + }); return res; }) satisfies Handle; diff --git a/web/src/routes/+layout.server.ts b/web/src/routes/+layout.server.ts new file mode 100644 index 0000000..98c7b77 --- /dev/null +++ b/web/src/routes/+layout.server.ts @@ -0,0 +1,5 @@ +import type { LayoutServerLoad } from './$types'; + +export const load = (async ({ locals }) => { + return { theme: locals.theme }; +}) satisfies LayoutServerLoad; diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index c1d879e..b9c6d09 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -2,9 +2,26 @@ import 'bootstrap/dist/css/bootstrap.min.css'; import '$lib/styles/global.css'; import { onMount } from 'svelte'; + import type { LayoutData } from './$types'; + import { theme } from './stores'; + import { browser } from '$app/environment'; + import Cookies from 'js-cookie'; + import 'bootstrap-icons/font/bootstrap-icons.min.css'; + onMount(async () => { await import('bootstrap'); }); + + export let data: LayoutData; + + $theme = data.theme; + + if (browser) { + theme.subscribe((value) => { + document.getElementById('html-element')?.setAttribute('data-bs-theme', value); + Cookies.set('theme', value, { sameSite: 'strict' }); + }); + } diff --git a/web/src/routes/admin/+layout.svelte b/web/src/routes/admin/+layout.svelte index 8ab4ebc..bf6d7ee 100644 --- a/web/src/routes/admin/+layout.svelte +++ b/web/src/routes/admin/+layout.svelte @@ -1,29 +1,65 @@ -
- -
-
+ -
+ + diff --git a/web/src/routes/stores.ts b/web/src/routes/stores.ts new file mode 100644 index 0000000..03aceab --- /dev/null +++ b/web/src/routes/stores.ts @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const theme = writable<'light' | 'dark'>('dark');