Browse Source

feat(ListPRs): add author name to summary

refactor to reflect new stardards for ui and data logic seperation
master
DanConwayDev 2 years ago
parent
commit
9ccf21c0a7
No known key found for this signature in database
GPG Key ID: 68E15486D73F75E1
  1. BIN
      __snapshots__/navbar--default.png
  2. BIN
      __snapshots__/prs-list-item--author-loading.png
  3. BIN
      __snapshots__/prs-list-item--long-and-no-spaces.png
  4. BIN
      __snapshots__/prs-list-item--long-details.png
  5. BIN
      __snapshots__/prs-list-item--short-details.png
  6. 56
      __snapshots__/prs-list-item.test.js.snap
  7. BIN
      __snapshots__/prs-list-list--default.png
  8. BIN
      __snapshots__/prs-list-list--no-title.png
  9. BIN
      __snapshots__/prs-list-list--partially-loaded.png
  10. 14
      __snapshots__/prs-list-list.test.js.snap
  11. BIN
      __snapshots__/repo-summary-list--default.png
  12. 2
      src/lib/components/prs/PRsList.stories.svelte
  13. 11
      src/lib/components/prs/PRsList.svelte
  14. 4
      src/lib/components/prs/PRsListItem.stories.svelte
  15. 30
      src/lib/components/prs/PRsListItem.svelte
  16. 32
      src/lib/components/prs/type.ts
  17. 25
      src/lib/components/prs/vectors.ts
  18. 6
      src/lib/components/users/type.ts
  19. 100
      src/lib/stores/PRs.ts
  20. 40
      src/lib/wrappers/OpenPRs.svelte
  21. 6
      src/routes/repo/[repo_id]/+page.svelte

BIN
__snapshots__/navbar--default.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
__snapshots__/prs-list-item--author-loading.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
__snapshots__/prs-list-item--long-and-no-spaces.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

BIN
__snapshots__/prs-list-item--long-details.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

BIN
__snapshots__/prs-list-item--short-details.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

