add a bunch of stuff.
This commit is contained in:
Generated
+187
-2
@@ -17,6 +17,7 @@
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-svelte3": "^3.2.1",
|
||||
"fa-svelte": "^3.1.0",
|
||||
"mysql2": "^2.3.3",
|
||||
"node-sass": "^7.0.1",
|
||||
"sass": "^1.49.9",
|
||||
"svelte": "^3.44.0",
|
||||
@@ -1225,6 +1226,15 @@
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
|
||||
"integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
@@ -2176,6 +2186,15 @@
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
@@ -2467,7 +2486,6 @@
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
@@ -2636,6 +2654,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
@@ -2803,6 +2827,12 @@
|
||||
"integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
@@ -3102,6 +3132,53 @@
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mysql2": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz",
|
||||
"integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"denque": "^2.0.1",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"long": "^4.0.0",
|
||||
"lru-cache": "^6.0.0",
|
||||
"named-placeholders": "^1.1.2",
|
||||
"seq-queue": "^0.0.5",
|
||||
"sqlstring": "^2.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/named-placeholders": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz",
|
||||
"integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^4.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/named-placeholders/node_modules/lru-cache": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/named-placeholders/node_modules/yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||
@@ -3540,6 +3617,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
@@ -3991,6 +4074,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
@@ -4165,6 +4254,15 @@
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sqlstring": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/sshpk": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
|
||||
@@ -5747,6 +5845,12 @@
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
|
||||
"dev": true
|
||||
},
|
||||
"denque": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
|
||||
"integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==",
|
||||
"dev": true
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
@@ -6386,6 +6490,15 @@
|
||||
"globule": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
@@ -6611,7 +6724,6 @@
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
}
|
||||
@@ -6741,6 +6853,12 @@
|
||||
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
|
||||
"dev": true
|
||||
},
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
|
||||
"dev": true
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
@@ -6890,6 +7008,12 @@
|
||||
"integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
|
||||
"dev": true
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==",
|
||||
"dev": true
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
@@ -7117,6 +7241,49 @@
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz",
|
||||
"integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"denque": "^2.0.1",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"long": "^4.0.0",
|
||||
"lru-cache": "^6.0.0",
|
||||
"named-placeholders": "^1.1.2",
|
||||
"seq-queue": "^0.0.5",
|
||||
"sqlstring": "^2.3.2"
|
||||
}
|
||||
},
|
||||
"named-placeholders": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz",
|
||||
"integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||
@@ -7444,6 +7611,12 @@
|
||||
"retry": "^0.12.0"
|
||||
}
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
|
||||
"dev": true
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
@@ -7755,6 +7928,12 @@
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=",
|
||||
"dev": true
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
@@ -7894,6 +8073,12 @@
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
},
|
||||
"sqlstring": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-svelte3": "^3.2.1",
|
||||
"fa-svelte": "^3.1.0",
|
||||
"mysql2": "^2.3.3",
|
||||
"node-sass": "^7.0.1",
|
||||
"sass": "^1.49.9",
|
||||
"svelte": "^3.44.0",
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE scope (
|
||||
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`abbreviation` CHAR(8) NOT NULL
|
||||
)
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS scope;
|
||||
-- +goose StatementEnd
|
||||
@@ -0,0 +1,17 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE scope_member (
|
||||
`scope_id` INT NOT NULL,
|
||||
`user_id` CHAR(36) NOT NULL,
|
||||
`name` VARCHAR(63) NOT NULL,
|
||||
`owner` BOOLEAN NOT NULL,
|
||||
|
||||
PRIMARY KEY (`scope_id`, `user_id`),
|
||||
UNIQUE (`scope_id`, `name`)
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS scope_member;
|
||||
-- +goose StatementEnd
|
||||
Vendored
+7
@@ -1,11 +1,18 @@
|
||||
/// <reference types="@sveltejs/kit" />
|
||||
|
||||
import type { ScopeEntry } from "$lib/models/scope";
|
||||
import type Scope from "$lib/models/scope";
|
||||
import type User from "$lib/models/user";
|
||||
|
||||
// See https://kit.svelte.dev/docs/types#the-app-namespace
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
declare namespace App {
|
||||
interface Locals {
|
||||
user: User,
|
||||
scopes: ScopeEntry[],
|
||||
}
|
||||
|
||||
// interface Platform {}
|
||||
// interface Session {}
|
||||
interface Stuff {
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style>
|
||||
body {
|
||||
background-color: hsl(240, 12%, 7%);
|
||||
background-color: hsl(240, 12%, 5%);
|
||||
color: #aaa;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import config from "$lib/config";
|
||||
import type { Handle } from "@sveltejs/kit";
|
||||
|
||||
export const handle: Handle = async({ event, resolve }) => {
|
||||
if (process.env.STUFFLOG3_USE_DUMMY_USER === "true") {
|
||||
event.locals.user = {
|
||||
id: "c11230be-4912-4313-83b0-410a248b5bd1",
|
||||
name: "Developer",
|
||||
}
|
||||
} else {
|
||||
event.locals.user = {id: "", name: "Guest"};
|
||||
|
||||
// Actual login check.
|
||||
}
|
||||
|
||||
if (event.locals.user.id !== "") {
|
||||
const db = await config.database();
|
||||
event.locals.scopes = await db.withUser(event.locals.user.id).scopes().list()
|
||||
} else {
|
||||
event.locals.scopes = [];
|
||||
}
|
||||
|
||||
const response = await resolve(event);
|
||||
return response;
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
$color-entry0: hsl(240, 5%, 7%)
|
||||
$color-entry0-transparent: hsla(240, 5%, 10%, 0.7)
|
||||
$color-entry1: hsl(240, 5%, 14%)
|
||||
$color-entry1-transparent: hsla(240, 5%, 17%, 0.8)
|
||||
$color-entry2: hsl(240, 5%, 21%)
|
||||
$color-entry2-transparent: hsla(240, 5%, 24%, 0.8)
|
||||
$color-entry3: hsl(240, 5%, 28%)
|
||||
$color-entry4: hsl(240, 5%, 35%)
|
||||
$color-entry5: hsl(240, 5%, 42%)
|
||||
@@ -15,6 +18,7 @@ $color-entry13: hsl(240, 5%, 98%)
|
||||
|
||||
$opacity-entry4: 0.40
|
||||
$opacity-entry5: 0.60
|
||||
$opacity-entry6: 0.80
|
||||
|
||||
$color-green: hsl(120, 50%, 74%)
|
||||
$color-green-dark: hsl(120, 50%, 35%)
|
||||
@@ -9,7 +9,7 @@
|
||||
import EntryProgress from "../layout/EntryProgress.svelte";
|
||||
import EntryProgressRow from "../layout/EntryProgressRow.svelte";
|
||||
import EntryStatusIcon from "../layout/EntryStatusIcon.svelte";
|
||||
import EntryStatusLine from "../layout/EntryStatusLine.svelte";
|
||||
import EntryStatusLine from "../layout/EntryStatusLine.svelte";
|
||||
import Icon from "../layout/Icon.svelte";
|
||||
|
||||
export let requirement: StandaloneRequirement
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte";
|
||||
|
||||
export let initialOrientation: "portrait" | "landscape" = "portrait";
|
||||
export let src = "/background.jpg";
|
||||
export let opacity = 1.0;
|
||||
|
||||
let landscape = (initialOrientation === "landscape");
|
||||
let image: HTMLImageElement;
|
||||
|
||||
onMount(() => {
|
||||
if (image.complete && typeof(image.naturalHeight) !== 'undefined' && image.naturalHeight !== 0) {
|
||||
const width = image.naturalWidth;
|
||||
const height = image.naturalHeight;
|
||||
|
||||
landscape = (width > (height * 1.50));
|
||||
} else {
|
||||
image.onload = () => {
|
||||
const width = image.naturalWidth;
|
||||
const height = image.naturalHeight;
|
||||
|
||||
landscape = (width > (height * 1.50));
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<img
|
||||
bind:this={image}
|
||||
class:landscape
|
||||
src={src}
|
||||
style={`opacity: ${opacity};`}
|
||||
alt="Background"
|
||||
/>
|
||||
|
||||
<style>
|
||||
|
||||
img {
|
||||
/* Set rules to fill background */
|
||||
width: 100%;
|
||||
/* Set up proportionate scaling */
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
/* Set up positioning */
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
|
||||
transition: 250ms;
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
img.landscape {
|
||||
/* Set rules to fill background */
|
||||
height: 100%;
|
||||
/* Set up proportionate scaling */
|
||||
min-width: 100%;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -9,15 +9,16 @@
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: $color-entry9;
|
||||
background-color: $color-entry1;
|
||||
background-color: $color-entry1-transparent;
|
||||
border-bottom-right-radius: 0.75em;
|
||||
margin: 0.5em 0;
|
||||
padding: 0.25em 0.5ch;
|
||||
transition: 250ms;
|
||||
overflow-y: hidden;
|
||||
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
div.entry:hover {
|
||||
background-color: $color-entry2;
|
||||
background-color: $color-entry2-transparent;
|
||||
color: $color-entry11;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +1,16 @@
|
||||
<script lang="ts">
|
||||
import type Status from "$lib/models/status";
|
||||
import type { IconName } from "./Icon.svelte";
|
||||
import Icon from "./Icon.svelte";
|
||||
import StatusColor from "./StatusColor.svelte";
|
||||
import StatusIcon from "./StatusIcon.svelte";
|
||||
import StatusText from "./StatusText.svelte";
|
||||
|
||||
export let status: Status
|
||||
|
||||
let statusText: string = "Unknown";
|
||||
let statusIcon: IconName = "question";
|
||||
|
||||
$: switch (status) {
|
||||
case 0:
|
||||
statusIcon = "hourglass";
|
||||
statusText = "Blocked";
|
||||
break;
|
||||
case 1:
|
||||
statusIcon = "lightbulb";
|
||||
statusText = "Available";
|
||||
break;
|
||||
case 2:
|
||||
statusIcon = "calendar";
|
||||
statusText = "Background";
|
||||
break;
|
||||
case 3:
|
||||
statusIcon = "spinner";
|
||||
statusText = "Active";
|
||||
break;
|
||||
case 4:
|
||||
statusIcon = "check";
|
||||
statusText = "Completed";
|
||||
break;
|
||||
case 5:
|
||||
statusIcon = "times";
|
||||
statusText = "Failed";
|
||||
break;
|
||||
case 6:
|
||||
statusIcon = "times";
|
||||
statusText = "Dropped";
|
||||
break;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="entry-status">
|
||||
<StatusColor status={status}>
|
||||
<Icon name={statusIcon} />
|
||||
<span>{statusText}</span>
|
||||
<StatusIcon status={status} />
|
||||
<StatusText status={status} />
|
||||
</StatusColor>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
export let subtitle: string = "";
|
||||
export let fullwidth: boolean = false;
|
||||
</script>
|
||||
|
||||
<div class="header-wrapper" class:fullwidth>
|
||||
<h1><slot></slot></h1>
|
||||
<h2>{subtitle}</h2>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
div.header-wrapper {
|
||||
&.fullwidth {
|
||||
width: 180ch;
|
||||
max-width: 95%;
|
||||
margin: auto;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0.333em 0;
|
||||
margin-bottom: 0;
|
||||
font-size: 3em;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1em;
|
||||
margin: 1em 0;
|
||||
margin-top: 0;
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -38,6 +38,8 @@
|
||||
import { faThumbtack } from "@fortawesome/free-solid-svg-icons/faThumbtack";
|
||||
import { faHistory } from "@fortawesome/free-solid-svg-icons/faHistory";
|
||||
import { faLightbulb } from "@fortawesome/free-solid-svg-icons/faLightbulb";
|
||||
import { faChevronRight } from "@fortawesome/free-solid-svg-icons/faChevronRight";
|
||||
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
|
||||
|
||||
const icons = {
|
||||
"clock": faClock,
|
||||
@@ -58,6 +60,8 @@
|
||||
"calendar": faCalendar,
|
||||
"expand": faExpand,
|
||||
"search": faSearch,
|
||||
"chevron_right": faChevronRight,
|
||||
"chevron_down": faChevronDown,
|
||||
};
|
||||
|
||||
export type IconName = keyof typeof icons;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<script lang="ts">
|
||||
import type Status from "$lib/models/status";
|
||||
import type { IconName } from "./Icon.svelte";
|
||||
import Icon from "./Icon.svelte";
|
||||
import StatusColor from "./StatusColor.svelte";
|
||||
import StatusIcon from "./StatusIcon.svelte";
|
||||
import StatusText from "./StatusText.svelte";
|
||||
|
||||
export let status: Status | null = null;
|
||||
export let expanded: boolean | null = null;
|
||||
export let title: string = "";
|
||||
|
||||
let expandIcon: IconName;
|
||||
|
||||
function onClick() {
|
||||
if (expanded !== null) {
|
||||
expanded = !expanded;
|
||||
}
|
||||
}
|
||||
|
||||
$: expandIcon = expanded ? "chevron_down" : "chevron_right";
|
||||
</script>
|
||||
|
||||
<div class="category">
|
||||
<div on:click={onClick} class="category-header">
|
||||
{#if expanded !== null}
|
||||
<Icon name={expandIcon} />
|
||||
{/if}
|
||||
{#if status !== null}
|
||||
<StatusColor status={status}>
|
||||
<StatusIcon status={status} />
|
||||
<StatusText status={status} />
|
||||
</StatusColor>
|
||||
{:else}
|
||||
<span>{title}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{#if expanded !== false}
|
||||
<div class="category-body">
|
||||
<slot></slot>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../colors.sass";
|
||||
|
||||
div.category {
|
||||
border-left: 3px solid $color-entry1;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div.category-body {
|
||||
margin-top: 0.1em;
|
||||
}
|
||||
|
||||
div.category-header {
|
||||
padding-left: 0.5ch;
|
||||
font-weight: 600;
|
||||
user-select: none;
|
||||
opacity: $opacity-entry4;
|
||||
|
||||
:global(.icon) {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,77 @@
|
||||
<script lang="ts">
|
||||
import { page } from "$app/stores";
|
||||
|
||||
export let href: string = "";
|
||||
export let subtitle: string = "";
|
||||
|
||||
let selected: boolean;
|
||||
$: selected = $page.url.pathname === href;
|
||||
</script>
|
||||
|
||||
{#if !!href}
|
||||
<a href={href}>
|
||||
<div on:click class="menu-item" class:selected>
|
||||
<div class="subtitle">{subtitle}</div>
|
||||
<div><slot></slot></div>
|
||||
</div>
|
||||
</a>
|
||||
{:else}
|
||||
<div on:click class="menu-item" class:selected>
|
||||
<div class="subtitle">{subtitle}</div>
|
||||
<div><slot></slot></div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
@import "../colors.sass";
|
||||
|
||||
div.menu-item {
|
||||
color: $color-entry9;
|
||||
font-size: 0.8em;
|
||||
padding: 0.15em 0;
|
||||
padding-left: 0.5ch;
|
||||
|
||||
transition: 0.25s;
|
||||
|
||||
&.selected {
|
||||
color: $color-entry13;
|
||||
background-color: $color-entry0-transparent;
|
||||
}
|
||||
|
||||
> div {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
> div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
> div.subtitle {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
div.subtitle {
|
||||
color: $color-entry5;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $color-entry13;
|
||||
background-color: $color-entry1-transparent;
|
||||
|
||||
div.subtitle {
|
||||
color: $color-entry8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import type Status from "$lib/models/status";
|
||||
import Icon, { type IconName } from "./Icon.svelte";
|
||||
|
||||
export let status: Status;
|
||||
export let block: boolean = false;
|
||||
</script>
|
||||
|
||||
<Icon block={block} name={STATUS_ICONS[status]} />
|
||||
|
||||
<script lang="ts" context="module">
|
||||
const STATUS_ICONS: Record<Status, IconName> = {
|
||||
0: "hourglass",
|
||||
1: "lightbulb",
|
||||
2: "calendar",
|
||||
3: "spinner",
|
||||
4: "check",
|
||||
5: "times",
|
||||
6: "times",
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,19 @@
|
||||
<script lang="ts">
|
||||
import type Status from "$lib/models/status";
|
||||
|
||||
export let status: Status;
|
||||
</script>
|
||||
|
||||
<span>{STATUS_NAMES[status]}</span>
|
||||
|
||||
<script lang="ts" context="module">
|
||||
const STATUS_NAMES: Record<Status, string> = {
|
||||
0: "Blocked",
|
||||
1: "Available",
|
||||
2: "Background",
|
||||
3: "Active",
|
||||
4: "Completed",
|
||||
5: "Failed",
|
||||
6: "Dropped",
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { Database } from "./database/interfaces";
|
||||
import MysqlDB from "./database/mysql/database";
|
||||
|
||||
let databasePromise: Promise<Database> | null = null;
|
||||
let databaseTime: number = 0;
|
||||
|
||||
const config = {
|
||||
database() {
|
||||
if (databasePromise == null || Date.now() < (databaseTime - 60000)) {
|
||||
databasePromise = MysqlDB.connectEnv();
|
||||
databaseTime = Date.now();
|
||||
}
|
||||
|
||||
return databasePromise;
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { ScopeEntry, ScopeInput } from "$lib/models/scope";
|
||||
import type Scope from "$lib/models/scope";
|
||||
import type { StatEntry } from "$lib/models/stat";
|
||||
import type Stat from "$lib/models/stat";
|
||||
|
||||
export interface Database {
|
||||
userId: string
|
||||
|
||||
scopes(): ScopeRepo
|
||||
stats(scopeId: number): StatRepo
|
||||
withUser(userId: string): Database
|
||||
}
|
||||
|
||||
export interface ScopeRepo {
|
||||
userId: string
|
||||
|
||||
find(id: number): Promise<Scope>
|
||||
list(): Promise<ScopeEntry[]>
|
||||
create(input: ScopeInput): Promise<Scope>
|
||||
update(id: number, input: Partial<ScopeInput>): Promise<Scope>
|
||||
delete(id: number): Promise<void>
|
||||
}
|
||||
|
||||
export interface StatRepo {
|
||||
userId: string
|
||||
scopeId: number
|
||||
|
||||
find(id: number): Promise<Stat>
|
||||
findEntries(...ids: number[]): Promise<StatEntry[]>
|
||||
list(): Promise<Stat[]>
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import {createPool} from "mysql2/promise"
|
||||
import type {Pool} from "mysql2/promise";
|
||||
|
||||
import type { Database, ScopeRepo, StatRepo } from "../interfaces";
|
||||
import MysqlDBScopes from "./scopes";
|
||||
|
||||
|
||||
export default class MysqlDB implements Database {
|
||||
connection: Pool
|
||||
userId: string;
|
||||
|
||||
private constructor(userId: string, connection: Connection) {
|
||||
this.userId = userId;
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
scopes(): ScopeRepo {
|
||||
return new MysqlDBScopes(this.connection, this.userId);
|
||||
}
|
||||
stats(scopeId: number): StatRepo {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
withUser(userId: string): Database {
|
||||
return new MysqlDB(userId, this.connection);
|
||||
}
|
||||
|
||||
static async connectEnv(): Promise<MysqlDB> {
|
||||
return this.connect(
|
||||
process.env.STUFFLOG3_MYSQL_HOST,
|
||||
parseInt(process.env.STUFFLOG3_MYSQL_PORT),
|
||||
process.env.STUFFLOG3_MYSQL_USERNAME,
|
||||
process.env.STUFFLOG3_MYSQL_PASSWORD,
|
||||
process.env.STUFFLOG3_MYSQL_SCHEMA,
|
||||
)
|
||||
}
|
||||
|
||||
static async connect(host: string, port: number, user: string, password: string, database: string): Promise<MysqlDB> {
|
||||
const connection = await createPool({
|
||||
host, user, database, password, port,
|
||||
waitForConnections: true,
|
||||
connectionLimit: 20,
|
||||
queueLimit: 0,
|
||||
});
|
||||
|
||||
return new MysqlDB("", connection);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import type {Pool} from "mysql2/promise";
|
||||
|
||||
import type scope from "$lib/models/scope";
|
||||
import type { ScopeEntry, ScopeInput } from "$lib/models/scope";
|
||||
import type { ScopeRepo } from "../interfaces";
|
||||
|
||||
export default class MysqlDBScopes implements ScopeRepo {
|
||||
userId: string;
|
||||
connection: Pool;
|
||||
|
||||
constructor(connection: Pool, userId: string) {
|
||||
this.connection = connection;
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
find(id: number): Promise<scope> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
async list(): Promise<ScopeEntry[]> {
|
||||
const [rows] = await this.connection.execute(`
|
||||
SELECT scope.*, scope_member.name as display_name
|
||||
FROM scope
|
||||
INNER JOIN scope_member ON id = scope_id
|
||||
WHERE user_id = ?
|
||||
`, [this.userId]);
|
||||
|
||||
return (rows as any[]).map(r => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
abbreviation: r.abbreviation,
|
||||
displayName: r.display_name,
|
||||
}))
|
||||
}
|
||||
create(input: ScopeInput): Promise<scope> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
update(id: number, input: Partial<ScopeInput>): Promise<scope> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
delete(id: number): Promise<void> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,16 @@ export interface ScopeEntry {
|
||||
id: number
|
||||
name: string
|
||||
abbreviation: string
|
||||
displayName: string
|
||||
}
|
||||
|
||||
export interface ScopeInput {
|
||||
name: string
|
||||
abbreviation: string
|
||||
displayName: string
|
||||
}
|
||||
|
||||
export interface ScopeMember {
|
||||
name: string
|
||||
owner: boolean
|
||||
}
|
||||
@@ -8,6 +8,22 @@ enum Status {
|
||||
Dropped = 6,
|
||||
}
|
||||
|
||||
|
||||
export interface LabeledStatus {
|
||||
value: Status
|
||||
name: string
|
||||
}
|
||||
|
||||
export const allStatuses: LabeledStatus[] = [
|
||||
{value: Status.Active, name: "Active"},
|
||||
{value: Status.Background, name: "Background"},
|
||||
{value: Status.Available, name: "Available"},
|
||||
{value: Status.Blocked, name: "Blocked"},
|
||||
{value: Status.Completed, name: "Completed"},
|
||||
{value: Status.Failed, name: "Failed"},
|
||||
{value: Status.Dropped, name: "Dropped"},
|
||||
];
|
||||
|
||||
// Blocked -> Available -> Active -> Completed
|
||||
// -> Failed
|
||||
// -> Dropped
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export default interface User {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export const get: RequestHandler = async({params}) => {
|
||||
|
||||
const scopes: Scope[] = [
|
||||
{
|
||||
id: 1, name: "3D Modeling", abbreviation: "3D",
|
||||
id: 1, name: "3D Modeling", abbreviation: "3D", displayName: "Test",
|
||||
stats: [
|
||||
{id: 101, name: "Asset", weight: 0.1, description: "Some description"},
|
||||
{id: 102, name: "Tweak", weight: 0.2, description: "Some description"},
|
||||
@@ -55,7 +55,7 @@ const scopes: Scope[] = [
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2, name: "Roleplay", abbreviation: "RP",
|
||||
id: 2, name: "Roleplay", abbreviation: "RP", displayName: "Test",
|
||||
stats: [
|
||||
{id: 201, name: "Story", weight: 3, description: "Some description"},
|
||||
{id: 202, name: "Story Word", weight: 0.002, description: "Some description"},
|
||||
@@ -67,9 +67,14 @@ const scopes: Scope[] = [
|
||||
{id: 208, name: "Wiki Complexity", weight: 0.5, description: "Some description"},
|
||||
],
|
||||
activeProjects: [
|
||||
{id: 2001, name: "Ilyna T'Rea", status: Status.Active},
|
||||
{id: 2002, name: "Renala T'Iavay", status: Status.Active},
|
||||
{id: 2003, name: "Background Stories", status: Status.Background},
|
||||
{id: 2001, name: "Ilyna: The Morning After", status: Status.Active},
|
||||
{id: 2002, name: "Renala: Finding Her Voice", status: Status.Active},
|
||||
{id: 2003, name: "General Stories", status: Status.Background},
|
||||
{id: 2004, name: "Uvena: Finish Wiki Page", status: Status.Active},
|
||||
{id: 2005, name: "Va'ynna: Cracking at the Seams", status: Status.Active},
|
||||
{id: 2006, name: "Witch Hunt: Sala's Backlog", status: Status.Active},
|
||||
{id: 2007, name: "Ilyna: Complete Wiki Page", status: Status.Completed},
|
||||
{id: 2008, name: "Renala: Complete Wiki Page", status: Status.Active},
|
||||
]
|
||||
},
|
||||
//{id: 3, name: "Minecraft", abbreviation: "MC"},
|
||||
|
||||
@@ -19,14 +19,92 @@
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const STATUS_ORDER = [
|
||||
Status.Active,
|
||||
Status.Background,
|
||||
Status.Available,
|
||||
Status.Blocked,
|
||||
Status.Completed,
|
||||
Status.Failed,
|
||||
Status.Dropped,
|
||||
]
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import type Scope from "$lib/models/scope";
|
||||
import Header from "$lib/components/layout/Header.svelte";
|
||||
import Status from "$lib/models/status";
|
||||
import MenuCategory from "$lib/components/layout/MenuCategory.svelte";
|
||||
import type { ProjectEntry } from "$lib/models/project";
|
||||
import MenuItem from "$lib/components/layout/MenuItem.svelte";
|
||||
|
||||
export let scope: Scope;
|
||||
|
||||
let projects = scope.activeProjects;
|
||||
let projectsByStatus: Record<Status, ProjectEntry[]>;
|
||||
|
||||
$: projectsByStatus = projects.reduce((p, c) => ({...p, [c.status]: [...p[c.status], c]}), {
|
||||
0: [], 1: [], 2: [], 3: [], 4: [], 5: [], 6: [],
|
||||
})
|
||||
</script>
|
||||
|
||||
<h1>{scope.name}</h1>
|
||||
<div class="scope-layout">
|
||||
<div class="column main">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="column side">
|
||||
<Header subtitle={scope.name}>{scope.abbreviation}</Header>
|
||||
<MenuCategory title="Scope">
|
||||
<MenuItem href="/{scope.id}">Overview</MenuItem>
|
||||
<MenuItem href="/{scope.id}/history">History</MenuItem>
|
||||
</MenuCategory>
|
||||
{#each STATUS_ORDER as status (status)}
|
||||
{#if projectsByStatus[status].length > 0}
|
||||
<MenuCategory status={status}>
|
||||
{#each projectsByStatus[status] as project (project.id)}
|
||||
<MenuItem href="/{scope.id}/project/{project.id}" subtitle={
|
||||
project.name.includes(": ") ? project.name.split(": ")[0] + ": " : ""
|
||||
}>{
|
||||
project.name.includes(": ") ? project.name.split(": ").slice(1).join(": ") : project.name
|
||||
}</MenuItem>
|
||||
{/each}
|
||||
</MenuCategory>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<slot></slot>
|
||||
<style lang="scss">
|
||||
div.scope-layout {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
flex-basis: 100%;
|
||||
flex: 1;
|
||||
|
||||
width: 90ch;
|
||||
max-width: 95%;
|
||||
margin: auto;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
> div.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 5;
|
||||
|
||||
&.side {
|
||||
flex: 2;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
margin-top: 1em;
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" context="module">
|
||||
import type { Load, LoadInput } from "@sveltejs/kit/types/internal";
|
||||
import type { Load } from "@sveltejs/kit/types/internal";
|
||||
|
||||
export const load: Load = async({ stuff }) => {
|
||||
return {
|
||||
@@ -17,4 +17,8 @@
|
||||
export let scope: Scope;
|
||||
</script>
|
||||
|
||||
<h1>{$page.stuff.scope.name}</h1>
|
||||
<h1>{$page.stuff.scope.name}</h1>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,10 @@
|
||||
<script>
|
||||
import { page } from "$app/stores";
|
||||
import Backgrond from "$lib/components/layout/Backgrond.svelte";
|
||||
|
||||
let opacity = 0.175;
|
||||
|
||||
$: opacity = $page.url.pathname === "/" ? 0.3 : 0.2;
|
||||
</script>
|
||||
<Backgrond initialOrientation="landscape" opacity={opacity} />
|
||||
<slot></slot>
|
||||
+2
-28
@@ -17,7 +17,6 @@
|
||||
error: `Failed: ${res.status}`
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -29,17 +28,14 @@
|
||||
import type { StandaloneRequirement } from "$lib/models/project";
|
||||
import type { StandaloneSprint } from "$lib/models/sprint";
|
||||
import SprintLink from "$lib/components/frontpage/SprintLink.svelte";
|
||||
|
||||
import Header from "$lib/components/layout/Header.svelte";
|
||||
export let scopes: ScopeEntry[] = [];
|
||||
export let items: StandaloneItem[] = [];
|
||||
export let requirements: StandaloneRequirement[] = [];
|
||||
export let sprints: StandaloneSprint[] = [];
|
||||
</script>
|
||||
|
||||
<div class="header-wrapper">
|
||||
<h1>Stufflog</h1>
|
||||
<h2>Logging your stuff.</h2>
|
||||
</div>
|
||||
<Header fullwidth subtitle="Logging your stuff">Stufflog</Header>
|
||||
|
||||
<main>
|
||||
<div class="column">
|
||||
@@ -76,28 +72,6 @@
|
||||
</main>
|
||||
|
||||
<style lang="scss">
|
||||
div.header-wrapper {
|
||||
width: 180ch;
|
||||
max-width: 95%;
|
||||
margin: auto;
|
||||
margin-top: 2em;
|
||||
|
||||
h1 {
|
||||
margin: 0.333em 0.333ch;
|
||||
margin-bottom: 0;
|
||||
font-size: 3em;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1em;
|
||||
margin: 1em 1ch;
|
||||
margin-top: 0;
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
@@ -6,14 +6,8 @@ import type { ScopeEntry } from "$lib/models/scope"
|
||||
import Status from "$lib/models/status"
|
||||
import type { StandaloneSprint } from "$lib/models/sprint"
|
||||
|
||||
export const get: RequestHandler = async({}) => {
|
||||
const scopes: ScopeEntry[] = [
|
||||
{id: 1, name: "3D Modeling", abbreviation: "3D"},
|
||||
{id: 2, name: "Roleplay", abbreviation: "RP"},
|
||||
{id: 3, name: "Minecraft", abbreviation: "MC"},
|
||||
{id: 4, name: "Coding", abbreviation: "CODE"},
|
||||
{id: 5, name: "System Administration", abbreviation: "SA"},
|
||||
]
|
||||
export const get: RequestHandler = async({locals}) => {
|
||||
const scopes: ScopeEntry[] = locals.scopes;
|
||||
|
||||
const items: StandaloneItem[] = [
|
||||
{
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 495 KiB |
Reference in New Issue
Block a user