16 changed files with 422 additions and 39 deletions
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,123 @@ |
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||||
|
|
||||||
|
exports[`PRs/Header Author Loading smoke-test 1`] = ` |
||||||
|
<div class="overflow-hidden grow text-xs text-neutral-content bg-base-200 border-b border-accent-content pt-2 pb-4 px-3"> |
||||||
|
<div class="text-lg text-base-content mb-2"> |
||||||
|
short title |
||||||
|
</div> |
||||||
|
<div class="pt-1"> |
||||||
|
<button class="btn btn-success btn-sm mr-3 align-middle"> |
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" |
||||||
|
viewbox="0 0 18 18" |
||||||
|
class="h-5 w-5 pt-1 flex-none fill-success-content" |
||||||
|
> |
||||||
|
<path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25m5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354M3.75 2.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m0 9.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m8.25.75a.75.75 0 1 0 1.5 0a.75.75 0 0 0-1.5 0"> |
||||||
|
</path> |
||||||
|
</svg> |
||||||
|
Open |
||||||
|
</button> |
||||||
|
<div class="inline mr-3 align-middle"> |
||||||
|
opened 3 months ago |
||||||
|
</div> |
||||||
|
<div class="inline align-middle"> |
||||||
|
<div class="skeleton h-3 pb-2 w-20 inline-block"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`PRs/Header Long Details smoke-test 1`] = ` |
||||||
|
<div class="overflow-hidden grow text-xs text-neutral-content bg-base-200 border-b border-accent-content pt-2 pb-4 px-3"> |
||||||
|
<div class="text-lg text-base-content mb-2"> |
||||||
|
rather long title that goes on and on and on and on and on and on... |
||||||
|
</div> |
||||||
|
<div class="pt-1"> |
||||||
|
<button class="btn btn-success btn-sm mr-3 align-middle"> |
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" |
||||||
|
viewbox="0 0 18 18" |
||||||
|
class="h-5 w-5 pt-1 flex-none fill-success-content" |
||||||
|
> |
||||||
|
<path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25m5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354M3.75 2.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m0 9.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m8.25.75a.75.75 0 1 0 1.5 0a.75.75 0 0 0-1.5 0"> |
||||||
|
</path> |
||||||
|
</svg> |
||||||
|
Open |
||||||
|
</button> |
||||||
|
<div class="inline mr-3 align-middle"> |
||||||
|
opened a minute ago |
||||||
|
</div> |
||||||
|
<div class="inline align-middle"> |
||||||
|
DanConwayDev |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`PRs/Header Long and No Spaces smoke-test 1`] = ` |
||||||
|
<div class="overflow-hidden grow text-xs text-neutral-content bg-base-200 border-b border-accent-content pt-2 pb-4 px-3"> |
||||||
|
<div class="text-lg text-base-content mb-2"> |
||||||
|
LongNameLongNameLongNameLongNameLongNameLongNameLongNameLongNameL... |
||||||
|
</div> |
||||||
|
<div class="pt-1"> |
||||||
|
<button class="btn btn-success btn-sm mr-3 align-middle"> |
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" |
||||||
|
viewbox="0 0 18 18" |
||||||
|
class="h-5 w-5 pt-1 flex-none fill-success-content" |
||||||
|
> |
||||||
|
<path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25m5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354M3.75 2.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m0 9.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m8.25.75a.75.75 0 1 0 1.5 0a.75.75 0 0 0-1.5 0"> |
||||||
|
</path> |
||||||
|
</svg> |
||||||
|
Open |
||||||
|
</button> |
||||||
|
<div class="inline mr-3 align-middle"> |
||||||
|
opened 3 months ago |
||||||
|
</div> |
||||||
|
<div class="inline align-middle"> |
||||||
|
DanConwayDev |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`PRs/Header Short Details smoke-test 1`] = ` |
||||||
|
<div class="overflow-hidden grow text-xs text-neutral-content bg-base-200 border-b border-accent-content pt-2 pb-4 px-3"> |
||||||
|
<div class="text-lg text-base-content mb-2"> |
||||||
|
short title |
||||||
|
</div> |
||||||
|
<div class="pt-1"> |
||||||
|
<button class="btn btn-success btn-sm mr-3 align-middle"> |
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" |
||||||
|
viewbox="0 0 18 18" |
||||||
|
class="h-5 w-5 pt-1 flex-none fill-success-content" |
||||||
|
> |
||||||
|
<path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25m5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354M3.75 2.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m0 9.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m8.25.75a.75.75 0 1 0 1.5 0a.75.75 0 0 0-1.5 0"> |
||||||
|
</path> |
||||||
|
</svg> |
||||||
|
Open |
||||||
|
</button> |
||||||
|
<div class="inline mr-3 align-middle"> |
||||||
|
opened 7 days ago |
||||||
|
</div> |
||||||
|
<div class="inline align-middle"> |
||||||
|
DanConwayDev |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`PRs/Header loading smoke-test 1`] = ` |
||||||
|
<div class="overflow-hidden grow text-xs text-neutral-content bg-base-200 border-b border-accent-content pt-2 pb-4 px-3"> |
||||||
|
<div> |
||||||
|
<div class="h-7 w-60 pt-1 skeleton"> |
||||||
|
</div> |
||||||
|
<div class> |
||||||
|
<div class="h-8 w-20 mt-3 skeleton align-middle inline-block"> |
||||||
|
</div> |
||||||
|
<div class="h-3 w-28 ml-3 mt-5 align-middle skeleton inline-block"> |
||||||
|
</div> |
||||||
|
<div class="h-3 w-28 ml-3 mt-5 align-middle skeleton inline-block"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
<script lang="ts" context="module"> |
||||||
|
import type { Meta } from "@storybook/svelte"; |
||||||
|
import PRHeader from "./PRHeader.svelte"; |
||||||
|
import { Story, Template } from "@storybook/addon-svelte-csf"; |
||||||
|
import { PRsListItemArgsVectors as vectors } from "./vectors"; |
||||||
|
|
||||||
|
export const meta: Meta<PRHeader> = { |
||||||
|
title: "PRs/Header", |
||||||
|
component: PRHeader, |
||||||
|
tags: ["autodocs"], |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<Template let:args> |
||||||
|
<PRHeader {...args} /> |
||||||
|
</Template> |
||||||
|
|
||||||
|
<Story name="Short Details" args={vectors.Short} /> |
||||||
|
|
||||||
|
<Story name="Long Details" args={vectors.Long} /> |
||||||
|
|
||||||
|
<Story name="Long and No Spaces" args={vectors.LongNoSpaces} /> |
||||||
|
|
||||||
|
<Story name="Author Loading" args={vectors.AuthorLoading} /> |
||||||
|
|
||||||
|
<Story name="loading" args={{ loading: true }} /> |
||||||
@ -0,0 +1,73 @@ |
|||||||
|
<script lang="ts" context="module"> |
||||||
|
</script> |
||||||
|
|
||||||
|
<script lang="ts"> |
||||||
|
import dayjs from "dayjs"; |
||||||
|
import relativeTime from "dayjs/plugin/relativeTime"; |
||||||
|
import { summary_defaults } from "./type"; |
||||||
|
import { getName } from "../users/type"; |
||||||
|
|
||||||
|
dayjs.extend(relativeTime); |
||||||
|
export let { title, id, repo_id, comments, author, created_at, loading } = |
||||||
|
summary_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> |
||||||
|
|
||||||
|
<div |
||||||
|
class="overflow-hidden grow text-xs text-neutral-content bg-base-200 border-b border-accent-content pt-2 pb-4 px-3" |
||||||
|
> |
||||||
|
{#if loading} |
||||||
|
<div> |
||||||
|
<div class="h-7 w-60 pt-1 skeleton"></div> |
||||||
|
<div class=""> |
||||||
|
<div |
||||||
|
class="h-8 w-20 mt-3 skeleton align-middle inline-block" |
||||||
|
></div> |
||||||
|
<div |
||||||
|
class="h-3 w-28 ml-3 mt-5 align-middle skeleton inline-block" |
||||||
|
></div> |
||||||
|
<div |
||||||
|
class="h-3 w-28 ml-3 mt-5 align-middle skeleton inline-block" |
||||||
|
></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{:else} |
||||||
|
<div class="text-lg text-base-content mb-2"> |
||||||
|
{short_title} |
||||||
|
</div> |
||||||
|
<div class="pt-1"> |
||||||
|
<button class="btn btn-success btn-sm mr-3 align-middle"> |
||||||
|
<svg |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
viewBox="0 0 18 18" |
||||||
|
class="h-5 w-5 pt-1 flex-none fill-success-content" |
||||||
|
><path |
||||||
|
d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25m5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354M3.75 2.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m0 9.5a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5m8.25.75a.75.75 0 1 0 1.5 0a.75.75 0 0 0-1.5 0" |
||||||
|
/> |
||||||
|
</svg> |
||||||
|
Open |
||||||
|
</button> |
||||||
|
<div class="inline mr-3 align-middle"> |
||||||
|
opened {created_at_ago} |
||||||
|
</div> |
||||||
|
<div class="inline align-middle"> |
||||||
|
{#if author.loading} |
||||||
|
<div class="skeleton h-3 pb-2 w-20 inline-block"></div> |
||||||
|
{:else} |
||||||
|
{author_name} |
||||||
|
{/if} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{/if} |
||||||
|
</div> |
||||||
@ -0,0 +1,86 @@ |
|||||||
|
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/repo/type"; |
||||||
|
import type { User } from "$lib/components/users/type"; |
||||||
|
import { ensureUser, users } from "./users"; |
||||||
|
import { summary_defaults, type PRSummary } from "$lib/components/prs/type"; |
||||||
|
|
||||||
|
let pr_kind: number = 318; |
||||||
|
|
||||||
|
export let selected_pr_summary: Writable<PRSummary> = writable({ ...summary_defaults }); |
||||||
|
|
||||||
|
let selected_repo_id: string = ""; |
||||||
|
let selected_pr_id: string = ""; |
||||||
|
let pr_summary_author_unsubsriber: Unsubscriber | undefined; |
||||||
|
|
||||||
|
export let ensurePRSummary = (repo_id: string, pr_id: string) => { |
||||||
|
if (selected_pr_id == pr_id) return; |
||||||
|
if (pr_id == "") return selected_pr_summary.set({ |
||||||
|
...summary_defaults, |
||||||
|
}); |
||||||
|
|
||||||
|
selected_repo_id = repo_id; |
||||||
|
selected_pr_id = pr_id; |
||||||
|
|
||||||
|
selected_pr_summary.update(summary => { |
||||||
|
return { |
||||||
|
...summary, |
||||||
|
id: pr_id, |
||||||
|
repo_id: repo_id, |
||||||
|
loading: true, |
||||||
|
}; |
||||||
|
}); |
||||||
|
if (pr_summary_author_unsubsriber) pr_summary_author_unsubsriber(); |
||||||
|
pr_summary_author_unsubsriber = undefined; |
||||||
|
|
||||||
|
|
||||||
|
let sub = ndk.subscribe({ |
||||||
|
ids: [pr_id], |
||||||
|
limit: 1, |
||||||
|
}); |
||||||
|
|
||||||
|
sub.on("event", (event: NDKEvent) => { |
||||||
|
try { |
||||||
|
if (event.kind == pr_kind |
||||||
|
&& event.getMatchingTags("r").find(t => t[1] === `r-${repo_id}`) |
||||||
|
&& event.id == pr_id |
||||||
|
) { |
||||||
|
|
||||||
|
selected_pr_summary.update(summary => { |
||||||
|
return { |
||||||
|
...summary, |
||||||
|
title: event.tagValue("name") || "", |
||||||
|
created_at: event.created_at, |
||||||
|
comments: 0, |
||||||
|
author: { |
||||||
|
hexpubkey: event.pubkey, |
||||||
|
loading: true, |
||||||
|
npub: "", |
||||||
|
}, |
||||||
|
loading: false, |
||||||
|
}; |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
pr_summary_author_unsubsriber = ensureUser(event.pubkey).subscribe((u: User) => { |
||||||
|
selected_pr_summary.update(summary => { |
||||||
|
return { |
||||||
|
...summary, |
||||||
|
author: event.pubkey == u.hexpubkey ? u : summary.author, |
||||||
|
}; |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
} catch { } |
||||||
|
}); |
||||||
|
sub.on("eose", () => { |
||||||
|
selected_pr_summary.update(summary => { |
||||||
|
return { |
||||||
|
...summary, |
||||||
|
loading: false, |
||||||
|
}; |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
@ -0,0 +1,30 @@ |
|||||||
|
<script lang="ts"> |
||||||
|
import { ensureSelectedRepo, selected_repo } from "$lib/stores/repo"; |
||||||
|
import { ensurePRSummary, selected_pr_summary } from "$lib/stores/PR"; |
||||||
|
import PrHeader from "$lib/components/prs/PRHeader.svelte"; |
||||||
|
import RepoHeader from "$lib/components/repo/RepoHeader.svelte"; |
||||||
|
|
||||||
|
export let data: { |
||||||
|
repo_id: string; |
||||||
|
pr_id: string; |
||||||
|
}; |
||||||
|
|
||||||
|
let repo_id = data.repo_id; |
||||||
|
let pr_id = data.pr_id; |
||||||
|
|
||||||
|
ensureSelectedRepo(repo_id); |
||||||
|
ensurePRSummary(repo_id, pr_id); |
||||||
|
</script> |
||||||
|
|
||||||
|
<RepoHeader {...$selected_repo} /> |
||||||
|
<PrHeader {...$selected_pr_summary} /> |
||||||
|
|
||||||
|
<div class="flex"> |
||||||
|
<div class="w-2/3 mx-2"> |
||||||
|
<div>placeholder for PR summary</div> |
||||||
|
<div>placeholder for all related events</div> |
||||||
|
</div> |
||||||
|
<div class="w-1/3 mx-2 prose"> |
||||||
|
<div>placeholder for status, tags, contributors</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
Loading…
Reference in new issue