mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-10-30 08:40:52 +08:00
Extract revision selector and revision badges into components
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<script lang="ts">
|
||||
import type { Revision } from "@bindings/cob/patch/Revision";
|
||||
|
||||
interface Props {
|
||||
revision: Revision;
|
||||
revisions: Revision[];
|
||||
}
|
||||
|
||||
/* eslint-disable prefer-const */
|
||||
let { revision, revisions }: Props = $props();
|
||||
/* eslint-enable prefer-const */
|
||||
</script>
|
||||
|
||||
{#if revision.id === revisions.slice(-1)[0].id}
|
||||
<span
|
||||
class="global-counter"
|
||||
style:height="22px"
|
||||
style:color="var(--color-foreground-contrast)">
|
||||
Latest
|
||||
</span>
|
||||
{/if}
|
||||
{#if revision.id === revisions[0].id}
|
||||
<span
|
||||
class="global-counter"
|
||||
style:height="22px"
|
||||
style:color="var(--color-foreground-contrast)">
|
||||
Initial
|
||||
</span>
|
||||
{/if}
|
||||
@@ -0,0 +1,101 @@
|
||||
<script lang="ts">
|
||||
import type { Patch } from "@bindings/cob/patch/Patch";
|
||||
import type { Revision } from "@bindings/cob/patch/Revision";
|
||||
|
||||
import uniqBy from "lodash/uniqBy";
|
||||
import orderBy from "lodash/orderBy";
|
||||
|
||||
import { authorForNodeId, formatOid } from "@app/lib/utils";
|
||||
|
||||
import Border from "./Border.svelte";
|
||||
import DropdownList from "./DropdownList.svelte";
|
||||
import DropdownListItem from "./DropdownListItem.svelte";
|
||||
import Icon from "./Icon.svelte";
|
||||
import NakedButton from "./NakedButton.svelte";
|
||||
import NodeId from "./NodeId.svelte";
|
||||
import Popover, { closeFocused } from "./Popover.svelte";
|
||||
import RevisionBadges from "./RevisionBadges.svelte";
|
||||
|
||||
interface Props {
|
||||
patch: Patch;
|
||||
revisions: Revision[];
|
||||
selectedRevision: Revision;
|
||||
selectRevision: (revision: Revision) => void;
|
||||
}
|
||||
|
||||
/* eslint-disable prefer-const */
|
||||
let { patch, revisions, selectedRevision, selectRevision }: Props = $props();
|
||||
/* eslint-enable prefer-const */
|
||||
|
||||
const revisionAuthors = $derived(
|
||||
orderBy(
|
||||
uniqBy(
|
||||
revisions.map(r => {
|
||||
return r.author;
|
||||
}),
|
||||
"did",
|
||||
),
|
||||
[
|
||||
o => {
|
||||
return o.did === patch.author.did;
|
||||
},
|
||||
],
|
||||
["desc"],
|
||||
),
|
||||
);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.dropdown-group:not(:last-of-type) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<Popover popoverPadding="0" popoverPositionTop="2.5rem" popoverPositionLeft="0">
|
||||
{#snippet toggle(onclick)}
|
||||
<NakedButton variant="ghost" {onclick}>
|
||||
<Icon name="chevron-down" />
|
||||
</NakedButton>
|
||||
{/snippet}
|
||||
|
||||
{#snippet popover()}
|
||||
<Border variant="ghost">
|
||||
<div style:max-width="20rem" style:padding-top="0.5rem">
|
||||
{#each revisionAuthors as author}
|
||||
<div class="dropdown-group">
|
||||
<div style:padding-left="0.5rem" style:padding-bottom="0.5rem">
|
||||
<NodeId {...authorForNodeId(author)} />
|
||||
</div>
|
||||
<DropdownList
|
||||
items={orderBy(
|
||||
revisions.filter(r => {
|
||||
return r.author.did === author.did;
|
||||
}),
|
||||
"timestamp",
|
||||
["desc"],
|
||||
)}>
|
||||
{#snippet item(revision)}
|
||||
<DropdownListItem
|
||||
selected={revision.id === selectedRevision.id}
|
||||
onclick={() => {
|
||||
closeFocused();
|
||||
selectRevision(revision);
|
||||
}}>
|
||||
<div class="global-flex txt-overflow">
|
||||
<span class="global-oid">
|
||||
{formatOid(revision.id)}
|
||||
</span>
|
||||
<RevisionBadges {revision} {revisions} />
|
||||
<span class="txt-overflow">
|
||||
{revision.description[0].body}
|
||||
</span>
|
||||
</div>
|
||||
</DropdownListItem>
|
||||
{/snippet}
|
||||
</DropdownList>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</Border>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
+11
-113
@@ -9,13 +9,9 @@
|
||||
import type { RepoInfo } from "@bindings/repo/RepoInfo";
|
||||
import type { Revision } from "@bindings/cob/patch/Revision";
|
||||
|
||||
import uniqBy from "lodash/uniqBy";
|
||||
import orderBy from "lodash/orderBy";
|
||||
|
||||
import * as roles from "@app/lib/roles";
|
||||
import { announce } from "@app/components/AnnounceSwitch.svelte";
|
||||
import {
|
||||
authorForNodeId,
|
||||
formatOid,
|
||||
patchStatusBackgroundColor,
|
||||
patchStatusColor,
|
||||
@@ -26,20 +22,17 @@
|
||||
import AssigneeInput from "@app/components/AssigneeInput.svelte";
|
||||
import Border from "@app/components/Border.svelte";
|
||||
import CopyableId from "@app/components/CopyableId.svelte";
|
||||
import DropdownList from "@app/components/DropdownList.svelte";
|
||||
import DropdownListItem from "@app/components/DropdownListItem.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import InlineTitle from "@app/components/InlineTitle.svelte";
|
||||
import LabelInput from "@app/components/LabelInput.svelte";
|
||||
import Layout from "./Layout.svelte";
|
||||
import NakedButton from "@app/components/NakedButton.svelte";
|
||||
import NodeId from "@app/components/NodeId.svelte";
|
||||
import PatchStateBadge from "@app/components/PatchStateBadge.svelte";
|
||||
import PatchStateButton from "@app/components/PatchStateButton.svelte";
|
||||
import PatchTeaser from "@app/components/PatchTeaser.svelte";
|
||||
import PatchTimeline from "@app/components/PatchTimeline.svelte";
|
||||
import Popover, { closeFocused } from "@app/components/Popover.svelte";
|
||||
import RevisionBadges from "@app/components/RevisionBadges.svelte";
|
||||
import RevisionComponent from "@app/components/Revision.svelte";
|
||||
import RevisionSelector from "@app/components/RevisionSelector.svelte";
|
||||
import Sidebar from "@app/components/Sidebar.svelte";
|
||||
import Tab from "@app/components/Tab.svelte";
|
||||
import TextInput from "@app/components/TextInput.svelte";
|
||||
@@ -77,22 +70,6 @@
|
||||
let tab: "patch" | "revisions" | "timeline" = $state("patch");
|
||||
let hideTimeline = $state(false);
|
||||
let selectedRevision: Revision = $state(revisions.slice(-1)[0]);
|
||||
const revisionAuthors = $derived(
|
||||
orderBy(
|
||||
uniqBy(
|
||||
revisions.map(r => {
|
||||
return r.author;
|
||||
}),
|
||||
"did",
|
||||
),
|
||||
[
|
||||
o => {
|
||||
return o.did === patch.author.did;
|
||||
},
|
||||
],
|
||||
["desc"],
|
||||
),
|
||||
);
|
||||
|
||||
$effect(() => {
|
||||
items = patches.content;
|
||||
@@ -309,9 +286,6 @@
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--color-foreground-dim);
|
||||
}
|
||||
.dropdown-group:not(:last-of-type) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
@@ -479,93 +453,17 @@
|
||||
tab = "revisions";
|
||||
}}>
|
||||
{formatOid(selectedRevision.id)}
|
||||
{#if selectedRevision.id === revisions.slice(-1)[0].id}
|
||||
<span
|
||||
class="global-counter"
|
||||
style:height="22px"
|
||||
style:color="var(--color-foreground-contrast)">
|
||||
Latest
|
||||
</span>
|
||||
{/if}
|
||||
{#if selectedRevision.id === revisions[0].id}
|
||||
<span
|
||||
class="global-counter"
|
||||
style:height="22px"
|
||||
style:color="var(--color-foreground-contrast)">
|
||||
Initial
|
||||
</span>
|
||||
{/if}
|
||||
<RevisionBadges revision={selectedRevision} {revisions} />
|
||||
</Tab>
|
||||
|
||||
<Popover
|
||||
popoverPadding="0"
|
||||
popoverPositionTop="2.5rem"
|
||||
popoverPositionLeft="0">
|
||||
{#snippet toggle(onclick)}
|
||||
<NakedButton variant="ghost" {onclick}>
|
||||
<Icon name="chevron-down" />
|
||||
</NakedButton>
|
||||
{/snippet}
|
||||
|
||||
{#snippet popover()}
|
||||
<Border variant="ghost">
|
||||
<div style:max-width="20rem" style:padding-top="0.5rem">
|
||||
{#each revisionAuthors as author}
|
||||
<div class="dropdown-group">
|
||||
<div
|
||||
style:padding-left="0.5rem"
|
||||
style:padding-bottom="0.5rem">
|
||||
<NodeId {...authorForNodeId(author)} />
|
||||
</div>
|
||||
<DropdownList
|
||||
items={orderBy(
|
||||
revisions.filter(r => {
|
||||
return r.author.did === author.did;
|
||||
}),
|
||||
"timestamp",
|
||||
["desc"],
|
||||
)}>
|
||||
{#snippet item(revision)}
|
||||
<DropdownListItem
|
||||
selected={revision.id === selectedRevision.id}
|
||||
onclick={() => {
|
||||
closeFocused();
|
||||
selectedRevision = revision;
|
||||
tab = "revisions";
|
||||
}}>
|
||||
<div class="global-flex txt-overflow">
|
||||
<span class="global-oid">
|
||||
{formatOid(revision.id)}
|
||||
</span>
|
||||
{#if revision.id === revisions.slice(-1)[0].id}
|
||||
<span
|
||||
class="global-counter"
|
||||
style:height="22px"
|
||||
style:color="var(--color-foreground-contrast)">
|
||||
Latest
|
||||
</span>
|
||||
{/if}
|
||||
{#if revision.id === revisions[0].id}
|
||||
<span
|
||||
class="global-counter"
|
||||
style:height="22px"
|
||||
style:color="var(--color-foreground-contrast)">
|
||||
Initial
|
||||
</span>
|
||||
{/if}
|
||||
<span class="txt-overflow">
|
||||
{revision.description[0].body}
|
||||
</span>
|
||||
</div>
|
||||
</DropdownListItem>
|
||||
{/snippet}
|
||||
</DropdownList>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</Border>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
<RevisionSelector
|
||||
{patch}
|
||||
{revisions}
|
||||
{selectedRevision}
|
||||
selectRevision={rev => {
|
||||
selectedRevision = rev;
|
||||
tab = "revisions";
|
||||
}} />
|
||||
{/if}
|
||||
|
||||
<div style:margin-left="auto">
|
||||
|
||||
Reference in New Issue
Block a user