Gisle Aune
3 years ago
commit
f75f342a31
31 changed files with 9557 additions and 0 deletions
-
20.eslintrc.cjs
-
8.gitignore
-
1.npmrc
-
40README.md
-
8304package-lock.json
-
29package.json
-
10src/app.d.ts
-
22src/app.html
-
40src/lib/components/frontpage/ItemLink.svelte
-
34src/lib/components/frontpage/RequirementLink.svelte
-
20src/lib/components/frontpage/ScopeLink.svelte
-
121src/lib/components/frontpage/SprintLink.svelte
-
34src/lib/components/layout/Entry.svelte
-
40src/lib/components/layout/EntryAmounts.svelte
-
14src/lib/components/layout/EntryDescription.svelte
-
28src/lib/components/layout/EntryName.svelte
-
200src/lib/components/layout/EntryProgress.svelte
-
16src/lib/components/layout/EntryProgressRow.svelte
-
16src/lib/models/item.ts
-
36src/lib/models/project.ts
-
11src/lib/models/scope.ts
-
24src/lib/models/sprint.ts
-
52src/lib/models/stat.ts
-
25src/lib/models/status.ts
-
15src/lib/stores/currentTime.ts
-
10src/lib/utils/aggregate.ts
-
146src/routes/index.svelte
-
190src/routes/indexdata.json.ts
-
BINstatic/favicon.png
-
15svelte.config.js
-
36tsconfig.json
@ -0,0 +1,20 @@ |
|||||
|
module.exports = { |
||||
|
root: true, |
||||
|
parser: '@typescript-eslint/parser', |
||||
|
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], |
||||
|
plugins: ['svelte3', '@typescript-eslint'], |
||||
|
ignorePatterns: ['*.cjs'], |
||||
|
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], |
||||
|
settings: { |
||||
|
'svelte3/typescript': () => require('typescript') |
||||
|
}, |
||||
|
parserOptions: { |
||||
|
sourceType: 'module', |
||||
|
ecmaVersion: 2020 |
||||
|
}, |
||||
|
env: { |
||||
|
browser: true, |
||||
|
es2017: true, |
||||
|
node: true |
||||
|
} |
||||
|
}; |
@ -0,0 +1,8 @@ |
|||||
|
.DS_Store |
||||
|
node_modules |
||||
|
/build |
||||
|
/.svelte-kit |
||||
|
/package |
||||
|
.env |
||||
|
.env.* |
||||
|
!.env.example |
@ -0,0 +1 @@ |
|||||
|
engine-strict=true |
@ -0,0 +1,40 @@ |
|||||
|
# create-svelte |
||||
|
|
||||
|
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). |
||||
|
|
||||
|
## Creating a project |
||||
|
|
||||
|
If you're seeing this, you've probably already done this step. Congrats! |
||||
|
|
||||
|
```bash |
||||
|
# create a new project in the current directory |
||||
|
npm init svelte@next |
||||
|
|
||||
|
# create a new project in my-app |
||||
|
npm init svelte@next my-app |
||||
|
``` |
||||
|
|
||||
|
> Note: the `@next` is temporary |
||||
|
|
||||
|
## Developing |
||||
|
|
||||
|
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: |
||||
|
|
||||
|
```bash |
||||
|
npm run dev |
||||
|
|
||||
|
# or start the server and open the app in a new browser tab |
||||
|
npm run dev -- --open |
||||
|
``` |
||||
|
|
||||
|
## Building |
||||
|
|
||||
|
To create a production version of your app: |
||||
|
|
||||
|
```bash |
||||
|
npm run build |
||||
|
``` |
||||
|
|
||||
|
You can preview the production build with `npm run preview`. |
||||
|
|
||||
|
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. |
8304
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,29 @@ |
|||||
|
{ |
||||
|
"name": "stufflog3", |
||||
|
"version": "0.0.1", |
||||
|
"scripts": { |
||||
|
"dev": "svelte-kit dev", |
||||
|
"build": "svelte-kit build", |
||||
|
"package": "svelte-kit package", |
||||
|
"preview": "svelte-kit preview", |
||||
|
"check": "svelte-check --tsconfig ./tsconfig.json", |
||||
|
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", |
||||
|
"lint": "eslint --ignore-path .gitignore ." |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"@sveltejs/adapter-auto": "next", |
||||
|
"@sveltejs/kit": "next", |
||||
|
"@typescript-eslint/eslint-plugin": "^5.10.1", |
||||
|
"@typescript-eslint/parser": "^5.10.1", |
||||
|
"eslint": "^7.32.0", |
||||
|
"eslint-plugin-svelte3": "^3.2.1", |
||||
|
"node-sass": "^7.0.1", |
||||
|
"sass": "^1.49.9", |
||||
|
"svelte": "^3.44.0", |
||||
|
"svelte-check": "^2.2.6", |
||||
|
"svelte-preprocess": "^4.10.1", |
||||
|
"tslib": "^2.3.1", |
||||
|
"typescript": "~4.5.4" |
||||
|
}, |
||||
|
"type": "module" |
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
/// <reference types="@sveltejs/kit" />
|
||||
|
|
||||
|
// See https://kit.svelte.dev/docs/types#the-app-namespace
|
||||
|
// for information about these interfaces
|
||||
|
declare namespace App { |
||||
|
// interface Locals {}
|
||||
|
// interface Platform {}
|
||||
|
// interface Session {}
|
||||
|
// interface Stuff {}
|
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
<head> |
||||
|
<meta charset="utf-8" /> |
||||
|
<meta name="description" content="" /> |
||||
|
<link rel="icon" href="%svelte.assets%/favicon.png" /> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
||||
|
<style> |
||||
|
body { |
||||
|
background-color: #141415; |
||||
|
color: #aaa; |
||||
|
padding: 0; |
||||
|
margin: 0; |
||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; |
||||
|
} |
||||
|
</style> |
||||
|
%svelte.head% |
||||
|
</head> |
||||
|
<body> |
||||
|
<div id="root">%svelte.body%</div> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,40 @@ |
|||||
|
<script lang="ts"> |
||||
|
import type { StandaloneItem } from "$lib/models/item"; |
||||
|
import Entry from "../layout/Entry.svelte"; |
||||
|
import EntryAmounts from "../layout/EntryAmounts.svelte"; |
||||
|
import EntryDescription from "../layout/EntryDescription.svelte"; |
||||
|
import EntryName from "../layout/EntryName.svelte"; |
||||
|
|
||||
|
export let item: StandaloneItem |
||||
|
export let compact: boolean = false; |
||||
|
|
||||
|
let link = ""; |
||||
|
let amounts = []; |
||||
|
let subtitle = ""; |
||||
|
|
||||
|
$: if (item.project != null) { |
||||
|
link = `/${item.scope.id}/project/${item.project.id}?focusitem=${item.id}` |
||||
|
} else { |
||||
|
link = `/${item.scope.id}/item/${item.id}` |
||||
|
} |
||||
|
|
||||
|
$: amounts = item.stats.map(s => ({amount: s.acquired || s.required, label: s.name})) |
||||
|
$: subtitle = item.project != null ? item.project.name : item.scope.abbreviation |
||||
|
</script> |
||||
|
|
||||
|
<a href={link}> |
||||
|
<Entry> |
||||
|
<EntryName subtitle={subtitle}>{item.name}</EntryName> |
||||
|
{#if !compact} |
||||
|
<EntryDescription>{item.description}</EntryDescription> |
||||
|
{/if} |
||||
|
<EntryAmounts values={amounts} /> |
||||
|
</Entry> |
||||
|
</a> |
||||
|
|
||||
|
<style> |
||||
|
a { |
||||
|
text-decoration: none; |
||||
|
color: inherit; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,34 @@ |
|||||
|
<script lang="ts"> |
||||
|
import type { StandaloneRequirement } from "$lib/models/project"; |
||||
|
|
||||
|
import Entry from "../layout/Entry.svelte"; |
||||
|
import EntryDescription from "../layout/EntryDescription.svelte"; |
||||
|
import EntryName from "../layout/EntryName.svelte"; |
||||
|
import EntryProgress from "../layout/EntryProgress.svelte"; |
||||
|
import EntryProgressRow from "../layout/EntryProgressRow.svelte"; |
||||
|
|
||||
|
export let requirement: StandaloneRequirement |
||||
|
export let compact: boolean = false; |
||||
|
export let boat: number = null; |
||||
|
</script> |
||||
|
|
||||
|
<a href="/{requirement.scope.id}/{requirement.project.id}?requirement={requirement.id}"> |
||||
|
<Entry> |
||||
|
<EntryName subtitle={requirement.project.name}>{requirement.name}</EntryName> |
||||
|
{#if !compact} |
||||
|
<EntryDescription>{requirement.description}</EntryDescription> |
||||
|
{/if} |
||||
|
<EntryProgressRow> |
||||
|
{#each requirement.stats as stat (stat.id)} |
||||
|
<EntryProgress boat={boat} name={stat.name} acquired={stat.acquired} required={stat.required} /> |
||||
|
{/each} |
||||
|
</EntryProgressRow> |
||||
|
</Entry> |
||||
|
</a> |
||||
|
|
||||
|
<style> |
||||
|
a { |
||||
|
text-decoration: none; |
||||
|
color: inherit; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,20 @@ |
|||||
|
<script lang="ts"> |
||||
|
import type { ScopeEntry } from "$lib/models/scope"; |
||||
|
import Entry from "../layout/Entry.svelte"; |
||||
|
import EntryName from "../layout/EntryName.svelte"; |
||||
|
|
||||
|
export let scope: ScopeEntry |
||||
|
</script> |
||||
|
|
||||
|
<a href="/{scope.id}/"> |
||||
|
<Entry> |
||||
|
<EntryName subtitle={scope.abbreviation}>{scope.name}</EntryName> |
||||
|
</Entry> |
||||
|
</a> |
||||
|
|
||||
|
<style> |
||||
|
a { |
||||
|
text-decoration: none; |
||||
|
color: inherit; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,121 @@ |
|||||
|
<script lang="ts"> |
||||
|
import type Sprint from "$lib/models/sprint"; |
||||
|
import type { StatAggregate, StatEntry } from "$lib/models/stat"; |
||||
|
import { calculateAggregate } from "$lib/utils/aggregate"; |
||||
|
|
||||
|
import currentTime from "$lib/stores/currentTime"; |
||||
|
|
||||
|
import Entry from "../layout/Entry.svelte"; |
||||
|
import EntryDescription from "../layout/EntryDescription.svelte"; |
||||
|
import EntryName from "../layout/EntryName.svelte"; |
||||
|
import EntryProgress from "../layout/EntryProgress.svelte"; |
||||
|
import EntryProgressRow from "../layout/EntryProgressRow.svelte"; |
||||
|
import ItemLink from "./ItemLink.svelte"; |
||||
|
import RequirementLink from "./RequirementLink.svelte"; |
||||
|
|
||||
|
export let sprint: Sprint |
||||
|
|
||||
|
let fromDate: Date; |
||||
|
let toDate: Date; |
||||
|
let boat: number; |
||||
|
let itemsAcquired: number; |
||||
|
let itemsRequired: number; |
||||
|
let aggregate: StatAggregate; |
||||
|
let reqAggregate: Record<string, StatAggregate>; |
||||
|
|
||||
|
$: { |
||||
|
fromDate = new Date(sprint.from); |
||||
|
toDate = new Date(sprint.to); |
||||
|
boat = ($currentTime.getTime() - fromDate.getTime()) / (toDate.getTime() - fromDate.getTime()); |
||||
|
boat = Math.max(0, Math.min(1, boat)); |
||||
|
} |
||||
|
|
||||
|
$: { |
||||
|
if (sprint.items != null) { |
||||
|
itemsAcquired = sprint.items.filter(i => !!i.acquireDate).length; |
||||
|
itemsRequired = sprint.items.length; |
||||
|
} else { |
||||
|
itemsAcquired = 0; |
||||
|
itemsRequired = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$: { |
||||
|
switch (sprint.kind) { |
||||
|
case "item": { |
||||
|
aggregate = calculateAggregate(sprint.items.map(i => i.stats).flat()); |
||||
|
break; |
||||
|
} |
||||
|
case "requirements": { |
||||
|
aggregate = calculateAggregate(sprint.requirements.map(r => r.stats).flat()); |
||||
|
break; |
||||
|
} |
||||
|
case "stats": { |
||||
|
aggregate = calculateAggregate(sprint.stats); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (sprint.aggregateRequired > 0) { |
||||
|
aggregate.required = sprint.aggregateRequired; |
||||
|
} |
||||
|
|
||||
|
reqAggregate = {}; |
||||
|
for (const requirement of (sprint.requirements || [])) { |
||||
|
reqAggregate[requirement.id] = calculateAggregate(requirement.stats); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<a href="/{sprint.scope.id}/sprints?sprint={sprint.id}"> |
||||
|
<Entry> |
||||
|
<EntryName subtitle="{sprint.scope.abbreviation} {sprint.kind} sprint">{sprint.name}</EntryName> |
||||
|
<EntryDescription>{sprint.description}</EntryDescription> |
||||
|
<EntryProgressRow> |
||||
|
{#if sprint.kind === "item"} |
||||
|
<EntryProgress |
||||
|
fullwidth green |
||||
|
percentage={sprint.aggregateRequired == 0} |
||||
|
name="Items" |
||||
|
acquired={itemsAcquired} |
||||
|
required={itemsRequired} |
||||
|
boat={boat} |
||||
|
/> |
||||
|
{:else} |
||||
|
<EntryProgress |
||||
|
fullwidth |
||||
|
percentage={sprint.aggregateRequired == 0} |
||||
|
name="Total" |
||||
|
acquired={aggregate.acquired} |
||||
|
required={aggregate.required} |
||||
|
boat={boat} |
||||
|
/> |
||||
|
{/if} |
||||
|
{#if !sprint.coarse} |
||||
|
{#each sprint.stats as stat (stat.id)} |
||||
|
<EntryProgress |
||||
|
name={stat.name} |
||||
|
acquired={stat.acquired} |
||||
|
required={stat.required} |
||||
|
boat={boat} |
||||
|
/> |
||||
|
{/each} |
||||
|
{/if} |
||||
|
</EntryProgressRow> |
||||
|
{#each sprint.items as item (item.id)} |
||||
|
{#if !item.acquireDate} |
||||
|
<ItemLink compact item={item} /> |
||||
|
{/if} |
||||
|
{/each} |
||||
|
{#each sprint.requirements as requirement (requirement.id)} |
||||
|
<RequirementLink compact boat={boat} requirement={requirement} /> |
||||
|
{/each} |
||||
|
</Entry> |
||||
|
</a> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
a { |
||||
|
text-decoration: none; |
||||
|
color: inherit; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,34 @@ |
|||||
|
<div class="entry"> |
||||
|
<slot></slot> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
div.entry { |
||||
|
display: block; |
||||
|
text-decoration: none; |
||||
|
color: #aaa; |
||||
|
background-color: #222; |
||||
|
border-bottom-right-radius: 0.75em; |
||||
|
margin: 0.5em 0; |
||||
|
padding: 0.25em 0.5ch; |
||||
|
transition: 250ms; |
||||
|
} |
||||
|
div.entry:hover { |
||||
|
background-color: #333; |
||||
|
color: #eee; |
||||
|
} |
||||
|
|
||||
|
:global(div.entry div.entry) { |
||||
|
margin: 0.25em 0; |
||||
|
} |
||||
|
:global(div.entry div.entry) { |
||||
|
border-bottom-right-radius: 0.5em; |
||||
|
} |
||||
|
:global(div.entry div.entry:hover) { |
||||
|
background-color: #444; |
||||
|
} |
||||
|
|
||||
|
div.entry:last-of-type { |
||||
|
margin-bottom: 0.1em; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,40 @@ |
|||||
|
<script lang="ts" context="module"> |
||||
|
export interface Amount { |
||||
|
label: string |
||||
|
amount: 0 |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
export let values: Amount[]; |
||||
|
</script> |
||||
|
|
||||
|
<div class="amounts"> |
||||
|
{#each values as value} |
||||
|
<div class="amount"> |
||||
|
<span class="value">{value.amount}×</span> |
||||
|
<span class="label">{value.label}</span> |
||||
|
</div> |
||||
|
{/each} |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
div.amounts { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
flex-wrap: wrap; |
||||
|
margin-top: 0.5em; |
||||
|
font-size: 0.75em; |
||||
|
} |
||||
|
div.amounts:empty { |
||||
|
margin-top: 0; |
||||
|
} |
||||
|
|
||||
|
div.amount { |
||||
|
padding-right: 1ch; |
||||
|
} |
||||
|
|
||||
|
span.label { |
||||
|
color: #777; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,14 @@ |
|||||
|
<script lang="ts"> |
||||
|
</script> |
||||
|
|
||||
|
<div class="description"> |
||||
|
<span><slot></slot></span> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
div.description { |
||||
|
margin-top: 0.25em; |
||||
|
font-size: 1em; |
||||
|
color: inherit; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,28 @@ |
|||||
|
<script lang="ts"> |
||||
|
export let subtitle: string = "" |
||||
|
</script> |
||||
|
|
||||
|
<div class="name"> |
||||
|
<span><slot></slot></span> |
||||
|
<span class="abbreviation">{subtitle}</span> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
div.name { |
||||
|
font-size: 1em; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
span.abbreviation { |
||||
|
font-size: 1em; |
||||
|
opacity: 0.333; |
||||
|
} |
||||
|
|
||||
|
@media screen and (max-width: 1500px) { |
||||
|
span.abbreviation { |
||||
|
display: block; |
||||
|
font-size: 0.75em; |
||||
|
margin-bottom: 0.5em; |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,200 @@ |
|||||
|
<script lang="ts" context="module"> |
||||
|
export const PROGRESS_COLORS = [ |
||||
|
"none", |
||||
|
"bronze", |
||||
|
"silver", |
||||
|
"gold", |
||||
|
] |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
export let name: string; |
||||
|
export let acquired: number; |
||||
|
export let required: number; |
||||
|
export let boat: number | null = null; |
||||
|
export let big: boolean = false; |
||||
|
export let bare: boolean = false; |
||||
|
export let fullwidth: boolean = false; |
||||
|
export let percentage: boolean = false; |
||||
|
export let green: boolean = false; |
||||
|
|
||||
|
let offClass = PROGRESS_COLORS[0]; |
||||
|
let onClass = PROGRESS_COLORS[1]; |
||||
|
let ons = 0; |
||||
|
let offs = 1; |
||||
|
let segmented = false; |
||||
|
let boatClass = "gray"; |
||||
|
let boatDone = false; |
||||
|
|
||||
|
$: { |
||||
|
if (required > 0) { |
||||
|
let level = Math.floor(acquired / required); |
||||
|
if (level >= PROGRESS_COLORS.length - 1) { |
||||
|
offs = 0; |
||||
|
ons = required; |
||||
|
offClass = "gold"; |
||||
|
onClass = "gold"; |
||||
|
} else { |
||||
|
ons = acquired - (level * required); |
||||
|
offs = required - ons; |
||||
|
console.log(name, ons, offs); |
||||
|
offClass = PROGRESS_COLORS[level]; |
||||
|
onClass = PROGRESS_COLORS[level + 1]; |
||||
|
} |
||||
|
|
||||
|
// Mark it non-segmented if the required is too high. This prevents a clunky progress bar, |
||||
|
// or a browser freeze if you set the required very high. |
||||
|
segmented = !percentage && (required <= (fullwidth ? 60 : 15)); |
||||
|
} else { |
||||
|
offClass = "none"; |
||||
|
segmented = true; |
||||
|
ons = 0; |
||||
|
offs = 1; |
||||
|
} |
||||
|
|
||||
|
if (green) { |
||||
|
onClass = "green"; |
||||
|
offClass = "none"; |
||||
|
|
||||
|
if (acquired >= required) { |
||||
|
ons = required; |
||||
|
offs = 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$: { |
||||
|
if (boat != null && required > 0) { |
||||
|
const diff = (acquired / required) - boat; |
||||
|
if (diff < -0.05) { |
||||
|
boatClass = "red"; |
||||
|
} else if (diff > 0.05) { |
||||
|
boatClass = "green"; |
||||
|
} else { |
||||
|
boatClass = "gray"; |
||||
|
} |
||||
|
|
||||
|
boatDone = acquired >= required; |
||||
|
} else { |
||||
|
boatClass = "gray"; |
||||
|
boatDone = false; |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<div class="progress" class:fullwidth> |
||||
|
<!-- Header --> |
||||
|
{#if !bare} |
||||
|
<div class="header"> |
||||
|
<span>{name}</span> |
||||
|
{#if percentage} |
||||
|
<span class="ackreq">({((acquired / required) * 100).toFixed(0)}%)</span> |
||||
|
{:else} |
||||
|
<span class="ackreq">({Math.round(acquired)} / {Math.round(required)})</span> |
||||
|
{/if} |
||||
|
</div> |
||||
|
{/if} |
||||
|
|
||||
|
<!-- Progress Bar --> |
||||
|
<div class="bar" class:big> |
||||
|
{#if segmented} |
||||
|
{#each {length: Math.max(ons, 0)} as _} |
||||
|
<div class="segmented on {onClass}"></div> |
||||
|
{/each} |
||||
|
{#each {length: Math.max(offs, 0)} as _} |
||||
|
<div class="segmented off {offClass}"></div> |
||||
|
{/each} |
||||
|
{:else} |
||||
|
{#if ons > 0} |
||||
|
<div style="flex: {ons}" class="non-segmented on {onClass}"></div> |
||||
|
{/if} |
||||
|
{#if offs > 0} |
||||
|
<div style="flex: {offs}" class="non-segmented off {offClass}"></div> |
||||
|
{/if} |
||||
|
{/if} |
||||
|
</div> |
||||
|
|
||||
|
<!-- "Boat" --> |
||||
|
{#if boat != null && !boatDone} |
||||
|
<div class="bar boat"> |
||||
|
<div style="flex: {Math.min(boat, 1)}" class="non-segmented on {boatClass}"></div> |
||||
|
<div style="flex: {Math.max(1 - boat, 0)}" class="non-segmented off none"></div> |
||||
|
</div> |
||||
|
{/if} |
||||
|
</div> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
div.progress { |
||||
|
padding: 0.25em 0.5ch; |
||||
|
font-size: 0.9em; |
||||
|
flex-basis: calc(33.33% - 1ch); |
||||
|
|
||||
|
@media screen and (max-width: 1300px) { |
||||
|
flex-basis: calc(50% - 1ch); |
||||
|
} |
||||
|
|
||||
|
@media screen and (max-width: 600px) { |
||||
|
font-size: 1.2em; |
||||
|
flex-basis: calc(100% - 1ch); |
||||
|
} |
||||
|
|
||||
|
&.fullwidth { |
||||
|
flex-basis: calc(100% - 1ch); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
div.bar { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
margin: 0; |
||||
|
box-sizing: border-box; |
||||
|
width: 100%; |
||||
|
height: 8px; |
||||
|
margin: 0.5px 0; |
||||
|
transform: skew(-11.25deg, 0); |
||||
|
|
||||
|
margin-top: 0.2em; |
||||
|
|
||||
|
@media screen and (max-width: 600px) { |
||||
|
height: 6px; |
||||
|
} |
||||
|
|
||||
|
&.big { |
||||
|
height: 12px; |
||||
|
} |
||||
|
&.boat { |
||||
|
transform: skew(-11.25deg, 0) translateX(-1.1px); |
||||
|
margin-top: 0em; |
||||
|
height: 2.5px; |
||||
|
} |
||||
|
|
||||
|
> div { |
||||
|
flex-grow: 1; |
||||
|
flex-basis: 0; |
||||
|
display: inline-block; |
||||
|
box-sizing: border-box; |
||||
|
margin: 0 0.5px; |
||||
|
border: 0.25px solid #000; |
||||
|
|
||||
|
div.non-segmented { |
||||
|
flex-grow: inherit; |
||||
|
flex-basis: inherit; |
||||
|
} |
||||
|
|
||||
|
&.on {opacity: 0.75; } |
||||
|
&.none { background-color: #000; } |
||||
|
&.gray { background-color: #999; opacity: 1; } |
||||
|
&.bronze { background-color: #f4b083; } |
||||
|
&.silver { background-color: #d8dce4; opacity: 0.8; } |
||||
|
&.gold { background-color: #ffd966; opacity: 0.9; } |
||||
|
&.green { background-color: #8ef88e; opacity: 0.8; } |
||||
|
&.red { background-color: hsl(0, 95%, 70%); opacity: 0.8; } |
||||
|
&.off {opacity: 0.30; } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
span.ackreq { |
||||
|
opacity: 0.333; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,16 @@ |
|||||
|
<div class="progress-row"> |
||||
|
<slot></slot> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
div.progress-row { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
flex-wrap: wrap; |
||||
|
margin-top: 0.5em; |
||||
|
font-size: 0.75em; |
||||
|
} |
||||
|
div.progress-row:empty { |
||||
|
margin-top: 0; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,16 @@ |
|||||
|
import type { ProjectEntry } from "./project"; |
||||
|
import type { ScopeEntry } from "./scope"; |
||||
|
import type { StatProgressEntry } from "./stat"; |
||||
|
|
||||
|
export default interface Item { |
||||
|
id: number |
||||
|
name: string |
||||
|
description: string |
||||
|
acquireDate?: string |
||||
|
stats: StatProgressEntry[] |
||||
|
} |
||||
|
|
||||
|
export interface StandaloneItem extends Item { |
||||
|
scope: ScopeEntry |
||||
|
project?: ProjectEntry |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
import type Item from "./item"; |
||||
|
import type Scope from "./scope"; |
||||
|
import type { ScopeEntry } from "./scope"; |
||||
|
import type { StatAggregate, StatEntry, StatProgressEntry } from "./stat"; |
||||
|
import type Stat from "./stat"; |
||||
|
import type Status from "./status"; |
||||
|
|
||||
|
export default interface Project { |
||||
|
id: number |
||||
|
name: string |
||||
|
description: string |
||||
|
status: Status |
||||
|
|
||||
|
scope: ScopeEntry |
||||
|
requirements: Requirement[] |
||||
|
} |
||||
|
|
||||
|
export interface ProjectEntry { |
||||
|
id: number |
||||
|
name: string |
||||
|
status: Status |
||||
|
} |
||||
|
|
||||
|
export interface Requirement { |
||||
|
id: number |
||||
|
name: string |
||||
|
description: string |
||||
|
status: Status |
||||
|
|
||||
|
stats: StatProgressEntry[] |
||||
|
} |
||||
|
|
||||
|
export interface StandaloneRequirement extends Requirement { |
||||
|
scope: ScopeEntry |
||||
|
project: ProjectEntry |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
import type { ProjectEntry } from "./project"; |
||||
|
|
||||
|
export default interface Scope extends ScopeEntry { |
||||
|
activeProjects: ProjectEntry[] |
||||
|
} |
||||
|
|
||||
|
export interface ScopeEntry { |
||||
|
id: number |
||||
|
name: string |
||||
|
abbreviation: string |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
import type { StandaloneItem } from "./item"; |
||||
|
import type { StandaloneRequirement } from "./project"; |
||||
|
import type { ScopeEntry } from "./scope"; |
||||
|
import type { StatAggregate, StatProgressEntry } from "./stat"; |
||||
|
|
||||
|
export default interface Sprint { |
||||
|
id: number |
||||
|
name: string |
||||
|
description: string |
||||
|
from: string |
||||
|
to: string |
||||
|
timed: boolean |
||||
|
coarse: boolean |
||||
|
kind: "item" | "requirements" | "stats" |
||||
|
scope: ScopeEntry |
||||
|
items: StandaloneItem[] |
||||
|
requirements: StandaloneRequirement[] |
||||
|
aggregateRequired: number, |
||||
|
stats: StatProgressEntry[] |
||||
|
} |
||||
|
|
||||
|
export interface StandaloneSprint extends Sprint { |
||||
|
scope: ScopeEntry |
||||
|
} |
@ -0,0 +1,52 @@ |
|||||
|
export default interface Stat extends StatEntry { |
||||
|
description: string |
||||
|
allowedAmounts?: Record<string, number> |
||||
|
} |
||||
|
|
||||
|
export interface StatEntry { |
||||
|
id: number |
||||
|
weight: number |
||||
|
name: string |
||||
|
} |
||||
|
|
||||
|
export interface StatProgressEntry extends StatEntry { |
||||
|
acquired: number |
||||
|
required: number |
||||
|
} |
||||
|
|
||||
|
export interface StatAggregate { |
||||
|
acquired: number |
||||
|
required: number |
||||
|
} |
||||
|
|
||||
|
const EXAMPLE2: Stat = { |
||||
|
id: 12, |
||||
|
name: "Assets", |
||||
|
description: "The amount of 'assets' produced in the end. This does not contribute towards the weight", |
||||
|
weight: 0, |
||||
|
} |
||||
|
|
||||
|
const EXAMPLE3: Stat = { |
||||
|
id: 12, |
||||
|
name: "Hard Surface Practice", |
||||
|
description: "A value of the asset complexity, indicating how much general modeling practice is involved.", |
||||
|
weight: 0.5, |
||||
|
allowedAmounts: { |
||||
|
"Rote": 1, |
||||
|
"Novel": 2, |
||||
|
"Tutorial": 4, |
||||
|
"Difficult": 7, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const EXAMPLE: Stat = { |
||||
|
id: 12, |
||||
|
name: "Complexity Points", |
||||
|
description: "A value of the asset complexity, indicating how much general modeling practice is involved.", |
||||
|
weight: 1, |
||||
|
allowedAmounts: { |
||||
|
"Small": 1, |
||||
|
"Moderate": 3, |
||||
|
"Complex": 7, |
||||
|
} |
||||
|
} |
@ -0,0 +1,25 @@ |
|||||
|
enum Status { |
||||
|
Blocked = 0, |
||||
|
Available = 1, |
||||
|
Inactive = 2, |
||||
|
Active = 3, |
||||
|
Completed = 4, |
||||
|
Failed = 5, |
||||
|
Dropped = 6, |
||||
|
} |
||||
|
|
||||
|
// Blocked -> Available -> Active -> Completed
|
||||
|
// -> Failed
|
||||
|
// -> Dropped
|
||||
|
// -> Inactive -> Active
|
||||
|
|
||||
|
//
|
||||
|
// (X) Create basic furniture [S v] [/] [X]
|
||||
|
// ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨
|
||||
|
// There needs to be a servicable library of
|
||||
|
// furntirue for this project
|
||||
|
//
|
||||
|
// Asset Complexity HS Practice
|
||||
|
// [ ] [ ] 0
|
||||
|
|
||||
|
export default Status |
@ -0,0 +1,15 @@ |
|||||
|
import { writable, type Readable } from "svelte/store"; |
||||
|
|
||||
|
const currentTimeWritable = writable(new Date()); |
||||
|
|
||||
|
setInterval(() => { |
||||
|
currentTimeWritable.set(new Date()); |
||||
|
}, 15000); |
||||
|
|
||||
|
/** |
||||
|
* A readable store that is updated twice every minute with the current time. Mainly for the progress |
||||
|
* bar timers, but other coarse-grained timers could use it as well. |
||||
|
*/ |
||||
|
const currentTime: Readable<Date> = { subscribe: currentTimeWritable.subscribe } |
||||
|
|
||||
|
export default currentTime; |
@ -0,0 +1,10 @@ |
|||||
|
import type { StatAggregate, StatProgressEntry } from "$lib/models/stat"; |
||||
|
|
||||
|
export function calculateAggregate(entries: StatProgressEntry[]): StatAggregate { |
||||
|
return entries.reduce<StatAggregate>((acc, entry) => { |
||||
|
return { |
||||
|
acquired: acc.acquired + (entry.acquired * entry.weight), |
||||
|
required: acc.required + (entry.required * entry.weight), |
||||
|
} |
||||
|
}, {acquired: 0, required: 0}); |
||||
|
} |
@ -0,0 +1,146 @@ |
|||||
|
<script lang="ts" context="module"> |
||||
|
import type { LoadInput } from "@sveltejs/kit/types/internal"; |
||||
|
|
||||
|
const TIPS = [ |
||||
|
"Ctrl-click items and requirements in your suggestions to log it.", |
||||
|
"Suggestions are incomplete, go into scopes or sprints to view all you need to do.", |
||||
|
] |
||||
|
|
||||
|
export async function load({ url, fetch }: LoadInput ) { |
||||
|
const res = await fetch("indexdata.json"); |
||||
|
|
||||
|
if (res.ok) { |
||||
|
return { |
||||
|
props: { |
||||
|
...await res.json(), |
||||
|
tip: TIPS[Math.floor(Math.random() * TIPS.length)] |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
status: res.status, |
||||
|
error: `Failed: ${res.status}` |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import ItemLink from "$lib/components/frontpage/ItemLink.svelte"; |
||||
|
import ScopeLink from "$lib/components/frontpage/ScopeLink.svelte"; |
||||
|
import RequirementLink from "$lib/components/frontpage/RequirementLink.svelte"; |
||||
|
import type { ScopeEntry } from "$lib/models/scope"; |
||||
|
import type { StandaloneItem } from "$lib/models/item"; |
||||
|
import type { StandaloneRequirement } from "$lib/models/project"; |
||||
|
import type { StandaloneSprint } from "$lib/models/sprint"; |
||||
|
import SprintLink from "$lib/components/frontpage/SprintLink.svelte"; |
||||
|
|
||||
|
export let scopes: ScopeEntry[] = []; |
||||
|
export let items: StandaloneItem[] = []; |
||||
|
export let requirements: StandaloneRequirement[] = []; |
||||
|
export let sprints: StandaloneSprint[] = []; |
||||
|
export let tip: string; |
||||
|
</script> |
||||
|
|
||||
|
<div class="header-wrapper"> |
||||
|
<h1>Stufflog</h1> |
||||
|
<h2>Logging your stuff.</h2> |
||||
|
</div> |
||||
|
|
||||
|
<main> |
||||
|
<div class="column"> |
||||
|
<div class="row"> |
||||
|
<h2>Scopes</h2> |
||||
|
{#each scopes as scope (scope.id)} |
||||
|
<ScopeLink scope={scope} /> |
||||
|
{/each} |
||||
|
</div> |
||||
|
<div class="row"> |
||||
|
<h2>Today</h2> |
||||
|
<p>When you mark an item as aquired today, it will appear here.</p> |
||||
|
<p>TIP: {tip}</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="column"> |
||||
|
<div class="row"> |
||||
|
<h2>Suggestions</h2> |
||||
|
{#each items as item (item.id)} |
||||
|
<ItemLink item={item} /> |
||||
|
{/each} |
||||
|
{#each requirements as requirement (requirement.id)} |
||||
|
<RequirementLink requirement={requirement} /> |
||||
|
{/each} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="column"> |
||||
|
<div class="row"> |
||||
|
<h2>Sprints</h2> |
||||
|
{#each sprints as sprint (sprint.id)} |
||||
|
<SprintLink sprint={sprint} /> |
||||
|
{/each} |
||||
|
</div> |
||||
|
</div> |
||||
|
</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; |
||||
|
} |
||||
|
|
||||
|
main { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
flex-basis: 100%; |
||||
|
flex: 1; |
||||
|
|
||||
|
width: 180ch; |
||||
|
max-width: 95%; |
||||
|
margin: auto; |
||||
|
|
||||
|
@media screen and (max-width: 1000px) { |
||||
|
width: 100%; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
> div.column { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
flex-basis: 50; |
||||
|
flex: 1; |
||||
|
|
||||
|
> div.row { |
||||
|
margin: 0.5em 1ch; |
||||
|
padding: 0.5em 1ch; |
||||
|
|
||||
|
> h2 { |
||||
|
font-size: 1.25em; |
||||
|
margin: 0; |
||||
|
margin-bottom: 0.25em; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,190 @@ |
|||||
|
import type { RequestHandler } from "@sveltejs/kit" |
||||
|
|
||||
|
import type { StandaloneItem } from "$lib/models/item" |
||||
|
import type { StandaloneRequirement } from "$lib/models/project" |
||||
|
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"}, |
||||
|
] |
||||
|
|
||||
|
const items: StandaloneItem[] = [ |
||||
|
{ |
||||
|
id: 1, scope: scopes[0], |
||||
|
name: "Table", |
||||
|
description: "A table for the Redrock rec-room.", |
||||
|
acquireDate: "2022-03-14T00:00:00Z", |
||||
|
stats: [ |
||||
|
{id: 1, name: "Asset", weight: 0.2, required: 1, acquired: 1}, |
||||
|
{id: 2, name: "Complexity", weight: 1, required: 3, acquired: 5}, |
||||
|
], |
||||
|
project: { |
||||
|
id: 443, |
||||
|
name: "3D Maps: Proving the concept", |
||||
|
status: Status.Active |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
id: 2, scope: scopes[0], |
||||
|
name: "Datapad Set", |
||||
|
description: "I need one, at least, but more is better.", |
||||
|
stats: [ |
||||
|
{id: 1, name: "Asset", weight: 0.2, required: 1, acquired: 0}, |
||||
|
{id: 2, name: "Complexity", weight: 1, required: 3, acquired: 0}, |
||||
|
{id: 3, name: "Hard Surface", weight: 0.333, required: 1, acquired: 0}, |
||||
|
], |
||||
|
project: { |
||||
|
id: 443, |
||||
|
name: "3D Maps: Proving the concept", |
||||
|
status: Status.Active |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
id: 3, scope: scopes[1], |
||||
|
name: "Enila/Renala: Technicalities", |
||||
|
description: "Renala is answering Leah's concern and takes the shift at the Respite.", |
||||
|
stats: [ |
||||
|
{id: 1, name: "Story", weight: 3, required: 1, acquired: 0}, |
||||
|
{id: 2, name: "Story Word", weight: 0.002, required: 500, acquired: 0}, |
||||
|
], |
||||
|
project: { |
||||
|
id: 1, |
||||
|
name: "Background Stories", |
||||
|
status: Status.Active |
||||
|
} |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
const requirements: StandaloneRequirement[] = [ |
||||
|
{ |
||||
|
id: 1, |
||||
|
name: "Basic Furniture", |
||||
|
description: "I need a lot of it.", |
||||
|
project: { |
||||
|
id: 443, |
||||
|
name: "3D Maps: Proving the concept", |
||||
|
status: Status.Active |
||||
|
}, |
||||
|
status: Status.Active, |
||||
|
stats: [ |
||||
|
{id: 1, name: "Asset", weight: 0.2, acquired: 8, required: 15}, |
||||
|
{id: 2, name: "Complexity", weight: 1, acquired: 69, required: 30}, |
||||
|
{id: 3, name: "Hard Surface", weight: 0.333, acquired: 20, required: 5}, |
||||
|
], |
||||
|
scope: scopes[0], |
||||
|
}, |
||||
|
{ |
||||
|
id: 2, |
||||
|
name: "Catching Up", |
||||
|
description: "Write a few stories to get back up to speed with less written characters.", |
||||
|
project: { |
||||
|
id: 1, |
||||
|
name: "Background Stories", |
||||
|
status: Status.Active |
||||
|
}, |
||||
|
status: Status.Active, |
||||
|
stats: [ |
||||
|
{id: 1, name: "Story", weight: 3, required: 10, acquired: 3}, |
||||
|
{id: 2, name: "Story Word", weight: 0.002, required: 5000, acquired: 2173}, |
||||
|
{id: 3, name: "Worldbuilding", weight: 0.5, required: 5, acquired: 1}, |
||||
|
], |
||||
|
scope: scopes[1], |
||||
|
}, |
||||
|
{ |
||||
|
id: 3, |
||||
|
name: "Chapter 3", |
||||
|
description: "it's go time", |
||||
|
project: { |
||||
|
id: 1, |
||||
|
name: "Wenera's Job", |
||||
|
status: Status.Active |
||||
|
}, |
||||
|
status: Status.Active, |
||||
|
stats: [ |
||||
|
{id: 1, name: "Story", weight: 3, required: 5, acquired: 1}, |
||||
|
{id: 2, name: "Story Word", weight: 0.002, required: 4000, acquired: 759}, |
||||
|
], |
||||
|
scope: scopes[1], |
||||
|
} |
||||
|
] |
||||
|
|
||||
|
const sprints: StandaloneSprint[] = [ |
||||
|
{ |
||||
|
id: 553, |
||||
|
name: "March Sprint", |
||||
|
description: "Hey kid, wanna model some trees?", |
||||
|
from: "2022-03-01T00:00:00+0200", |
||||
|
to: "2022-03-30T23:59:59+0200", |
||||
|
coarse: false, |
||||
|
kind: "stats", |
||||
|
scope: scopes[0], |
||||
|
timed: true, |
||||
|
stats: [ |
||||
|
{id: 1, name: "Asset", weight: 0, acquired: 13, required: 15}, |
||||
|
{id: 2, name: "Complexity", weight: 1, acquired: 37, required: 30}, |
||||
|
{id: 3, name: "Hard Surface", weight: 0.25, acquired: 8, required: 5}, |
||||
|
{id: 4, name: "UV Mapping", weight: 0.25, acquired: 3, required: 5}, |
||||
|
], |
||||
|
items: [], |
||||
|
requirements: [], |
||||
|
aggregateRequired: 40, |
||||
|
}, |
||||
|
{ |
||||
|
id: 643, |
||||
|
name: "March Sprint", |
||||
|
description: "Crank out stories", |
||||
|
from: "2022-03-01T00:00:00+0200", |
||||
|
to: "2022-03-30T23:59:59+0200", |
||||
|
coarse: false, |
||||
|
kind: "requirements", |
||||
|
scope: scopes[1], |
||||
|
timed: true, |
||||
|
stats: [], |
||||
|
items: [], |
||||
|
requirements: [ |
||||
|
requirements[1], |
||||
|
requirements[2], |
||||
|
], |
||||
|
aggregateRequired: 0, |
||||
|
}, |
||||
|
{ |
||||
|
id: 771, |
||||
|
name: "March Sprint", |
||||
|
description: "Do these", |
||||
|
from: "2022-03-01T00:00:00+0200", |
||||
|
to: "2022-03-30T23:59:59+0200", |
||||
|
coarse: false, |
||||
|
kind: "item", |
||||
|
scope: scopes[0], |
||||
|
timed: true, |
||||
|
stats: [ |
||||
|
{id: 1, name: "Asset", weight: 0.2, required: 2, acquired: 1}, |
||||
|
{id: 2, name: "Complexity", weight: 1, required: 8, acquired: 5}, |
||||
|
{id: 3, name: "Hard Surface", weight: 0.333, required: 1, acquired: 0}, |
||||
|
], |
||||
|
items: [ |
||||
|
items[0], |
||||
|
items[1], |
||||
|
], |
||||
|
requirements: [], |
||||
|
aggregateRequired: 0, |
||||
|
} |
||||
|
] |
||||
|
|
||||
|
return { |
||||
|
status: 200, |
||||
|
headers: { |
||||
|
"Content-Type": "application/json" |
||||
|
}, |
||||
|
body: JSON.stringify({ |
||||
|
scopes, items, requirements, sprints |
||||
|
}), |
||||
|
} |
||||
|
} |
After Width: 128 | Height: 128 | Size: 1.5 KiB |
@ -0,0 +1,15 @@ |
|||||
|
import adapter from '@sveltejs/adapter-auto'; |
||||
|
import preprocess from 'svelte-preprocess'; |
||||
|
|
||||
|
/** @type {import('@sveltejs/kit').Config} */ |
||||
|
const config = { |
||||
|
// Consult https://github.com/sveltejs/svelte-preprocess
|
||||
|
// for more information about preprocessors
|
||||
|
preprocess: preprocess(), |
||||
|
|
||||
|
kit: { |
||||
|
adapter: adapter() |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
export default config; |
@ -0,0 +1,36 @@ |
|||||
|
{ |
||||
|
"compilerOptions": { |
||||
|
"moduleResolution": "node", |
||||
|
"module": "es2020", |
||||
|
"lib": ["es2020", "DOM"], |
||||
|
"target": "es2020", |
||||
|
/** |
||||
|
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript |
||||
|
to enforce using \`import type\` instead of \`import\` for Types. |
||||
|
*/ |
||||
|
"importsNotUsedAsValues": "error", |
||||
|
/** |
||||
|
TypeScript doesn't know about import usages in the template because it only sees the |
||||
|
script of a Svelte file. Therefore preserve all value imports. Requires TS 4.5 or higher. |
||||
|
*/ |
||||
|
"preserveValueImports": true, |
||||
|
"isolatedModules": true, |
||||
|
"resolveJsonModule": true, |
||||
|
/** |
||||
|
To have warnings/errors of the Svelte compiler at the correct position, |
||||
|
enable source maps by default. |
||||
|
*/ |
||||
|
"sourceMap": true, |
||||
|
"esModuleInterop": true, |
||||
|
"skipLibCheck": true, |
||||
|
"forceConsistentCasingInFileNames": true, |
||||
|
"baseUrl": ".", |
||||
|
"allowJs": true, |
||||
|
"checkJs": true, |
||||
|
"paths": { |
||||
|
"$lib": ["src/lib"], |
||||
|
"$lib/*": ["src/lib/*"] |
||||
|
} |
||||
|
}, |
||||
|
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"] |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue