Browse Source
stop automatic grouping of repo events by identifer and earliest unique commit into a single collection. allow selection of different repos that have an identifier collision by prioritising pubkey:identifier over identifer show repos grouped by namemaster
57 changed files with 1142 additions and 693 deletions
@ -0,0 +1,56 @@ |
|||||||
|
import type { RepoDIdentiferCollection } from '$lib/components/repo/type' |
||||||
|
import { writable, type Writable } from 'svelte/store' |
||||||
|
import { ensureRepo, eventToRepoEvent } from './repos' |
||||||
|
import { base_relays, ndk } from './ndk' |
||||||
|
import { repo_kind } from '$lib/kinds' |
||||||
|
import { NDKEvent, NDKRelaySet } from '@nostr-dev-kit/ndk' |
||||||
|
|
||||||
|
export const repos_identifer: { |
||||||
|
[d: string]: Writable<RepoDIdentiferCollection> |
||||||
|
} = {} |
||||||
|
|
||||||
|
export const ensureIdentifierRepoCollection = ( |
||||||
|
identifier: string |
||||||
|
): Writable<RepoDIdentiferCollection> => { |
||||||
|
if (!Object.keys(repos_identifer).includes(identifier)) { |
||||||
|
repos_identifer[identifier] = writable({ |
||||||
|
d: '', |
||||||
|
events: [], |
||||||
|
loading: true, |
||||||
|
}) |
||||||
|
const sub = ndk.subscribe( |
||||||
|
{ kinds: [repo_kind], '#d': [identifier] }, |
||||||
|
{ closeOnEose: true }, |
||||||
|
NDKRelaySet.fromRelayUrls(base_relays, ndk) |
||||||
|
) |
||||||
|
sub.on('event', (event: NDKEvent) => { |
||||||
|
const repo_event = eventToRepoEvent(event) |
||||||
|
if (repo_event && repo_event.identifier === identifier) { |
||||||
|
ensureRepo(event).subscribe((repo_event) => { |
||||||
|
repos_identifer[identifier].update((collection) => { |
||||||
|
let events = collection.events |
||||||
|
let exists = false |
||||||
|
events.map((e) => { |
||||||
|
if (e.author === repo_event.author) { |
||||||
|
exists = true |
||||||
|
return repo_event |
||||||
|
} else return e |
||||||
|
}) |
||||||
|
if (!exists) events = [...events, repo_event] |
||||||
|
return { |
||||||
|
...collection, |
||||||
|
events, |
||||||
|
} |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
sub.on('eose', () => { |
||||||
|
repos_identifer[identifier].update((collection) => ({ |
||||||
|
...collection, |
||||||
|
loading: false, |
||||||
|
})) |
||||||
|
}) |
||||||
|
} |
||||||
|
return repos_identifer[identifier] |
||||||
|
} |
||||||
@ -0,0 +1,78 @@ |
|||||||
|
import type { SelectedPubkeyRepoCollections } from '$lib/components/repo/type' |
||||||
|
import { get, writable, type Unsubscriber, type Writable } from 'svelte/store' |
||||||
|
import { ensureRepoCollection, eventToRepoEvent } from './repos' |
||||||
|
import { base_relays, ndk } from './ndk' |
||||||
|
import { repo_kind } from '$lib/kinds' |
||||||
|
import { NDKEvent, NDKRelaySet } from '@nostr-dev-kit/ndk' |
||||||
|
import { extractAReference } from '$lib/components/repo/utils' |
||||||
|
|
||||||
|
export const selected_npub_repo_collections: Writable<SelectedPubkeyRepoCollections> = |
||||||
|
writable({ |
||||||
|
pubkey: '', |
||||||
|
collections: [], |
||||||
|
}) |
||||||
|
|
||||||
|
const unsubscribers: Unsubscriber[] = [] |
||||||
|
|
||||||
|
export const ensureSelectedPubkeyRepoCollection = ( |
||||||
|
pubkey: string |
||||||
|
): Writable<SelectedPubkeyRepoCollections> => { |
||||||
|
const collections = get(selected_npub_repo_collections) |
||||||
|
if (collections.pubkey === pubkey) return selected_npub_repo_collections |
||||||
|
// TODO call unsubscribers
|
||||||
|
selected_npub_repo_collections.set({ |
||||||
|
pubkey, |
||||||
|
collections: [], |
||||||
|
}) |
||||||
|
|
||||||
|
const sub = ndk.subscribe( |
||||||
|
{ kinds: [repo_kind], authors: [pubkey] }, |
||||||
|
{ closeOnEose: true }, |
||||||
|
NDKRelaySet.fromRelayUrls(base_relays, ndk) |
||||||
|
) |
||||||
|
const identifiers: string[] = [] |
||||||
|
sub.on('event', (event: NDKEvent) => { |
||||||
|
const repo_event = eventToRepoEvent(event) |
||||||
|
if ( |
||||||
|
repo_event && |
||||||
|
repo_event.author === pubkey && |
||||||
|
!identifiers.includes(repo_event.identifier) |
||||||
|
) |
||||||
|
identifiers.push(repo_event.identifier) |
||||||
|
}) |
||||||
|
sub.on('eose', () => { |
||||||
|
identifiers.forEach((identifier) => { |
||||||
|
unsubscribers.push( |
||||||
|
ensureRepoCollection(`${repo_kind}:${pubkey}:${identifier}`).subscribe( |
||||||
|
(c) => { |
||||||
|
if (!c.maintainers.includes(pubkey)) return |
||||||
|
|
||||||
|
selected_npub_repo_collections.update((selected_collections) => { |
||||||
|
if (selected_collections.pubkey !== pubkey) |
||||||
|
return { ...selected_collections } |
||||||
|
let collection_in_selected_collections = false |
||||||
|
const collections = selected_collections.collections.map( |
||||||
|
(old_c) => { |
||||||
|
const ref = extractAReference(old_c.selected_a) |
||||||
|
if (ref && ref.identifier === identifier) { |
||||||
|
collection_in_selected_collections = true |
||||||
|
return { |
||||||
|
...c, |
||||||
|
} |
||||||
|
} |
||||||
|
return { ...old_c } |
||||||
|
} |
||||||
|
) |
||||||
|
if (!collection_in_selected_collections) collections.push(c) |
||||||
|
return { |
||||||
|
...selected_collections, |
||||||
|
collections, |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
) |
||||||
|
) |
||||||
|
}) |
||||||
|
}) |
||||||
|
return selected_npub_repo_collections |
||||||
|
} |
||||||
@ -0,0 +1,55 @@ |
|||||||
|
import type { RepoRecentCollection } from '$lib/components/repo/type' |
||||||
|
import { writable, type Writable } from 'svelte/store' |
||||||
|
import { ensureRepo, eventToRepoEvent } from './repos' |
||||||
|
import { base_relays, ndk } from './ndk' |
||||||
|
import { repo_kind } from '$lib/kinds' |
||||||
|
import { NDKEvent, NDKRelaySet } from '@nostr-dev-kit/ndk' |
||||||
|
|
||||||
|
export const recent_repos: Writable<RepoRecentCollection> = writable({ |
||||||
|
events: [], |
||||||
|
loading: true, |
||||||
|
}) |
||||||
|
|
||||||
|
let started = false |
||||||
|
|
||||||
|
export const ensureRecentRepos = (): Writable<RepoRecentCollection> => { |
||||||
|
if (started) return recent_repos |
||||||
|
started = true |
||||||
|
const sub = ndk.subscribe( |
||||||
|
{ kinds: [repo_kind] }, |
||||||
|
{ closeOnEose: true }, |
||||||
|
NDKRelaySet.fromRelayUrls(base_relays, ndk) |
||||||
|
) |
||||||
|
sub.on('event', (event: NDKEvent) => { |
||||||
|
const repo_event = eventToRepoEvent(event) |
||||||
|
if (repo_event) { |
||||||
|
ensureRepo(event).subscribe((repo_event) => { |
||||||
|
recent_repos.update((collection) => { |
||||||
|
let events = collection.events |
||||||
|
let exists = false |
||||||
|
events.map((e) => { |
||||||
|
if ( |
||||||
|
e.author === repo_event.author && |
||||||
|
e.identifier === repo_event.identifier |
||||||
|
) { |
||||||
|
exists = true |
||||||
|
return repo_event |
||||||
|
} else return e |
||||||
|
}) |
||||||
|
if (!exists) events = [...events, repo_event] |
||||||
|
return { |
||||||
|
...collection, |
||||||
|
events, |
||||||
|
} |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
sub.on('eose', () => { |
||||||
|
recent_repos.update((collection) => ({ |
||||||
|
...collection, |
||||||
|
loading: false, |
||||||
|
})) |
||||||
|
}) |
||||||
|
return recent_repos |
||||||
|
} |
||||||
@ -1,16 +1,17 @@ |
|||||||
<script lang="ts"> |
<script lang="ts"> |
||||||
import ReposSummaryList from '$lib/components/ReposSummaryList.svelte' |
import ReposSummaryList from '$lib/components/ReposSummaryList.svelte' |
||||||
import { |
import { summary_defaults } from '$lib/components/repo/type' |
||||||
ensureRecentReposEvents, |
import { ensureRecentRepos, recent_repos } from '$lib/stores/ReposRecent' |
||||||
recent_repo_summaries, |
import { repoEventToSummary } from '$lib/stores/repos' |
||||||
recent_repo_summaries_loading, |
|
||||||
} from '$lib/stores/repos' |
|
||||||
|
|
||||||
ensureRecentReposEvents() |
ensureRecentRepos() |
||||||
</script> |
</script> |
||||||
|
|
||||||
<ReposSummaryList |
<ReposSummaryList |
||||||
title="Latest Repositories" |
title="Latest Repositories" |
||||||
repos={$recent_repo_summaries} |
repos={$recent_repos.events.map( |
||||||
loading={$recent_repo_summaries_loading} |
(c) => repoEventToSummary(c) || { ...summary_defaults } |
||||||
|
)} |
||||||
|
group_by="name" |
||||||
|
loading={$recent_repos.loading} |
||||||
/> |
/> |
||||||
|
|||||||
@ -0,0 +1,122 @@ |
|||||||
|
<script lang="ts"> |
||||||
|
import { nip19 } from 'nostr-tools' |
||||||
|
import Container from '$lib/components/Container.svelte' |
||||||
|
import { goto } from '$app/navigation' |
||||||
|
import { issue_kind, patch_kind, repo_kind } from '$lib/kinds' |
||||||
|
import { base_relays, ndk } from '$lib/stores/ndk' |
||||||
|
import { NDKEvent, NDKRelaySet } from '@nostr-dev-kit/ndk' |
||||||
|
import { aToNaddr } from '$lib/components/repo/utils' |
||||||
|
import { ensureIssueFull } from '$lib/stores/Issue' |
||||||
|
import { ensureProposalFull } from '$lib/stores/Proposal' |
||||||
|
|
||||||
|
export let data: { nostr_ref: string } |
||||||
|
|
||||||
|
let error = false |
||||||
|
let error_msg = |
||||||
|
'reference in URL is not a repository, proposal, issue or npub reference' |
||||||
|
let waited = false |
||||||
|
|
||||||
|
const showError = (msg?: string) => { |
||||||
|
if (msg) error_msg = msg |
||||||
|
error = true |
||||||
|
waited = true |
||||||
|
} |
||||||
|
|
||||||
|
let lookupEvent = (id: string) => { |
||||||
|
let sub = ndk.subscribe( |
||||||
|
{ |
||||||
|
ids: [id], |
||||||
|
limit: 100, |
||||||
|
}, |
||||||
|
{ |
||||||
|
closeOnEose: false, |
||||||
|
}, |
||||||
|
NDKRelaySet.fromRelayUrls(base_relays, ndk) |
||||||
|
) |
||||||
|
|
||||||
|
sub.on('event', (event: NDKEvent) => { |
||||||
|
try { |
||||||
|
if (event.id == id) { |
||||||
|
let a = event.tagValue('a') |
||||||
|
if (!a) { |
||||||
|
showError( |
||||||
|
'found event but it contains an invalid "a" tag reference' |
||||||
|
) |
||||||
|
} else { |
||||||
|
if (event.kind === issue_kind) { |
||||||
|
ensureIssueFull(a, id) |
||||||
|
goto(`/r/${aToNaddr(a)}/issues/${nip19.noteEncode(id)}`) |
||||||
|
} else if (event.kind === patch_kind) { |
||||||
|
ensureProposalFull(a, id) |
||||||
|
goto(`/r/${aToNaddr(a)}/proposals/${nip19.noteEncode(id)}`) |
||||||
|
} else { |
||||||
|
showError() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} catch {} |
||||||
|
}) |
||||||
|
|
||||||
|
sub.on('eose', () => { |
||||||
|
showError('cannot find event') |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
$: { |
||||||
|
try { |
||||||
|
let decoded = nip19.decode(data.nostr_ref) |
||||||
|
if (decoded.type === 'npub' || decoded.type === 'nprofile') |
||||||
|
goto(`/p/${data.nostr_ref}`) |
||||||
|
else if (decoded.type === 'naddr' && decoded.data.kind === repo_kind) { |
||||||
|
goto(`/r/${data.nostr_ref}`) |
||||||
|
} else if (decoded.type === 'nrelay' || decoded.type === 'nsec') { |
||||||
|
showError() |
||||||
|
} else if (typeof decoded.data === 'string') { |
||||||
|
lookupEvent(decoded.data) |
||||||
|
} else if ( |
||||||
|
(decoded.type === 'nevent' || decoded.type === 'note') && |
||||||
|
// doesnt have a confirmed kind of something other than issue or patch |
||||||
|
!( |
||||||
|
decoded.data.kind && |
||||||
|
[patch_kind, issue_kind].includes(decoded.data.kind) |
||||||
|
) |
||||||
|
) { |
||||||
|
lookupEvent(decoded.data.id) |
||||||
|
} else { |
||||||
|
showError() |
||||||
|
} |
||||||
|
} catch { |
||||||
|
try { |
||||||
|
nip19.noteEncode(data.nostr_ref) // will throw if invalid event id |
||||||
|
lookupEvent(data.nostr_ref) |
||||||
|
} catch { |
||||||
|
showError() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
{#if error && waited} |
||||||
|
<Container> |
||||||
|
<div |
||||||
|
role="alert" |
||||||
|
class="wrap alert alert-error m-auto mt-6 w-full max-w-lg" |
||||||
|
> |
||||||
|
<svg |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
class="h-6 w-6 shrink-0 stroke-current" |
||||||
|
fill="none" |
||||||
|
viewBox="0 0 24 24" |
||||||
|
><path |
||||||
|
stroke-linecap="round" |
||||||
|
stroke-linejoin="round" |
||||||
|
stroke-width="2" |
||||||
|
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" |
||||||
|
/></svg |
||||||
|
> |
||||||
|
<span>Error! {error_msg}: {data.nostr_ref}</span> |
||||||
|
</div> |
||||||
|
</Container> |
||||||
|
{:else} |
||||||
|
<Container>loading...</Container> |
||||||
|
{/if} |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
export const load = ({ params }: { params: { nostr_ref: string } }) => { |
||||||
|
return { |
||||||
|
nostr_ref: params.nostr_ref, |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
export const load = ({ params }: { params: { repo_naddr: string } }) => { |
||||||
|
return { |
||||||
|
repo_naddr: params.repo_naddr, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export const ssr = false |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
export const load = ({ params }: { params: { repo_naddr: string } }) => { |
||||||
|
return { |
||||||
|
repo_naddr: params.repo_naddr, |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
export const load = ({ |
||||||
|
params, |
||||||
|
}: { |
||||||
|
params: { issue_nip19: string; repo_naddr: string } |
||||||
|
}) => { |
||||||
|
return { |
||||||
|
repo_naddr: decodeURIComponent(params.repo_naddr), |
||||||
|
issue_nip19: params.issue_nip19, |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
export const load = ({ params }: { params: { repo_naddr: string } }) => { |
||||||
|
return { |
||||||
|
repo_naddr: params.repo_naddr, |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
export const load = ({ params }: { params: { repo_naddr: string } }) => { |
||||||
|
return { |
||||||
|
repo_naddr: params.repo_naddr, |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,107 @@ |
|||||||
|
<script lang="ts"> |
||||||
|
import { |
||||||
|
ensureProposalFull, |
||||||
|
selected_proposal_full, |
||||||
|
selected_proposal_replies, |
||||||
|
} from '$lib/stores/Proposal' |
||||||
|
import Thread from '$lib/wrappers/Thread.svelte' |
||||||
|
import Container from '$lib/components/Container.svelte' |
||||||
|
import ProposalHeader from '$lib/components/proposals/ProposalHeader.svelte' |
||||||
|
import ProposalDetails from '$lib/components/proposals/ProposalDetails.svelte' |
||||||
|
import RepoPageWrapper from '$lib/wrappers/RepoPageWrapper.svelte' |
||||||
|
import { naddrToRepoA, neventOrNoteToHexId } from '$lib/components/repo/utils' |
||||||
|
|
||||||
|
export let data: { |
||||||
|
repo_naddr: string |
||||||
|
proposal_nip19: string |
||||||
|
} |
||||||
|
|
||||||
|
let repo_naddr = data.repo_naddr |
||||||
|
let a = '' |
||||||
|
$: { |
||||||
|
const a_result = naddrToRepoA(repo_naddr) |
||||||
|
if (a_result) a = a_result |
||||||
|
} |
||||||
|
|
||||||
|
let proposal_nip19 = data.proposal_nip19 |
||||||
|
let proposal_id = '' |
||||||
|
let invalid_proposal_ref = false |
||||||
|
$: { |
||||||
|
const proposal_nip19_result = neventOrNoteToHexId(proposal_nip19) |
||||||
|
|
||||||
|
if (proposal_nip19_result) { |
||||||
|
proposal_id = proposal_nip19_result |
||||||
|
invalid_proposal_ref = false |
||||||
|
ensureProposalFull(a, proposal_id) |
||||||
|
} else { |
||||||
|
invalid_proposal_ref = true |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let repo_error = false |
||||||
|
let proposal_error = false |
||||||
|
$: { |
||||||
|
proposal_error = |
||||||
|
!$selected_proposal_full.summary.loading && |
||||||
|
$selected_proposal_full.summary.created_at === 0 |
||||||
|
} |
||||||
|
|
||||||
|
let waited_5_secs = false |
||||||
|
setTimeout(() => { |
||||||
|
waited_5_secs = true |
||||||
|
}, 5000) |
||||||
|
</script> |
||||||
|
|
||||||
|
<RepoPageWrapper {repo_naddr} with_side_bar={false} selected_tab="proposals"> |
||||||
|
{#if invalid_proposal_ref || (waited_5_secs && proposal_error)} |
||||||
|
<Container> |
||||||
|
<div role="alert" class="alert alert-error m-auto mt-6 w-full max-w-xs"> |
||||||
|
<svg |
||||||
|
xmlns="http://www.w3.org/2000/svg" |
||||||
|
class="h-6 w-6 shrink-0 stroke-current" |
||||||
|
fill="none" |
||||||
|
viewBox="0 0 24 24" |
||||||
|
><path |
||||||
|
stroke-linecap="round" |
||||||
|
stroke-linejoin="round" |
||||||
|
stroke-width="2" |
||||||
|
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" |
||||||
|
/></svg |
||||||
|
> |
||||||
|
{#if invalid_proposal_ref}<span |
||||||
|
>Error! invalid Issue reference: {proposal_id} '{proposal_nip19}'</span |
||||||
|
> |
||||||
|
{:else} |
||||||
|
<span |
||||||
|
>Error! cannot find Issue {repo_error ? 'or repo ' : ''}event</span |
||||||
|
> |
||||||
|
{/if} |
||||||
|
</div> |
||||||
|
</Container> |
||||||
|
{:else} |
||||||
|
<ProposalHeader {...$selected_proposal_full.summary} /> |
||||||
|
<Container> |
||||||
|
<div class="mx-auto max-w-6xl lg:flex"> |
||||||
|
<div class="md:mr-2 lg:w-2/3"> |
||||||
|
<div class="max-w-4xl"> |
||||||
|
{#if $selected_proposal_full.proposal_event} |
||||||
|
<Thread |
||||||
|
type="proposal" |
||||||
|
event={$selected_proposal_full.proposal_event} |
||||||
|
replies={$selected_proposal_replies} |
||||||
|
/> |
||||||
|
{/if} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="prose ml-2 hidden w-1/3 lg:flex"> |
||||||
|
<ProposalDetails |
||||||
|
type="proposal" |
||||||
|
summary={$selected_proposal_full.summary} |
||||||
|
labels={$selected_proposal_full.labels} |
||||||
|
loading={$selected_proposal_full.loading} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</Container> |
||||||
|
{/if} |
||||||
|
</RepoPageWrapper> |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
export const load = ({ |
||||||
|
params, |
||||||
|
}: { |
||||||
|
params: { proposal_nip19: string; repo_naddr: string } |
||||||
|
}) => { |
||||||
|
return { |
||||||
|
repo_naddr: decodeURIComponent(params.repo_naddr), |
||||||
|
proposal_nip19: params.proposal_nip19, |
||||||
|
} |
||||||
|
} |
||||||
@ -1,7 +0,0 @@ |
|||||||
export const load = ({ params }: { params: { repo_id: string } }) => { |
|
||||||
return { |
|
||||||
repo_id: decodeURIComponent(params.repo_id), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export const ssr = false |
|
||||||
@ -1,10 +0,0 @@ |
|||||||
export const load = ({ |
|
||||||
params, |
|
||||||
}: { |
|
||||||
params: { issue_id: string; repo_id: string } |
|
||||||
}) => { |
|
||||||
return { |
|
||||||
repo_id: decodeURIComponent(params.repo_id), |
|
||||||
issue_id: params.issue_id, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,5 +0,0 @@ |
|||||||
export const load = ({ params }: { params: { repo_id: string } }) => { |
|
||||||
return { |
|
||||||
repo_id: decodeURIComponent(params.repo_id), |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,5 +0,0 @@ |
|||||||
export const load = ({ params }: { params: { repo_id: string } }) => { |
|
||||||
return { |
|
||||||
repo_id: decodeURIComponent(params.repo_id), |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,122 +0,0 @@ |
|||||||
<script lang="ts"> |
|
||||||
import { |
|
||||||
ensureSelectedRepoCollection, |
|
||||||
selected_repo_collection, |
|
||||||
selected_repo_event, |
|
||||||
} from '$lib/stores/repo' |
|
||||||
import { |
|
||||||
ensureProposalFull, |
|
||||||
selected_proposal_full, |
|
||||||
selected_proposal_replies, |
|
||||||
} from '$lib/stores/Proposal' |
|
||||||
import ProposalHeader from '$lib/components/proposals/ProposalHeader.svelte' |
|
||||||
import Thread from '$lib/wrappers/Thread.svelte' |
|
||||||
import ProposalDetails from '$lib/components/proposals/ProposalDetails.svelte' |
|
||||||
import Container from '$lib/components/Container.svelte' |
|
||||||
import RepoPageWrapper from '$lib/wrappers/RepoPageWrapper.svelte' |
|
||||||
|
|
||||||
export let data: { |
|
||||||
repo_id: string |
|
||||||
proposal_id: string |
|
||||||
} |
|
||||||
|
|
||||||
let repo_id = data.repo_id |
|
||||||
let proposal_id = data.proposal_id |
|
||||||
|
|
||||||
ensureSelectedRepoCollection(repo_id) |
|
||||||
ensureProposalFull(repo_id, proposal_id) |
|
||||||
|
|
||||||
let repo_error = false |
|
||||||
let proposal_error = false |
|
||||||
$: { |
|
||||||
repo_error = |
|
||||||
!$selected_repo_collection.loading && |
|
||||||
$selected_repo_event.name.length === 0 |
|
||||||
proposal_error = |
|
||||||
!$selected_proposal_full.summary.loading && |
|
||||||
$selected_proposal_full.summary.created_at === 0 |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<RepoPageWrapper |
|
||||||
identifier={repo_id} |
|
||||||
with_side_bar={false} |
|
||||||
selected_tab="proposals" |
|
||||||
> |
|
||||||
{#if proposal_error} |
|
||||||
<Container> |
|
||||||
<div role="alert" class="alert alert-error m-auto mt-6 w-full max-w-xs"> |
|
||||||
<svg |
|
||||||
xmlns="http://www.w3.org/2000/svg" |
|
||||||
class="h-6 w-6 shrink-0 stroke-current" |
|
||||||
fill="none" |
|
||||||
viewBox="0 0 24 24" |
|
||||||
><path |
|
||||||
stroke-linecap="round" |
|
||||||
stroke-linejoin="round" |
|
||||||
stroke-width="2" |
|
||||||
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" |
|
||||||
/></svg |
|
||||||
> |
|
||||||
<span |
|
||||||
>Error! cannot find Proposal {repo_error ? 'or repo ' : ''}event</span |
|
||||||
> |
|
||||||
</div> |
|
||||||
</Container> |
|
||||||
{:else} |
|
||||||
<ProposalHeader {...$selected_proposal_full.summary} /> |
|
||||||
<Container> |
|
||||||
<div class="mx-auto max-w-6xl lg:flex"> |
|
||||||
<div class="lg:w-2/3 xl:mr-2"> |
|
||||||
<div class="max-w-4xl"> |
|
||||||
{#if $selected_proposal_full.proposal_event} |
|
||||||
<Thread |
|
||||||
type="proposal" |
|
||||||
event={$selected_proposal_full.proposal_event} |
|
||||||
replies={$selected_proposal_replies} |
|
||||||
/> |
|
||||||
{/if} |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div class="prose ml-2 hidden w-1/3 lg:block"> |
|
||||||
<div role="alert" class="alert mt-3"> |
|
||||||
<div class="text-center"> |
|
||||||
<div> |
|
||||||
<svg |
|
||||||
xmlns="http://www.w3.org/2000/svg" |
|
||||||
fill="none" |
|
||||||
viewBox="0 0 24 24" |
|
||||||
class="inline h-6 w-6 shrink-0 stroke-info" |
|
||||||
><path |
|
||||||
stroke-linecap="round" |
|
||||||
stroke-linejoin="round" |
|
||||||
stroke-width="2" |
|
||||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" |
|
||||||
></path></svg |
|
||||||
> |
|
||||||
<h3 class="prose mx-1 inline text-sm font-bold"> |
|
||||||
view in local git repository |
|
||||||
</h3> |
|
||||||
</div> |
|
||||||
|
|
||||||
<p class="mx-0 mb-1 mt-2 text-xs"> |
|
||||||
<a href="/ngit">install ngit</a>, run |
|
||||||
<span class="rounded bg-neutral p-1 font-mono" |
|
||||||
><span class="py-3">ngit list</span></span |
|
||||||
> from the local repository and select the proposal title |
|
||||||
</p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div class="block"> |
|
||||||
<ProposalDetails |
|
||||||
type="proposal" |
|
||||||
summary={$selected_proposal_full.summary} |
|
||||||
labels={$selected_proposal_full.labels} |
|
||||||
loading={$selected_proposal_full.loading} |
|
||||||
/> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</Container> |
|
||||||
{/if} |
|
||||||
</RepoPageWrapper> |
|
||||||
@ -1,10 +0,0 @@ |
|||||||
export const load = ({ |
|
||||||
params, |
|
||||||
}: { |
|
||||||
params: { proposal_id: string; repo_id: string } |
|
||||||
}) => { |
|
||||||
return { |
|
||||||
repo_id: decodeURIComponent(params.repo_id), |
|
||||||
proposal_id: params.proposal_id, |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,5 +0,0 @@ |
|||||||
export const load = ({ params }: { params: { repo_id: string } }) => { |
|
||||||
return { |
|
||||||
repo_id: decodeURIComponent(params.repo_id), |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,20 @@ |
|||||||
|
<script lang="ts"> |
||||||
|
import Container from '$lib/components/Container.svelte' |
||||||
|
import ReposSummaryList from '$lib/components/ReposSummaryList.svelte' |
||||||
|
import { ensureIdentifierRepoCollection } from '$lib/stores/ReposIdentifier' |
||||||
|
import { repoEventToSummary } from '$lib/stores/repos' |
||||||
|
|
||||||
|
export let data: { repo_identifier: string } |
||||||
|
|
||||||
|
let collection = ensureIdentifierRepoCollection(data.repo_identifier || '') |
||||||
|
</script> |
||||||
|
|
||||||
|
<Container> |
||||||
|
<div class="m-5"> |
||||||
|
<ReposSummaryList |
||||||
|
title={`repositories for '${data.repo_identifier}'`} |
||||||
|
repos={$collection.events.map(repoEventToSummary)} |
||||||
|
loading={$collection.loading} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</Container> |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
export const load = ({ params }: { params: { repo_identifier: string } }) => { |
||||||
|
return { |
||||||
|
repo_identifier: params.repo_identifier, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export const ssr = false |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
import { redirect } from '@sveltejs/kit' |
||||||
|
|
||||||
|
export const load = ({ params }: { params: { event_id: string } }) => { |
||||||
|
throw redirect(301, `/e/${params.event_id}`) |
||||||
|
} |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
import { redirect } from '@sveltejs/kit' |
||||||
|
|
||||||
|
export const load = ({ params }: { params: { repo_identifier: string } }) => { |
||||||
|
throw redirect(301, `/repo/${params.repo_identifier}`) |
||||||
|
} |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
import { redirect } from '@sveltejs/kit' |
||||||
|
|
||||||
|
export const load = ({ params }: { params: { event_id: string } }) => { |
||||||
|
throw redirect(301, `/e/${params.event_id}`) |
||||||
|
} |
||||||
Loading…
Reference in new issue