mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-23 09:33:01 +03:00
Found this nice way of doing async derived stores
This commit is contained in:
parent
e8d8d158ce
commit
d9dc79a4b4
@ -17,6 +17,7 @@
|
|||||||
"@codemirror/merge": "^0.1.3",
|
"@codemirror/merge": "^0.1.3",
|
||||||
"@codemirror/state": "^6.2.0",
|
"@codemirror/state": "^6.2.0",
|
||||||
"@codemirror/view": "^6.7.3",
|
"@codemirror/view": "^6.7.3",
|
||||||
|
"@square/svelte-store": "^1.0.14",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"fluent-svelte": "^1.6.0",
|
"fluent-svelte": "^1.6.0",
|
||||||
@ -35,16 +36,16 @@
|
|||||||
"@sveltejs/kit": "next",
|
"@sveltejs/kit": "next",
|
||||||
"@tauri-apps/cli": "^1.2.2",
|
"@tauri-apps/cli": "^1.2.2",
|
||||||
"@types/diff": "^5.0.2",
|
"@types/diff": "^5.0.2",
|
||||||
"autoprefixer": "^10.4.7",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
"@typescript-eslint/parser": "^5.45.0",
|
"@typescript-eslint/parser": "^5.45.0",
|
||||||
|
"autoprefixer": "^10.4.7",
|
||||||
"eslint": "^8.28.0",
|
"eslint": "^8.28.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-svelte3": "^4.0.0",
|
"eslint-plugin-svelte3": "^4.0.0",
|
||||||
"prettier": "^2.8.0",
|
|
||||||
"prettier-plugin-svelte": "^2.8.1",
|
|
||||||
"postcss": "^8.4.14",
|
"postcss": "^8.4.14",
|
||||||
"postcss-load-config": "^4.0.1",
|
"postcss-load-config": "^4.0.1",
|
||||||
|
"prettier": "^2.8.0",
|
||||||
|
"prettier-plugin-svelte": "^2.8.1",
|
||||||
"svelte": "^3.55.1",
|
"svelte": "^3.55.1",
|
||||||
"svelte-check": "^3.0.1",
|
"svelte-check": "^3.0.1",
|
||||||
"tailwindcss": "^3.1.5",
|
"tailwindcss": "^3.1.5",
|
||||||
|
@ -5,6 +5,7 @@ specifiers:
|
|||||||
'@codemirror/merge': ^0.1.3
|
'@codemirror/merge': ^0.1.3
|
||||||
'@codemirror/state': ^6.2.0
|
'@codemirror/state': ^6.2.0
|
||||||
'@codemirror/view': ^6.7.3
|
'@codemirror/view': ^6.7.3
|
||||||
|
'@square/svelte-store': ^1.0.14
|
||||||
'@sveltejs/adapter-static': next
|
'@sveltejs/adapter-static': next
|
||||||
'@sveltejs/kit': next
|
'@sveltejs/kit': next
|
||||||
'@tauri-apps/api': ^1.2.0
|
'@tauri-apps/api': ^1.2.0
|
||||||
@ -43,6 +44,7 @@ dependencies:
|
|||||||
'@codemirror/merge': 0.1.3
|
'@codemirror/merge': 0.1.3
|
||||||
'@codemirror/state': 6.2.0
|
'@codemirror/state': 6.2.0
|
||||||
'@codemirror/view': 6.7.3
|
'@codemirror/view': 6.7.3
|
||||||
|
'@square/svelte-store': 1.0.14
|
||||||
'@tauri-apps/api': 1.2.0
|
'@tauri-apps/api': 1.2.0
|
||||||
date-fns: 2.29.3
|
date-fns: 2.29.3
|
||||||
fluent-svelte: 1.6.0
|
fluent-svelte: 1.6.0
|
||||||
@ -411,6 +413,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
|
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
|
||||||
dev: true
|
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:
|
/@sveltejs/adapter-static/1.0.0-next.50_l5ueyfihz3gpzzvvyo2ean5u3e:
|
||||||
resolution: {integrity: sha512-xZKBmiwFGW8nrH8+eysUAAo9XrtApI81q0m67y1bexVw8IY7/x741b6VEklNM7BZ7js0Mi2x+yCkHpOee8UZKQ==}
|
resolution: {integrity: sha512-xZKBmiwFGW8nrH8+eysUAAo9XrtApI81q0m67y1bexVw8IY7/x741b6VEklNM7BZ7js0Mi2x+yCkHpOee8UZKQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -992,6 +1001,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/cookie-storage/6.1.0:
|
||||||
|
resolution: {integrity: sha512-HeVqbVy8BjXhAAuFtL6MTG+witHoLbxfky2jgVh9FmxmyL6IKa9gSSyPNjevXCCCxPu6Tzd9J8+eXTRQzYU/cg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cookie/0.5.0:
|
/cookie/0.5.0:
|
||||||
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
import { themeIcons } from 'seti-icons';
|
import { themeIcons } from 'seti-icons';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
import { derived } from 'svelte/store';
|
import { derived } from 'svelte/store';
|
||||||
|
import { asyncDerived } from '@square/svelte-store';
|
||||||
import type { Session } from '$lib/sessions';
|
import type { Session } from '$lib/sessions';
|
||||||
import { startOfDay } from 'date-fns';
|
import { startOfDay } from 'date-fns';
|
||||||
import { list as listDeltas } from '$lib/deltas';
|
import { list as listDeltas } from '$lib/deltas';
|
||||||
|
import type { Delta } from '$lib/deltas';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
const { project, sessions } = data;
|
const { project, sessions } = data;
|
||||||
@ -48,17 +50,36 @@
|
|||||||
return svg;
|
return svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
$: dateSessions = derived([sessions], ([sessions]) => {
|
type UISession = { session: Session; deltas: Record<string, Delta[]> };
|
||||||
const dateSessions: Record<number, Session[]> = {};
|
|
||||||
sessions.forEach((session) => {
|
$: dateSessions = asyncDerived([sessions], async ([sessions]) => {
|
||||||
const date = startOfDay(new Date(session.meta.startTimestampMs));
|
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()]) {
|
if (dateSessions[date.getTime()]) {
|
||||||
dateSessions[date.getTime()]?.push(session);
|
dateSessions[date.getTime()]?.push(uiSession);
|
||||||
} else {
|
} else {
|
||||||
dateSessions[date.getTime()] = [session];
|
dateSessions[date.getTime()] = [uiSession];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// TODO: maybe sort?
|
|
||||||
return dateSessions;
|
return dateSessions;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -67,43 +88,48 @@
|
|||||||
<div class="m-6 overflow-x-hidden w-full">
|
<div class="m-6 overflow-x-hidden w-full">
|
||||||
All sessions
|
All sessions
|
||||||
<div class="flex flex-row border overflow-x-auto space-x-12 px-4 py-12">
|
<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}
|
||||||
<!-- Day -->
|
<span>Loading...</span>
|
||||||
<div class="bg-zinc-600 py-1 min-w-full overflow-hidden">
|
{:else}
|
||||||
<div>{formatDate(new Date(+dateMilliseconds))}</div>
|
{#each Object.entries($dateSessions) as [dateMilliseconds, uiSessions]}
|
||||||
<div class="flex space-x-2 ">
|
<!-- Day -->
|
||||||
{#each sessions as session}
|
<div class="bg-zinc-600 py-1 min-w-full overflow-hidden">
|
||||||
<!-- Session -->
|
<div>{formatDate(new Date(+dateMilliseconds))}</div>
|
||||||
<div>
|
<div class="flex space-x-2 ">
|
||||||
<div class="text-sm rounded borded bg-orange-500 text-zinc-200">
|
{#each uiSessions as uiSession}
|
||||||
{formatTime(new Date(session.meta.startTimestampMs))}
|
<!-- Session -->
|
||||||
-
|
<div>
|
||||||
{formatTime(new Date(session.meta.lastTimestampMs))}
|
<div class="text-sm rounded borded bg-orange-500 text-zinc-200">
|
||||||
</div>
|
{formatTime(new Date(uiSession.session.meta.startTimestampMs))}
|
||||||
<div title="Session duration">
|
-
|
||||||
{Math.round(
|
{formatTime(new Date(uiSession.session.meta.lastTimestampMs))}
|
||||||
(session.meta.lastTimestampMs - session.meta.startTimestampMs) / 1000 / 60
|
</div>
|
||||||
)} min
|
<div title="Session duration">
|
||||||
</div>
|
{Math.round(
|
||||||
<div title="Session files">
|
(uiSession.session.meta.lastTimestampMs -
|
||||||
{#await listDeltas( { projectId: $project?.id, sessionId: session.id } ) then deltas}
|
uiSession.session.meta.startTimestampMs) /
|
||||||
{#each Object.keys(deltas) as delta}
|
1000 /
|
||||||
|
60
|
||||||
|
)} min
|
||||||
|
</div>
|
||||||
|
<div title="Session files">
|
||||||
|
{#each Object.keys(uiSession.deltas) as filePath}
|
||||||
<div class="flex flex-row w-32 items-center">
|
<div class="flex flex-row w-32 items-center">
|
||||||
<div class="w-6 h-6 text-white fill-blue-400">
|
<div class="w-6 h-6 text-white fill-blue-400">
|
||||||
{@html pathToIconSvg(delta)}
|
{@html pathToIconSvg(filePath)}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-white w-24 truncate">
|
<div class="text-white w-24 truncate">
|
||||||
{pathToName(delta)}
|
{pathToName(filePath)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
{/await}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
{/each}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
{/each}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user