Found this nice way of doing async derived stores

This commit is contained in:
Kiril Videlov 2023-02-24 21:46:09 +01:00
parent e8d8d158ce
commit d9dc79a4b4
3 changed files with 78 additions and 38 deletions

View File

@ -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",

View File

@ -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'}

View File

@ -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<number, Session[]> = {};
sessions.forEach((session) => {
const date = startOfDay(new Date(session.meta.startTimestampMs));
type UISession = { session: Session; deltas: Record<string, Delta[]> };
$: 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<number, UISession[]> = {};
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;
});
</script>
@ -67,37 +88,38 @@
<div class="m-6 overflow-x-hidden w-full">
All sessions
<div class="flex flex-row border overflow-x-auto space-x-12 px-4 py-12">
{#each Object.entries($dateSessions) as [dateMilliseconds, sessions]}
{#if $dateSessions === undefined}
<span>Loading...</span>
{:else}
{#each Object.entries($dateSessions) as [dateMilliseconds, uiSessions]}
<!-- Day -->
<div class="bg-zinc-600 py-1 min-w-full overflow-hidden">
<div>{formatDate(new Date(+dateMilliseconds))}</div>
<div class="flex space-x-2 ">
{#each sessions as session}
{#each uiSessions as uiSession}
<!-- Session -->
<div>
<div class="text-sm rounded borded bg-orange-500 text-zinc-200">
{formatTime(new Date(session.meta.startTimestampMs))}
{formatTime(new Date(uiSession.session.meta.startTimestampMs))}
-
{formatTime(new Date(session.meta.lastTimestampMs))}
{formatTime(new Date(uiSession.session.meta.lastTimestampMs))}
</div>
<div title="Session duration">
{Math.round(
(session.meta.lastTimestampMs - session.meta.startTimestampMs) / 1000 / 60
(uiSession.session.meta.lastTimestampMs -
uiSession.session.meta.startTimestampMs) /
1000 /
60
)} min
</div>
<div title="Session files">
{#await listDeltas( { projectId: $project?.id, sessionId: session.id } ) then deltas}
{#each Object.keys(deltas) as delta}
{#each Object.keys(uiSession.deltas) as filePath}
<div class="flex flex-row w-32 items-center">
<div class="w-6 h-6 text-white fill-blue-400">
{@html pathToIconSvg(delta)}
{@html pathToIconSvg(filePath)}
</div>
<div class="text-white w-24 truncate">
{pathToName(delta)}
</div>
</div>
{/each}
{/await}
{pathToName(filePath)}
</div>
</div>
{/each}
@ -106,4 +128,8 @@
{/each}
</div>
</div>
{/each}
{/if}
</div>
</div>
</div>