diff --git a/package.json b/package.json index ce0038f19..d82424471 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@codemirror/merge": "^0.1.3", "@codemirror/state": "^6.2.0", "@codemirror/view": "^6.7.3", + "@square/svelte-store": "^1.0.14", "@tauri-apps/api": "^1.2.0", "date-fns": "^2.29.3", "fluent-svelte": "^1.6.0", @@ -35,16 +36,16 @@ "@sveltejs/kit": "next", "@tauri-apps/cli": "^1.2.2", "@types/diff": "^5.0.2", - "autoprefixer": "^10.4.7", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", + "autoprefixer": "^10.4.7", "eslint": "^8.28.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-svelte3": "^4.0.0", - "prettier": "^2.8.0", - "prettier-plugin-svelte": "^2.8.1", "postcss": "^8.4.14", "postcss-load-config": "^4.0.1", + "prettier": "^2.8.0", + "prettier-plugin-svelte": "^2.8.1", "svelte": "^3.55.1", "svelte-check": "^3.0.1", "tailwindcss": "^3.1.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b30ec9bc..9a9140520 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,7 @@ specifiers: '@codemirror/merge': ^0.1.3 '@codemirror/state': ^6.2.0 '@codemirror/view': ^6.7.3 + '@square/svelte-store': ^1.0.14 '@sveltejs/adapter-static': next '@sveltejs/kit': next '@tauri-apps/api': ^1.2.0 @@ -43,6 +44,7 @@ dependencies: '@codemirror/merge': 0.1.3 '@codemirror/state': 6.2.0 '@codemirror/view': 6.7.3 + '@square/svelte-store': 1.0.14 '@tauri-apps/api': 1.2.0 date-fns: 2.29.3 fluent-svelte: 1.6.0 @@ -411,6 +413,13 @@ packages: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true + /@square/svelte-store/1.0.14: + resolution: {integrity: sha512-kNaSpEec2JevfOB9XaWkq00oAOvm2fq8/0yotg++UVEHuHXQqM6pW602ByjBwFHn1gTRSdb568BAtkEDBt5uKQ==} + dependencies: + cookie-storage: 6.1.0 + svelte: 3.55.1 + dev: false + /@sveltejs/adapter-static/1.0.0-next.50_l5ueyfihz3gpzzvvyo2ean5u3e: resolution: {integrity: sha512-xZKBmiwFGW8nrH8+eysUAAo9XrtApI81q0m67y1bexVw8IY7/x741b6VEklNM7BZ7js0Mi2x+yCkHpOee8UZKQ==} peerDependencies: @@ -992,6 +1001,10 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true + /cookie-storage/6.1.0: + resolution: {integrity: sha512-HeVqbVy8BjXhAAuFtL6MTG+witHoLbxfky2jgVh9FmxmyL6IKa9gSSyPNjevXCCCxPu6Tzd9J8+eXTRQzYU/cg==} + dev: false + /cookie/0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} diff --git a/src/routes/projects/[projectId]/timeline/+page.svelte b/src/routes/projects/[projectId]/timeline/+page.svelte index c35cdb484..5d2ec4749 100644 --- a/src/routes/projects/[projectId]/timeline/+page.svelte +++ b/src/routes/projects/[projectId]/timeline/+page.svelte @@ -2,9 +2,11 @@ import { themeIcons } from 'seti-icons'; import type { PageData } from './$types'; import { derived } from 'svelte/store'; + import { asyncDerived } from '@square/svelte-store'; import type { Session } from '$lib/sessions'; import { startOfDay } from 'date-fns'; import { list as listDeltas } from '$lib/deltas'; + import type { Delta } from '$lib/deltas'; export let data: PageData; const { project, sessions } = data; @@ -48,17 +50,36 @@ return svg; } - $: dateSessions = derived([sessions], ([sessions]) => { - const dateSessions: Record = {}; - sessions.forEach((session) => { - const date = startOfDay(new Date(session.meta.startTimestampMs)); + type UISession = { session: Session; deltas: Record }; + + $: dateSessions = asyncDerived([sessions], async ([sessions]) => { + const deltas = await Promise.all( + sessions.map((session) => { + return listDeltas({ + projectId: $project?.id, + sessionId: session.id + }); + }) + ); + + const uiSessions = sessions + .map((session, i) => { + return { session, deltas: deltas[i] } as UISession; + }) + .filter((uiSession) => { + return Object.keys(uiSession.deltas).length > 0; + }); + + const dateSessions: Record = {}; + uiSessions.forEach((uiSession) => { + const date = startOfDay(new Date(uiSession.session.meta.startTimestampMs)); if (dateSessions[date.getTime()]) { - dateSessions[date.getTime()]?.push(session); + dateSessions[date.getTime()]?.push(uiSession); } else { - dateSessions[date.getTime()] = [session]; + dateSessions[date.getTime()] = [uiSession]; } }); - // TODO: maybe sort? + return dateSessions; }); @@ -67,43 +88,48 @@
All sessions
- {#each Object.entries($dateSessions) as [dateMilliseconds, sessions]} - -
-
{formatDate(new Date(+dateMilliseconds))}
-
- {#each sessions as session} - -
-
- {formatTime(new Date(session.meta.startTimestampMs))} - - - {formatTime(new Date(session.meta.lastTimestampMs))} -
-
- {Math.round( - (session.meta.lastTimestampMs - session.meta.startTimestampMs) / 1000 / 60 - )} min -
-
- {#await listDeltas( { projectId: $project?.id, sessionId: session.id } ) then deltas} - {#each Object.keys(deltas) as delta} + {#if $dateSessions === undefined} + Loading... + {:else} + {#each Object.entries($dateSessions) as [dateMilliseconds, uiSessions]} + +
+
{formatDate(new Date(+dateMilliseconds))}
+
+ {#each uiSessions as uiSession} + +
+
+ {formatTime(new Date(uiSession.session.meta.startTimestampMs))} + - + {formatTime(new Date(uiSession.session.meta.lastTimestampMs))} +
+
+ {Math.round( + (uiSession.session.meta.lastTimestampMs - + uiSession.session.meta.startTimestampMs) / + 1000 / + 60 + )} min +
+
+ {#each Object.keys(uiSession.deltas) as filePath}
- {@html pathToIconSvg(delta)} + {@html pathToIconSvg(filePath)}
- {pathToName(delta)} + {pathToName(filePath)}
{/each} - {/await} +
-
- {/each} + {/each} +
-
- {/each} + {/each} + {/if}