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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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