56
__snapshots__/prs-list-item.test.js.snap

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PRs/List/Item Long Details smoke-test 1`] = `
exports[`PRs/List/Item Author Loading smoke-test 1`] = `
<li class="flex p-2 pt-4 hover:bg-neutral-700 cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 16 16"
@ -11,21 +11,32 @@ exports[`PRs/List/Item Long Details smoke-test 1`] = ` @@ -11,21 +11,32 @@ exports[`PRs/List/Item Long Details smoke-test 1`] = `
</svg>
<div class="ml-3 overflow-hidden grow text-xs text-neutral-content">
<div class="text-sm text-base-content">
rather long title that goes on and on and on and on and on and on...
short title
</div>
<ul class="pt-2">
<li class="align-middle inline mr-3">
<svg xmlns="http://www.w3.org/2000/svg"
class="h-3 w-3 pt-0 flex-none fill-base-content inline-block"
viewbox="0 0 16 16"
>
<path d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z">
</path>
</svg>
1
</li>
<li class="inline mr-3">
opened a minute ago
opened 3 months ago
</li>
<li class="inline">
carole
<div class="skeleton h-3 pb-2 w-20 inline-block">
</div>
</li>
</ul>
</div>
</li>
`;
exports[`PRs/List/Item Long and No Spaces smoke-test 1`] = `
exports[`PRs/List/Item Long Details smoke-test 1`] = `
<li class="flex p-2 pt-4 hover:bg-neutral-700 cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 16 16"
@ -36,31 +47,21 @@ exports[`PRs/List/Item Long and No Spaces smoke-test 1`] = ` @@ -36,31 +47,21 @@ exports[`PRs/List/Item Long and No Spaces smoke-test 1`] = `
</svg>
<div class="ml-3 overflow-hidden grow text-xs text-neutral-content">
<div class="text-sm text-base-content">
LongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameL...
rather long title that goes on and on and on and on and on and on...
</div>
<ul class="pt-2">
<li class="align-middle inline mr-3">
<svg xmlns="http://www.w3.org/2000/svg"
class="h-3 w-3 pt-0 flex-none fill-base-content inline-block"
viewbox="0 0 16 16"
>
<path d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z">
</path>
</svg>
1
</li>
<li class="inline mr-3">
opened 3 months ago
opened a minute ago
</li>
<li class="inline">
steve
DanConwayDev
</li>
</ul>
</div>
</li>
`;
exports[`PRs/List/Item No Details smoke-test 1`] = `
exports[`PRs/List/Item Long and No Spaces smoke-test 1`] = `
<li class="flex p-2 pt-4 hover:bg-neutral-700 cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 16 16"
@ -71,13 +72,24 @@ exports[`PRs/List/Item No Details smoke-test 1`] = ` @@ -71,13 +72,24 @@ exports[`PRs/List/Item No Details smoke-test 1`] = `
</svg>
<div class="ml-3 overflow-hidden grow text-xs text-neutral-content">
<div class="text-sm text-base-content">
Untitled
LongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameL...
</div>
<ul class="pt-2">
<li class="align-middle inline mr-3">
<svg xmlns="http://www.w3.org/2000/svg"
class="h-3 w-3 pt-0 flex-none fill-base-content inline-block"
viewbox="0 0 16 16"
>
<path d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z">
</path>
</svg>
1
</li>
<li class="inline mr-3">
opened
opened 3 months ago
</li>
<li class="inline">
DanConwayDev
</li>
</ul>
</div>
@ -112,7 +124,7 @@ exports[`PRs/List/Item Short Details smoke-test 1`] = ` @@ -112,7 +124,7 @@ exports[`PRs/List/Item Short Details smoke-test 1`] = `
opened 7 days ago
</li>
<li class="inline">
fred
DanConwayDev
</li>
</ul>
</div>

BIN
__snapshots__/prs-list-list--default.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
__snapshots__/prs-list-list--no-title.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 19 KiB

BIN
__snapshots__/prs-list-list--partially-loaded.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 22 KiB

14
__snapshots__/prs-list-list.test.js.snap

@ -35,7 +35,7 @@ exports[`PRs/List/List Default smoke-test 1`] = ` @@ -35,7 +35,7 @@ exports[`PRs/List/List Default smoke-test 1`] = `
opened 7 days ago
</li>
<li class="inline">
fred
DanConwayDev
</li>
</ul>
</div>
@ -57,7 +57,7 @@ exports[`PRs/List/List Default smoke-test 1`] = ` @@ -57,7 +57,7 @@ exports[`PRs/List/List Default smoke-test 1`] = `
opened a minute ago
</li>
<li class="inline">
carole
DanConwayDev
</li>
</ul>
</div>
@ -89,7 +89,7 @@ exports[`PRs/List/List Default smoke-test 1`] = ` @@ -89,7 +89,7 @@ exports[`PRs/List/List Default smoke-test 1`] = `
opened 3 months ago
</li>
<li class="inline">
steve
DanConwayDev
</li>
</ul>
</div>
@ -185,7 +185,7 @@ exports[`PRs/List/List No Title smoke-test 1`] = ` @@ -185,7 +185,7 @@ exports[`PRs/List/List No Title smoke-test 1`] = `
opened 7 days ago
</li>
<li class="inline">
fred
DanConwayDev
</li>
</ul>
</div>
@ -207,7 +207,7 @@ exports[`PRs/List/List No Title smoke-test 1`] = ` @@ -207,7 +207,7 @@ exports[`PRs/List/List No Title smoke-test 1`] = `
opened a minute ago
</li>
<li class="inline">
carole
DanConwayDev
</li>
</ul>
</div>
@ -251,7 +251,7 @@ exports[`PRs/List/List Partially Loaded smoke-test 1`] = ` @@ -251,7 +251,7 @@ exports[`PRs/List/List Partially Loaded smoke-test 1`] = `
opened 7 days ago
</li>
<li class="inline">
fred
DanConwayDev
</li>
</ul>
</div>
@ -273,7 +273,7 @@ exports[`PRs/List/List Partially Loaded smoke-test 1`] = ` @@ -273,7 +273,7 @@ exports[`PRs/List/List Partially Loaded smoke-test 1`] = `
opened a minute ago
</li>
<li class="inline">
carole
DanConwayDev
</li>
</ul>
</div>

BIN
__snapshots__/repo-summary-list--default.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

2
src/lib/components/PRsList.stories.svelte → src/lib/components/prs/PRsList.stories.svelte

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
import type { Meta } from "@storybook/svelte";
import PRsList from "./PRsList.svelte";
import { Story, Template } from "@storybook/addon-svelte-csf";
import { PRsListItemArgsVectors as vectors } from "./PR.vectors";
import { PRsListItemArgsVectors as vectors } from "./vectors";
export const meta: Meta<PRsList> = {
title: "PRs/List/List",

11
src/lib/components/PRsList.svelte → src/lib/components/prs/PRsList.svelte

@ -2,12 +2,11 @@ @@ -2,12 +2,11 @@
import { fade } from "svelte/transition";
import { onMount } from "svelte";
import PRsListItem, {
type Args as PRsListItemArgs,
} from "$lib/components/PRsListItem.svelte";
import PRsListItem from "$lib/components/prs/PRsListItem.svelte";
import type { PRSummary } from "./type";
export let title: string = "";
export let prs: PRsListItemArgs[] = [];
export let prs: PRSummary[] = [];
export let loading: boolean = false;
</script>
@ -21,8 +20,8 @@ @@ -21,8 +20,8 @@
<p class="prose">None</p>
{/if}
<ul class=" divide-y divide-neutral-600">
{#each prs as { title, comments, author, created_at }}
<PRsListItem {title} {comments} {author} {created_at} />
{#each prs as pr}
<PRsListItem {...pr} />
{/each}
{#if loading}
<PRsListItem loading={true} />

4
src/lib/components/PRsListItem.stories.svelte → src/lib/components/prs/PRsListItem.stories.svelte

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
import type { Meta } from "@storybook/svelte";
import PRsListItem from "./PRsListItem.svelte";
import { Story, Template } from "@storybook/addon-svelte-csf";
import { PRsListItemArgsVectors as vectors } from "./PR.vectors";
import { PRsListItemArgsVectors as vectors } from "./vectors";
export const meta: Meta<PRsListItem> = {
title: "PRs/List/Item",
@ -21,6 +21,6 @@ @@ -21,6 +21,6 @@
<Story name="Long and No Spaces" args={vectors.LongNoSpaces} />
<Story name="No Details" args={{}} />
<Story name="Author Loading" args={vectors.AuthorLoading} />
<Story name="loading" args={{ loading: true }} />

30
src/lib/components/PRsListItem.svelte → src/lib/components/prs/PRsListItem.svelte

@ -1,36 +1,26 @@ @@ -1,36 +1,26 @@
<script lang="ts" context="module">
export interface Args {
title: string;
comments: number;
author: string;
created_at: number | undefined;
loading?: boolean;
}
export const defaults: Args = {
title: "",
comments: 0,
author: "",
created_at: 0,
loading: false,
};
</script>
<script lang="ts">
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { defaults } from "./type";
import { getName } from "../users/type";
dayjs.extend(relativeTime);
export let { title, comments, author, created_at, loading } = defaults;
export let { title, id, comments, author, created_at, loading } = defaults;
let short_title: string;
let created_at_ago: string;
let author_name = "";
$: {
author_name = getName(author);
}
$: {
if (title.length > 70) short_title = title.slice(0, 65) + "...";
else if (title.length == 0) short_title = "Untitled";
else short_title = title;
created_at_ago = created_at ? dayjs(created_at * 1000).fromNow() : "";
}
$: {
}
</script>
<li
@ -92,7 +82,11 @@ @@ -92,7 +82,11 @@
opened {created_at_ago}
</li>
<li class="inline">
{author}
{#if author.loading}
<div class="skeleton h-3 pb-2 w-20 inline-block"></div>
{:else}
{author_name}
{/if}
</li>
</ul>
{/if}

32
src/lib/components/prs/type.ts

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
import type { User } from "../users/type";
import { defaults as user_defaults } from "../users/type";
export interface PRSummary {
title: string;
id: string;
comments: number;
author: User;
created_at: number | undefined;
loading: boolean;
}
export const defaults: PRSummary = {
title: "",
id: "",
comments: 0,
author: { ...user_defaults },
created_at: 0,
loading: true,
};
export interface PRSummaries {
id: string;
summaries: PRSummary[];
loading: boolean;
}
export const summaries_defaults: PRSummaries = {
id: "",
summaries: [],
loading: true,
};

25
src/lib/components/PR.vectors.ts → src/lib/components/prs/vectors.ts

@ -1,26 +1,37 @@ @@ -1,26 +1,37 @@
import type { Args as PRListItemArgs } from "./PRsListItem.svelte";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import type { PRSummary } from "./type";
import { UserVectors } from "../users/vectors";
dayjs.extend(relativeTime);
export let PRsListItemArgsVectors = {
Short: {
title: "short title",
author: "fred",
author: { ...UserVectors.default },
created_at: dayjs().subtract(7, 'days').unix(),
comments: 2,
} as PRListItemArgs,
loading: false,
} as PRSummary,
Long: {
title: "rather long title that goes on and on and on and on and on and on and on and on and on and on and on and on and on and on and on",
author: "carole",
author: { ...UserVectors.default },
created_at: dayjs().subtract(1, 'minute').unix(),
comments: 0,
} as PRListItemArgs,
loading: false,
} as PRSummary,
LongNoSpaces: {
title: "LongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameLongName",
author: "steve",
author: { ...UserVectors.default },
created_at: dayjs().subtract(3, 'month').subtract(3, 'days').unix(),
comments: 1,
} as PRListItemArgs,
loading: false,
} as PRSummary,
AuthorLoading: {
title: "short title",
author: { ...UserVectors.loading },
created_at: dayjs().subtract(3, 'month').subtract(3, 'days').unix(),
comments: 1,
loading: false,
} as PRSummary,
};

6
src/lib/components/users/type.ts

@ -7,6 +7,12 @@ export interface User { @@ -7,6 +7,12 @@ export interface User {
profile?: NDKUserProfile;
}
export let defaults: User = {
loading: true,
hexpubkey: "",
npub: "",
}
export function getName(user: User, fallback_to_pubkey: boolean = false): string {
return user.profile ? (
user.profile.name

100
src/lib/stores/PRs.ts

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
import type { NDKEvent } from "@nostr-dev-kit/ndk";
import { writable, type Unsubscriber, type Writable } from "svelte/store"
import { ndk } from "./ndk";
import type { Repo } from "$lib/components/repo/type";
import { defaults } from "$lib/components/prs/type";
import type { User } from "$lib/components/users/type";
import { ensureUser, users } from "./users";
import type { PRSummaries, PRSummary } from "$lib/components/prs/type";
export let pr_summaries: Writable<PRSummaries> = writable({
id: "",
summaries: [],
loading: false,
});
let pr_kind: number = 318;
let selected_repo_id: string = "";
let authors_unsubscribers: Unsubscriber[] = [];
export let ensurePRSummaries = (repo_id: string) => {
if (selected_repo_id == repo_id) return;
if (repo_id == "") return pr_summaries.set({
id: "",
summaries: [],
loading: false,
});
selected_repo_id = repo_id;
pr_summaries.update(prs => {
return {
...prs,
id: repo_id,
loading: true,
};
});
authors_unsubscribers.forEach(u => u());
authors_unsubscribers = [];
let sub = ndk.subscribe({
kinds: [pr_kind],
'#r': [`r-${repo_id}`],
limit: 50,
});
sub.on("event", (event: NDKEvent) => {
try {
if (event.kind == pr_kind
&& event.getMatchingTags("r").find(t => t[1] === `r-${repo_id}`)
) {
console.log(event);
pr_summaries.update(prs => {
return {
...prs,
summaries: [
...prs.summaries,
{
...defaults,
id: event.id,
title: event.tagValue("name") || "",
created_at: event.created_at,
comments: 0,
author: {
hexpubkey: event.pubkey,
loading: true,
npub: "",
},
loading: false,
}
],
}
});
authors_unsubscribers.push(
ensureUser(event.pubkey).subscribe((u: User) => {
pr_summaries.update(prs => {
console.log('test');
return {
...prs,
summaries: prs.summaries.map(o => ({
...o,
author: u,
})),
}
});
})
);
}
} catch { }
});
sub.on("eose", () => {
pr_summaries.update(prs => {
return {
...prs,
loading: false,
};
});
});
}

40
src/lib/wrappers/OpenPRs.svelte

@ -1,38 +1,14 @@ @@ -1,38 +1,14 @@
<script lang="ts">
import PRsList from "$lib/components/PRsList.svelte";
import type { Args } from "$lib/components/PRsListItem.svelte";
import { ndk } from "$lib/stores/ndk";
import PRsList from "$lib/components/prs/PRsList.svelte";
import { ensurePRSummaries, pr_summaries } from "$lib/stores/PRs";
export let limit: number = 100;
let prs: Args[] = [];
export let loading: boolean = true;
let repo_kind: number = 30317;
let pr_kind: number = 318;
export let repo_id: string = "";
let sub = ndk.subscribe({
kinds: [pr_kind],
"#d": [repo_id],
limit,
});
sub.on("event", (event) => {
if (prs.length < limit) {
if (event.kind == pr_kind)
prs = [
...prs,
{
title: event.tagValue("name") || "",
author: event.pubkey,
created_at: event.created_at,
comments: 1,
},
];
} else if (loading == true) loading = false;
});
sub.on("eose", () => {
if (loading == true) loading = false;
});
ensurePRSummaries(repo_id);
</script>
<PRsList title="Open PRs" {prs} {loading} />
<PRsList
title="Open PRs"
prs={$pr_summaries.summaries}
loading={$pr_summaries.loading}
/>

6
src/routes/repo/[repo_id]/+page.svelte

@ -9,12 +9,12 @@ @@ -9,12 +9,12 @@
ensureSelectedRepo(repo_id);
</script>
<h1>{$selected_repo.name}</h1>
<h1 class="mx-2 my-4">{$selected_repo.name}</h1>
<div class="flex">
<div class="w-2/3">
<div class="w-2/3 mx-2">
<OpenPRs {repo_id} />
</div>
<div class="w-1/3 prose">
<div class="w-1/3 mx-2 prose">
<RepoDetails {repo_id} />
</div>
</div>

Loading…
Cancel
Save