Browse Source

feat: add UserHeader

add user profile details via a svelte store

this sets a standard for abstracting ui from data wrappers even when
multiple calls are needed
master
DanConwayDev 2 years ago
parent
commit
4fc877bd3e
No known key found for this signature in database
GPG Key ID: 68E15486D73F75E1
  1. 1
      .storybook/main.ts
  2. BIN
      .storybook/test-assets/test-profile-image.jpg
  3. BIN
      __snapshots__/repo-details--long-and-no-spaces.png
  4. BIN
      __snapshots__/repo-details--long-details.png
  5. BIN
      __snapshots__/repo-details--no-description.png
  6. BIN
      __snapshots__/repo-details--no-name-or-description.png
  7. BIN
      __snapshots__/repo-details--no-relays.png
  8. BIN
      __snapshots__/repo-details--no-tags.png
  9. BIN
      __snapshots__/repo-details--one-maintainer-s-profile-has-no-display-name-or-name.png
  10. BIN
      __snapshots__/repo-details--one-maintainer-s-profile-not-loaded.png
  11. BIN
      __snapshots__/repo-details--one-maintainer-s-profile-only-has-display-name-but-no-name.png
  12. 322
      __snapshots__/repo-details.test.js.snap
  13. BIN
      __snapshots__/users-header--default-5-c-13-d-641.png
  14. BIN
      __snapshots__/users-header--display-name-without-name.png
  15. BIN
      __snapshots__/users-header--loading.png
  16. BIN
      __snapshots__/users-header--name-and-display-name-shows-name.png
  17. BIN
      __snapshots__/users-header--no-image.png
  18. BIN
      __snapshots__/users-header--not-found.png
  19. 86
      __snapshots__/users-header.test.js.snap
  20. 2
      src/lib/components/RepoSummaryCard.stories.svelte
  21. 2
      src/lib/components/ReposSummaryList.stories.svelte
  22. 2
      src/lib/components/repo/RepoDetails.stories.svelte
  23. 26
      src/lib/components/repo/RepoDetails.svelte
  24. 22
      src/lib/components/repo/type.ts
  25. 37
      src/lib/components/repo/vectors.ts
  26. 2
      src/lib/components/users/UserHeader.stories.svelte
  27. 1
      src/lib/components/users/UserHeader.svelte
  28. 2
      src/lib/components/users/vectors.ts
  29. 76
      src/lib/stores/repo.ts
  30. 36
      src/lib/stores/users.ts
  31. 37
      src/lib/wrappers/RepoDetails.svelte
  32. 4
      src/routes/repo/[repo_id]/+page.svelte

1
.storybook/main.ts

