show added/removed status in sessions list

This commit is contained in:
Nikita Galaiko 2023-05-30 15:28:29 +02:00
parent 3cf1532138
commit a1da5ba8bc
6 changed files with 88 additions and 23 deletions

View File

@ -0,0 +1,23 @@
<script lang="ts">
export let added = 0;
export let removed = 0;
$: diffStatRatio = added / (added + removed);
$: diffStatAdded = Math.floor(4 * diffStatRatio);
$: diffStatRemoved = 4 - diffStatAdded;
</script>
<div class="flex items-center gap-2">
<div id="diffstat-lines" class="flex items-center gap-1">
<span class="text-green-400">+{added}</span>
<span class="text-red-500">-{removed}</span>
</div>
<div id="diffstat-squares" class="flex items-center gap-0.5">
{#each { length: diffStatAdded } as _}
<div class="h-2 w-2 rounded-sm bg-green-400" />
{/each}
{#each { length: diffStatRemoved } as _}
<div class="h-2 w-2 rounded-sm bg-red-500" />
{/each}
</div>
</div>

View File

@ -11,3 +11,4 @@ export { default as Differ } from './Differ';
export { default as DeltasViewer } from './DeltasViewer.svelte';
export { default as DiffContext } from './DiffContext.svelte';
export { default as Checkbox } from './Checkbox';
export { default as Stats } from './Stats.svelte';

View File

@ -3,6 +3,7 @@
import { Status, type Project, git, type CloudApi, type User } from '$lib/api';
import { Button, Overlay, Link } from '$lib/components';
import { IconGitBranch, IconSparkle } from '$lib/icons';
import { Stats } from '$lib/components';
export const show = () => modal.show();
@ -29,7 +30,7 @@
});
};
let [linesAdded, linesRemoved] = Object.values(diffs)
$: [linesAdded, linesRemoved] = Object.values(diffs)
.map((diff) => {
let added = 0;
let removed = 0;
@ -50,10 +51,6 @@
})
.reduce((a, b) => [a[0] + b[0], a[1] + b[1]], [0, 0]);
let diffStatRatio = linesAdded / (linesAdded + linesRemoved);
let diffStatAdded = Math.floor(4 * diffStatRatio);
let diffStatRemoved = 4 - diffStatAdded;
const reset = () => {
summary = '';
description = '';
@ -180,22 +177,8 @@
href="/projects/{project.id}/commit/"
>
{Object.keys(statuses).length} files changed
<Stats added={linesAdded} removed={linesRemoved} />
</Link>
<div id="diffstat" class="flex items-center gap-2">
<div id="diffstat-lines" class="flex items-center gap-1">
<span class="text-green-400">+{linesAdded}</span>
<span class="text-red-500">-{linesRemoved}</span>
</div>
<div id="diffstat-squares" class="flex items-center gap-0.5">
{#each { length: diffStatAdded } as _}
<div class="h-2 w-2 rounded-sm bg-green-400" />
{/each}
{#each { length: diffStatRemoved } as _}
<div class="h-2 w-2 rounded-sm bg-red-500" />
{/each}
</div>
</div>
</div>
<div class="flex gap-2">

View File

@ -31,6 +31,11 @@
Object.fromEntries(
Object.entries(deltas).filter(([path]) => (filter ? path === filter : true))
)
),
files: derived(stores.files({ projectId, sessionId: session.id }), (files) =>
Object.fromEntries(
Object.entries(files).filter(([path]) => (filter ? path === filter : true))
)
)
}))
);

View File

@ -1,16 +1,55 @@
<script lang="ts">
import type { Delta, Session } from '$lib/api';
import { Operation, type Delta, type Session } from '$lib/api';
import { page } from '$app/stores';
import { collapse } from '$lib/paths';
import { derived } from '@square/svelte-store';
import { stores } from '$lib';
import { IconBookmarkFilled } from '$lib/icons';
import { Value } from 'svelte-loadable-store';
import { line } from '$lib/diff';
import { Stats } from '$lib/components';
export let isCurrent: boolean;
export let session: Session;
export let currentFilepath: string;
export let deltas: Record<string, Delta[]>;
export let files: Record<string, string>;
const applyDeltas = (text: string, deltas: Delta[]) => {
const operations = deltas.flatMap((delta) => delta.operations);
operations.forEach((operation) => {
if (Operation.isInsert(operation)) {
text =
text.slice(0, operation.insert[0]) +
operation.insert[1] +
text.slice(operation.insert[0]);
} else if (Operation.isDelete(operation)) {
text =
text.slice(0, operation.delete[0]) +
text.slice(operation.delete[0] + operation.delete[1]);
}
});
return text;
};
$: stats = Object.entries(deltas)
.map(([path, deltas]) => {
const doc = files[path] ?? '';
const left = deltas.length > 0 ? applyDeltas(doc, deltas.slice(0, deltas.length - 1)) : doc;
const right = deltas.length > 0 ? applyDeltas(left, deltas.slice(deltas.length - 1)) : left;
const diff = line(left.split('\n'), right.split('\n'));
const linesAdded = diff
.filter((d) => d[0] === 1)
.map((d) => d[1].length)
.reduce((a, b) => a + b, 0);
const linesRemoved = diff
.filter((d) => d[0] === -1)
.map((d) => d[1].length)
.reduce((a, b) => a + b, 0);
return [linesAdded, linesRemoved];
})
.reduce((a, b) => [a[0] + b[0], a[1] + b[1]], [0, 0]);
$: bookmarks = derived(stores.bookmarks.list({ projectId: session.projectId }), (bookmarks) => {
if (bookmarks.isLoading) return [];
@ -88,6 +127,8 @@
<span class="flex flex-row justify-between px-3 pb-3">
{changedFiles.length}
{changedFiles.length !== 1 ? 'files' : 'file'}
<Stats added={stats[0]} removed={stats[1]} />
</span>
{#if isCurrent}

View File

@ -7,6 +7,7 @@
export let sessions: (Session & {
deltas: Readable<Loadable<Record<string, Delta[]>>>;
files: Readable<Loadable<Record<string, string>>>;
})[];
export let currentSession: Session | undefined;
export let currentFilepath: string;
@ -16,6 +17,11 @@
(deltas) => deltas.map((delta) => Object.fromEntries(Object.entries(delta ?? {})))
);
$: visibleFiles = derived(
sessions.map(({ files }) => files),
(files) => files.map((file) => Object.fromEntries(Object.entries(file ?? {})))
);
$: visibleSessions = sessions?.map((session, i) => ({
...session,
visible:
@ -42,8 +48,14 @@
>
{#each visibleSessions as session, i}
{@const isCurrent = session.id === currentSession?.id}
{#if session.visible && !$visibleDeltas.isLoading && !Value.isError($visibleDeltas.value)}
<SessionCard {isCurrent} {session} deltas={$visibleDeltas.value[i]} {currentFilepath} />
{#if session.visible && !$visibleDeltas.isLoading && !Value.isError($visibleDeltas.value) && !$visibleFiles.isLoading && !Value.isError($visibleFiles.value)}
<SessionCard
{isCurrent}
{session}
deltas={$visibleDeltas.value[i]}
files={$visibleFiles.value[i]}
{currentFilepath}
/>
{/if}
{:else}
<div class="mt-4 text-center text-zinc-300">No activities found</div>