🤦 Refactor timeline to use UISession data

- Refactor UI sessions to display deltas in the timeline
- Add dateSessions variable to the layout page
- Update timeline page to use dateSessions instead of sessions
- Refactor formatDate on timeline page
This commit is contained in:
Kiril Videlov 2023-03-02 15:03:54 +01:00
parent 8421901f34
commit 546c97c3ef
5 changed files with 70 additions and 61 deletions

View File

@ -4,3 +4,4 @@ export * as log from './log';
export * as toasts from './toasts'; export * as toasts from './toasts';
export * as sessions from './sessions'; export * as sessions from './sessions';
export * as week from './week'; export * as week from './week';
export * as uisessions from './uisessions';

9
src/lib/uisessions.ts Normal file
View File

@ -0,0 +1,9 @@
import type { Session } from '$lib/sessions';
import type { Delta } from '$lib/deltas';
export type UISession = {
session: Session;
deltas: Record<string, Delta[]>;
earliestDeltaTimestampMs: number;
latestDeltaTimestampMs: number;
};

View File

@ -11,6 +11,8 @@
$: project = data.project; $: project = data.project;
$: sessions = data.sessions; $: sessions = data.sessions;
$: lastSessionId = $sessions[$sessions.length - 1]?.id; $: lastSessionId = $sessions[$sessions.length - 1]?.id;
$: dateSessions = data.dateSessions;
console.debug('loading sessions for project: ', $dateSessions === undefined); // Force pre-loading of dateSessions
function projectUrl(project: Project) { function projectUrl(project: Project) {
const gitUrl = project.api?.git_url; const gitUrl = project.api?.git_url;

View File

@ -2,6 +2,11 @@ import { readable, derived } from 'svelte/store';
import type { LayoutLoad } from './$types'; import type { LayoutLoad } from './$types';
import { building } from '$app/environment'; import { building } from '$app/environment';
import type { Session } from '$lib/sessions'; import type { Session } from '$lib/sessions';
import type { UISession } from '$lib/uisessions';
import { asyncDerived } from '@square/svelte-store';
import { list as listDeltas } from '$lib/deltas';
import type { Delta } from '$lib/deltas';
import { startOfDay } from 'date-fns';
export const prerender = false; export const prerender = false;
@ -13,8 +18,58 @@ export const load: LayoutLoad = async ({ parent, params }) => {
const orderedSessions = derived(sessions, (sessions) => { const orderedSessions = derived(sessions, (sessions) => {
return sessions.slice().sort((a, b) => a.meta.startTimestampMs - b.meta.startTimestampMs); return sessions.slice().sort((a, b) => a.meta.startTimestampMs - b.meta.startTimestampMs);
}); });
const dateSessions = asyncDerived([orderedSessions], async ([sessions]) => {
const deltas = await Promise.all(
sessions.map((session) => {
return listDeltas({
projectId: params.projectId ?? '',
sessionId: session.id
});
})
);
// Sort deltas by timestamp
deltas.forEach((delta) => {
Object.keys(delta).forEach((key) => {
delta[key].sort((a, b) => a.timestampMs - b.timestampMs);
});
});
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(uiSession);
} else {
dateSessions[date.getTime()] = [uiSession];
}
});
// For each UISession in dateSessions, set the earliestDeltaTimestampMs and latestDeltaTimestampMs
Object.keys(dateSessions).forEach((date: any) => {
dateSessions[date].forEach((uiSession: any) => {
const deltaTimestamps = Object.keys(uiSession.deltas).reduce((acc, key) => {
return acc.concat(uiSession.deltas[key].map((delta: Delta) => delta.timestampMs));
}, []);
uiSession.earliestDeltaTimestampMs = Math.min(...deltaTimestamps);
uiSession.latestDeltaTimestampMs = Math.max(...deltaTimestamps);
});
});
return dateSessions;
});
return { return {
project: projects.get(params.projectId), project: projects.get(params.projectId),
sessions: orderedSessions sessions: orderedSessions,
dateSessions: dateSessions
}; };
}; };

View File

@ -1,10 +1,6 @@
<script lang="ts"> <script lang="ts">
import { themeIcons } from 'seti-icons'; import { themeIcons } from 'seti-icons';
import type { PageData } from './$types'; import type { PageData } from './$types';
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 { listFiles } from '$lib/sessions'; import { listFiles } from '$lib/sessions';
import type { Delta } from '$lib/deltas'; import type { Delta } from '$lib/deltas';
import { toHumanBranchName } from '$lib/branch'; import { toHumanBranchName } from '$lib/branch';
@ -13,9 +9,10 @@
import TimelineDaySessionActivities from '$lib/components/timeline/TimelineDaySessionActivities.svelte'; import TimelineDaySessionActivities from '$lib/components/timeline/TimelineDaySessionActivities.svelte';
import { CodeViewer } from '$lib/components'; import { CodeViewer } from '$lib/components';
import 'fluent-svelte/theme.css'; import 'fluent-svelte/theme.css';
import type { UISession } from '$lib/uisessions';
export let data: PageData; export let data: PageData;
const { project, sessions } = data; const { project, dateSessions } = data;
const formatDate = (date: Date) => { const formatDate = (date: Date) => {
return new Intl.DateTimeFormat('default', { return new Intl.DateTimeFormat('default', {
@ -56,61 +53,6 @@
return svg; return svg;
} }
type UISession = {
session: Session;
deltas: Record<string, Delta[]>;
earliestDeltaTimestampMs: number;
latestDeltaTimestampMs: number;
};
$: dateSessions = asyncDerived([sessions], async ([sessions]) => {
const deltas = await Promise.all(
sessions.map((session) => {
return listDeltas({
projectId: $project?.id ?? '',
sessionId: session.id
});
})
);
// Sort deltas by timestamp
deltas.forEach((delta) => {
Object.keys(delta).forEach((key) => {
delta[key].sort((a, b) => a.timestampMs - b.timestampMs);
});
});
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(uiSession);
} else {
dateSessions[date.getTime()] = [uiSession];
}
});
// For each UISession in dateSessions, set the earliestDeltaTimestampMs and latestDeltaTimestampMs
Object.keys(dateSessions).forEach((date: any) => {
dateSessions[date].forEach((uiSession: any) => {
const deltaTimestamps = Object.keys(uiSession.deltas).reduce((acc, key) => {
return acc.concat(uiSession.deltas[key].map((delta: Delta) => delta.timestampMs));
}, []);
uiSession.earliestDeltaTimestampMs = Math.min(...deltaTimestamps);
uiSession.latestDeltaTimestampMs = Math.max(...deltaTimestamps);
});
});
return dateSessions;
});
type Selection = { type Selection = {
sessionIdx: number; sessionIdx: number;
dateMilliseconds: number; dateMilliseconds: number;