@ -13,6 +13,7 @@ const config: StorybookConfig = { @@ -13,6 +13,7 @@ const config: StorybookConfig = {
name: "@storybook/sveltekit",
options: {},
},
staticDirs: ['test-assets'],
docs: {
autodocs: "tag",
},

BIN
.storybook/test-assets/test-profile-image.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
__snapshots__/repo-details--long-and-no-spaces.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 54 KiB

BIN
__snapshots__/repo-details--long-details.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 66 KiB

BIN
__snapshots__/repo-details--no-description.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
__snapshots__/repo-details--no-name-or-description.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
__snapshots__/repo-details--no-relays.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 27 KiB

BIN
__snapshots__/repo-details--no-tags.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 31 KiB

BIN
__snapshots__/repo-details--one-maintainer-s-profile-has-no-display-name-or-name.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 35 KiB

BIN
__snapshots__/repo-details--one-maintainer-s-profile-not-loaded.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 33 KiB

BIN
__snapshots__/repo-details--one-maintainer-s-profile-only-has-display-name-but-no-name.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 38 KiB

322
__snapshots__/repo-details.test.js.snap

@ -27,16 +27,46 @@ exports[`Repo/Details Long Details smoke-test 1`] = ` @@ -27,16 +27,46 @@ exports[`Repo/Details Long Details smoke-test 1`] = `
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="bob"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
bob
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<h4>
relays
@ -80,16 +110,46 @@ exports[`Repo/Details Long and No Spaces smoke-test 1`] = ` @@ -80,16 +110,46 @@ exports[`Repo/Details Long and No Spaces smoke-test 1`] = `
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="bob"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
bob
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<h4>
relays
@ -129,16 +189,46 @@ exports[`Repo/Details No Description smoke-test 1`] = ` @@ -129,16 +189,46 @@ exports[`Repo/Details No Description smoke-test 1`] = `
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="bob"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
bob
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<h4>
relays
@ -254,16 +344,46 @@ exports[`Repo/Details No Name or Description smoke-test 1`] = ` @@ -254,16 +344,46 @@ exports[`Repo/Details No Name or Description smoke-test 1`] = `
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="bob"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
bob
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<h4>
relays
@ -307,16 +427,46 @@ exports[`Repo/Details No Relays smoke-test 1`] = ` @@ -307,16 +427,46 @@ exports[`Repo/Details No Relays smoke-test 1`] = `
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="bob"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
bob
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<div>
</div>
@ -338,16 +488,46 @@ exports[`Repo/Details No Tags smoke-test 1`] = ` @@ -338,16 +488,46 @@ exports[`Repo/Details No Tags smoke-test 1`] = `
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="bob"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
bob
</div>
<div class="badge badge-accent block my-2">
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<h4>
relays
@ -391,16 +571,42 @@ exports[`Repo/Details One Maintainer's Profile Has No displayName or Name smoke- @@ -391,16 +571,42 @@ exports[`Repo/Details One Maintainer's Profile Has No displayName or Name smoke-
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge badge-neutral block my-2">
cannot find name
</div>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded bg-neutral">
</div>
</div>
<div class="flex-auto pl-3 m-auto">
npub18669...
</div>
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<h4>
relays
@ -444,15 +650,43 @@ exports[`Repo/Details One Maintainer's Profile Not Loaded smoke-test 1`] = ` @@ -444,15 +650,43 @@ exports[`Repo/Details One Maintainer's Profile Not Loaded smoke-test 1`] = `
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge skeleton my-2 w-40 block">
</div>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded skeleton">
</div>
</div>
<div class="flex-auto pl-3 m-auto">
<div class="w-24 h-4 skeleton">
</div>
</div>
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<h4>
relays
@ -496,16 +730,46 @@ exports[`Repo/Details One Maintainer's Profile Only Has displayName But No Name @@ -496,16 +730,46 @@ exports[`Repo/Details One Maintainer's Profile Only Has displayName But No Name
<h4>
maintainers
</h4>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="carole"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
carole
</div>
<div class="badge badge-accent block my-2">
bob
</div>
<div class="badge badge-accent block my-2">
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="DanConwayDev"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
DanConwayDev
</div>
</div>
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="steve"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
steve
</div>
</div>
</div>
<div>
<h4>
relays

BIN
__snapshots__/users-header--default-5-c-13-d-641.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
__snapshots__/users-header--display-name-without-name.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
__snapshots__/users-header--loading.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
__snapshots__/users-header--name-and-display-name-shows-name.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
__snapshots__/users-header--no-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
__snapshots__/users-header--not-found.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

86
__snapshots__/users-header.test.js.snap

@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Users/Header default smoke-test 1`] = `
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="DanConwayDev"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
DanConwayDev
</div>
</div>
`;
exports[`Users/Header displayName without name smoke-test 1`] = `
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="DanConwayDev"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
DanConwayDev
</div>
</div>
`;
exports[`Users/Header loading smoke-test 1`] = `
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded skeleton">
</div>
</div>
<div class="flex-auto pl-3 m-auto">
<div class="w-24 h-4 skeleton">
</div>
</div>
</div>
`;
exports[`Users/Header name and displayName shows name smoke-test 1`] = `
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded">
<img class="my-0"
src="../test-profile-image.jpg"
alt="Dan"
>
</div>
</div>
<div class="flex-auto pl-3 m-auto">
Dan
</div>
</div>
`;
exports[`Users/Header no image smoke-test 1`] = `
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded bg-neutral">
</div>
</div>
<div class="flex-auto pl-3 m-auto">
DanConwayDev
</div>
</div>
`;
exports[`Users/Header not found smoke-test 1`] = `
<div class="flex my-2">
<div class="avatar flex-none">
<div class="w-8 h-8 rounded bg-neutral">
</div>
</div>
<div class="flex-auto pl-3 m-auto">
npub18669...
</div>
</div>
`;

2
src/lib/components/RepoSummaryCard.stories.svelte

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
import type { Meta } from "@storybook/svelte";
import RepoSummaryCard from "./RepoSummaryCard.svelte";
import { Story, Template } from "@storybook/addon-svelte-csf";
import { RepoSummaryCardArgsVectors as vectors } from "./Repo.vectors";
import { RepoSummaryCardArgsVectors as vectors } from "./repo/vectors";
export const meta: Meta<RepoSummaryCard> = {
title: "Repo/Summary/Card",

2
src/lib/components/ReposSummaryList.stories.svelte

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
import type { Meta } from "@storybook/svelte";
import ReposSummaryList from "./ReposSummaryList.svelte";
import { Story, Template } from "@storybook/addon-svelte-csf";
import { RepoSummaryCardArgsVectors as vectors } from "./Repo.vectors";
import { RepoSummaryCardArgsVectors as vectors } from "./repo/vectors";
export const meta: Meta<ReposSummaryList> = {
title: "Repo/Summary/List",

2
src/lib/components/RepoDetails.stories.svelte → src/lib/components/repo/RepoDetails.stories.svelte

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
import type { Meta } from "@storybook/svelte";
import RepoDetails from "./RepoDetails.svelte";
import { Story, Template } from "@storybook/addon-svelte-csf";
import { RepoDetailsArgsVectors as vectors } from "./Repo.vectors";
import { RepoDetailsArgsVectors as vectors } from "./vectors";
export const meta: Meta<RepoDetails> = {
title: "Repo/Details",

26
src/lib/components/RepoDetails.svelte → src/lib/components/repo/RepoDetails.svelte

@ -1,31 +1,11 @@ @@ -1,31 +1,11 @@
<script lang="ts" context="module">
import type { NDKUserProfile } from "@nostr-dev-kit/ndk";
export interface Args {
repo_id: string;
name: string;
description: string;
git_server: string;
tags: string[];
maintainers: User[];
relays: string[];
loading?: boolean;
}
export const defaults: Args = {
repo_id: "",
name: "",
description: "",
git_server: "",
tags: [],
maintainers: [],
relays: [],
loading: true,
};
</script>
<script lang="ts">
import type { User } from "./users/type";
import UserHeader from "./users/UserHeader.svelte";
import type { User } from "$lib/components/users/type";
import UserHeader from "$lib/components/users/UserHeader.svelte";
import { defaults } from "./type";
export let {
repo_id,

22
src/lib/components/repo/type.ts

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
import type { User } from "../users/type";
export interface Repo {
repo_id: string;
name: string;
description: string;
git_server: string;
tags: string[];
maintainers: User[];
relays: string[];
loading: boolean;
}
export const defaults: Repo = {
repo_id: "",
name: "",
description: "",
git_server: "",
tags: [],
maintainers: [],
relays: [],
loading: true,
};

37
src/lib/components/Repo.vectors.ts → src/lib/components/repo/vectors.ts

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
import type { Args as SummaryCardArgs } from "./RepoSummaryCard.svelte";
import type { Args as DetailsArgs } from "./RepoDetails.svelte";
import type { Args as SummaryCardArgs } from "../RepoSummaryCard.svelte";
import type { NDKUserProfile } from "@nostr-dev-kit/ndk";
import type { User } from "./users/type";
import { UserVectors, withName } from "./users/vectors";
import type { User } from "../users/type";
import { UserVectors, withName } from "../users/vectors";
import type { Repo } from "./type";
export let RepoSummaryCardArgsVectors = {
Short: {
@ -20,7 +20,7 @@ export let RepoSummaryCardArgsVectors = { @@ -20,7 +20,7 @@ export let RepoSummaryCardArgsVectors = {
"LoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsum>",
} as SummaryCardArgs,
};
let base: DetailsArgs = {
let base: Repo = {
repo_id: "9ee507fc4357d7ee16a5d8901bedcd103f23c17d",
name: "Short Name",
description: "short description",
@ -36,46 +36,47 @@ let base: DetailsArgs = { @@ -36,46 +36,47 @@ let base: DetailsArgs = {
withName(UserVectors.default, "bob"),
withName(UserVectors.default, "steve"),
],
loading: false,
};
export let RepoDetailsArgsVectors = {
Short: { ...base, } as DetailsArgs,
Short: { ...base, } as Repo,
Long: {
...base,
name: "Long Name that goes on and on and on and on and on and on and on and on and on",
description:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis nisl eget turpis congue molestie. Nulla vitae purus nec augue accumsan facilisis sed sed ligula. Vestibulum sed risus lacinia risus lacinia molestie. Ut lorem quam, consequat eget tempus in, rhoncus vel nunc. Duis efficitur a leo vel sodales. Nam id fermentum lacus. Etiam nec placerat velit. Praesent ac consectetur est. Aenean iaculis commodo enim.\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis quis nisl eget turpis congue molestie.",
} as DetailsArgs,
} as Repo,
LongNoSpaces: {
...base,
name: "LongNameLongNameLongNameLongNameLongNameLongNameLongNameLongName",
description:
"LoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsumLoremipsum",
} as DetailsArgs,
NoNameOrDescription: { ...base, name: "", description: "" } as DetailsArgs,
NoDescription: { ...base, description: "" } as DetailsArgs,
NoTags: { ...base, tags: [] } as DetailsArgs,
} as Repo,
NoNameOrDescription: { ...base, name: "", description: "" } as Repo,
NoDescription: { ...base, description: "" } as Repo,
NoTags: { ...base, tags: [] } as Repo,
MaintainersOneProfileNotLoaded: {
...base, maintainers: [
{ ...base.maintainers[0] },
{ ...UserVectors.loading },
{ ...base.maintainers[2] },
]
} as DetailsArgs,
} as Repo,
MaintainersOneProfileDisplayNameWithoutName: {
...base, maintainers: [
{ ...base.maintainers[0] },
{ ...UserVectors.display_name_only },
{ ...base.maintainers[2] },
]
} as DetailsArgs,
} as Repo,
MaintainersOneProfileNameAndDisplayNamePresent: {
...base, maintainers: [
{ ...base.maintainers[0] },
{ ...UserVectors.display_name_and_name },
{ ...base.maintainers[2] },
]
} as DetailsArgs,
} as Repo,
MaintainersOneProfileNoNameOrDisplayNameBeingPresent: {
...base, maintainers: [
{ ...base.maintainers[0] },
@ -83,8 +84,8 @@ export let RepoDetailsArgsVectors = { @@ -83,8 +84,8 @@ export let RepoDetailsArgsVectors = {
{ ...base.maintainers[2] },
]
} as DetailsArgs,
NoMaintainers: { ...base, maintainers: [] } as DetailsArgs,
NoRelays: { ...base, relays: [] } as DetailsArgs,
NoMaintainersOrRelays: { ...base, maintainers: [], relays: [] } as DetailsArgs,
} as Repo,
NoMaintainers: { ...base, maintainers: [] } as Repo,
NoRelays: { ...base, relays: [] } as Repo,
NoMaintainersOrRelays: { ...base, maintainers: [], relays: [] } as Repo,
};

2
src/lib/components/users/UserHeader.stories.svelte

@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
<Story
name="displayName without name"
args={{ user: { ...vectors.no_profile } }}
args={{ user: { ...vectors.display_name_only } }}
/>
<Story

1
src/lib/components/users/UserHeader.svelte

@ -7,7 +7,6 @@ @@ -7,7 +7,6 @@
</script>
<script lang="ts">
import Name from "./Name.svelte";
import { getName, type User } from "./type";
export let user: User = defaults;

2
src/lib/components/users/vectors.ts

@ -8,7 +8,7 @@ let base: User = { @@ -8,7 +8,7 @@ let base: User = {
loading: false,
};
let image = "https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg";
let image = "../test-profile-image.jpg";
export let UserVectors = {
loading: { ...base, loading: true } as User,

76
src/lib/stores/repo.ts

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
import { NDKUser } 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/repo/type";
import type { User } from "$lib/components/users/type";
import { ensureUser, users } from "./users";
let repo_kind: number = 30317;
export let selected_repo: Writable<Repo> = writable({ ...defaults });
let selected_repo_id: string = "";
let maintainers_unsubscribers: Unsubscriber[] = [];
export let ensureSelectedRepo = (repo_id: string) => {
if (selected_repo_id == repo_id) return selected_repo;
selected_repo_id = repo_id;
let sub = ndk.subscribe({
kinds: [repo_kind],
'#d': [repo_id],
limit: 1,
});
sub.on("event", (event) => {
try {
if (event.kind == repo_kind && event.tagValue("d") == repo_id) {
selected_repo.set({
loading: false,
repo_id: event.replaceableDTag(),
name: event.tagValue("name") || "",
description: event.tagValue("description") || "",
git_server: event.tagValue("git_server") || "",
tags: event.getMatchingTags("t") || [],
maintainers: event.getMatchingTags("p").map(
(t: string[]) =>
({
hexpubkey: t[1],
loading: true,
npub: "",
}) as User,
),
relays: event
.getMatchingTags("relay")
.map((t: string[]) => t[1]),
});
let old_unsubscribers = maintainers_unsubscribers;
maintainers_unsubscribers = event
.getMatchingTags("p")
.map((t: string[]) => {
return ensureUser(t[1]).subscribe((u: User) => {
selected_repo.update((repo) => {
return {
...repo,
maintainers: repo.maintainers.map((m) => {
if (m.hexpubkey == u.hexpubkey) return { ...u };
else return { ...m };
}),
};
});
})
});
old_unsubscribers.forEach((unsubscriber) => unsubscriber());
}
} catch { }
});
sub.on("eose", () => {
selected_repo.update((repo) => {
return {
...repo,
loading: false,
}
})
});
}

36
src/lib/stores/users.ts

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
import type { User } from "$lib/components/users/type";
import { NDKUser } from "@nostr-dev-kit/ndk";
import { writable, type Writable } from "svelte/store"
import { ndk } from "./ndk";
export let users: { [hexpubkey: string]: Writable<User>; } = {};
export let ensureUser = (hexpubkey: string): Writable<User> => {
if (!users[hexpubkey]) {
let u = ndk.getUser({ hexpubkey });
let base: User = {
loading: false,
hexpubkey,
npub: u.npub,
};
users[hexpubkey] = writable(base);
u.fetchProfile().then(
(p) => {
users[hexpubkey].update((u) => ({
...u,
loading: false,
profile: p === null ? undefined : p,
}));
},
() => {
users[hexpubkey].update((u) => ({
...u,
loading: false,
}));
}
);
}
return users[hexpubkey];
}

37
src/lib/wrappers/RepoDetails.svelte

@ -1,39 +1,10 @@ @@ -1,39 +1,10 @@
<script lang="ts">
import type { Args } from "$lib/components/RepoDetails.svelte";
import { defaults } from "$lib/components/RepoDetails.svelte";
import RepoDetails from "$lib/components/RepoDetails.svelte";
import { ndk } from "$lib/stores/ndk";
import RepoDetails from "$lib/components/repo/RepoDetails.svelte";
import { ensureSelectedRepo, selected_repo } from "$lib/stores/repo";
export let repo_id = "";
let repo: Args = { ...defaults };
let loading: boolean = true;
let kind: number = 30317;
let sub = ndk.subscribe({
kinds: [kind],
limit: 1,
});
sub.on("event", (event) => {
try {
if (event.kind == kind && event.tagValue("d") == repo_id)
repo = {
repo_id: event.replaceableDTag(),
name: event.tagValue("name") || "",
description: event.tagValue("description") || "",
git_server: event.tagValue("git_server") || "",
tags: event.getMatchingTags("t") || [],
maintainers: event
.getMatchingTags("p")
.map((t: string[]) => t[1]),
relays: event
.getMatchingTags("relay")
.map((t: string[]) => t[1]),
};
} catch {}
});
sub.on("eose", () => {
if (loading == true) loading = false;
});
ensureSelectedRepo(repo_id);
</script>
<RepoDetails {...repo} {loading} />
<RepoDetails {...$selected_repo} />

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

@ -1,11 +1,15 @@ @@ -1,11 +1,15 @@
<script lang="ts">
import RepoDetails from "$lib/wrappers/RepoDetails.svelte";
import OpenPRs from "$lib/wrappers/OpenPRs.svelte";
import { ensureSelectedRepo, selected_repo } from "$lib/stores/repo";
export let data: { repo_id: string };
let repo_id = data.repo_id;
ensureSelectedRepo(repo_id);
</script>
<h1>{$selected_repo.name}</h1>
<div class="flex">
<div class="w-2/3">
<OpenPRs {repo_id} />

Loading…
Cancel
Save