mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-16 03:40:37 +08:00
Implement issue and patch filters in second column
This commit is contained in:
@@ -3,11 +3,18 @@
|
||||
import type { RepoInfo } from "@bindings/repo/RepoInfo";
|
||||
import type { IssueStatus } from "@app/views/repo/router";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import capitalize from "lodash/capitalize";
|
||||
|
||||
import IssueTeaser from "@app/components/IssueTeaser.svelte";
|
||||
import * as router from "@app/lib/router";
|
||||
import { issueStatusColor } 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 IssueTeaser from "@app/components/IssueTeaser.svelte";
|
||||
import OutlineButton from "./OutlineButton.svelte";
|
||||
import Popover, { closeFocused } from "./Popover.svelte";
|
||||
|
||||
const activeRouteStore = router.activeRouteStore;
|
||||
|
||||
@@ -17,11 +24,15 @@
|
||||
issues: Issue[];
|
||||
status: IssueStatus;
|
||||
title: string;
|
||||
changeFilter: (status: IssueStatus) => void;
|
||||
}
|
||||
|
||||
/* eslint-disable prefer-const */
|
||||
let { repo, selectedIssueId, issues, status, title }: Props = $props();
|
||||
let { repo, selectedIssueId, issues, status, title, changeFilter }: Props =
|
||||
$props();
|
||||
/* eslint-enable prefer-const */
|
||||
|
||||
const project = $derived(repo.payloads["xyz.radicle.project"]!);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -40,25 +51,79 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
{#snippet icons(status: IssueStatus)}
|
||||
<div
|
||||
class="icon"
|
||||
style:color={status === "all" ? undefined : issueStatusColor[status]}>
|
||||
<Icon name={status === "closed" ? "issue-closed" : "issue"} />
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
{#snippet counters(status: IssueStatus)}
|
||||
<div style:margin-left="auto" style:padding-left="0.25rem">
|
||||
{#if status === "all"}
|
||||
{project.meta.issues.open + project.meta.issues.closed}
|
||||
{:else}
|
||||
{project.meta.issues[status]}
|
||||
{/if}
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
<div class="container">
|
||||
<div class="txt-regular txt-semibold global-flex" style:gap="4px">
|
||||
<div
|
||||
class="txt-regular txt-semibold global-flex"
|
||||
style:gap="4px"
|
||||
style:white-space="nowrap">
|
||||
{title}
|
||||
<Icon name="chevron-right" />
|
||||
Issues
|
||||
</div>
|
||||
|
||||
<OutlineButton
|
||||
variant="ghost"
|
||||
disabled={$activeRouteStore.resource === "repo.createIssue"}
|
||||
onclick={() => {
|
||||
void router.push({
|
||||
resource: "repo.createIssue",
|
||||
rid: repo.rid,
|
||||
status,
|
||||
});
|
||||
}}>
|
||||
<Icon name="plus" />New
|
||||
</OutlineButton>
|
||||
<div class="global-flex" style:margin-left="1rem">
|
||||
<Popover popoverPositionRight="0" popoverPositionTop="2.5rem">
|
||||
{#snippet toggle(onclick)}
|
||||
<OutlineButton variant="ghost" {onclick}>
|
||||
{@render icons(status)}
|
||||
{capitalize(status)}
|
||||
{@render counters(status)}
|
||||
<Icon name="chevron-down" />
|
||||
</OutlineButton>
|
||||
{/snippet}
|
||||
|
||||
{#snippet popover()}
|
||||
<Border variant="ghost">
|
||||
<DropdownList items={["all", "open", "closed"] as IssueStatus[]}>
|
||||
{#snippet item(state)}
|
||||
<DropdownListItem
|
||||
style="gap: 0.5rem"
|
||||
selected={status === state}
|
||||
onclick={() => {
|
||||
changeFilter(state);
|
||||
closeFocused();
|
||||
}}>
|
||||
{@render icons(state)}
|
||||
{capitalize(state)}
|
||||
{@render counters(state)}
|
||||
</DropdownListItem>
|
||||
{/snippet}
|
||||
</DropdownList>
|
||||
</Border>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
|
||||
<OutlineButton
|
||||
variant="ghost"
|
||||
disabled={$activeRouteStore.resource === "repo.createIssue"}
|
||||
onclick={() => {
|
||||
void router.push({
|
||||
resource: "repo.createIssue",
|
||||
rid: repo.rid,
|
||||
status,
|
||||
});
|
||||
}}>
|
||||
<Icon name="plus" />New
|
||||
</OutlineButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="issue-list">
|
||||
{#each issues as issue}
|
||||
@@ -69,4 +134,26 @@
|
||||
rid={repo.rid}
|
||||
selected={issue.id === selectedIssueId} />
|
||||
{/each}
|
||||
|
||||
{#if issues.length === 0}
|
||||
<Border
|
||||
styleMinWidth="25rem"
|
||||
variant="ghost"
|
||||
styleAlignItems="center"
|
||||
styleJustifyContent="center">
|
||||
<div
|
||||
class="global-flex"
|
||||
style:height="74px"
|
||||
style:justify-content="center">
|
||||
<div class="txt-missing txt-small global-flex" style:gap="0.25rem">
|
||||
<Icon name="none" />
|
||||
{#if status === "all"}
|
||||
No issues.
|
||||
{:else}
|
||||
No {status} issues.
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</Border>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { IssueStatus } from "@app/views/repo/router";
|
||||
import type { ProjectPayload } from "@bindings/repo/ProjectPayload";
|
||||
import type { RepoInfo } from "@bindings/repo/RepoInfo";
|
||||
|
||||
import Border from "./Border.svelte";
|
||||
@@ -10,12 +9,13 @@
|
||||
import Settings from "./Settings.svelte";
|
||||
|
||||
interface Props {
|
||||
project: ProjectPayload;
|
||||
status: IssueStatus;
|
||||
repo: RepoInfo;
|
||||
}
|
||||
|
||||
const { project, status, repo }: Props = $props();
|
||||
const { status, repo }: Props = $props();
|
||||
|
||||
const project = $derived(repo.payloads["xyz.radicle.project"]!);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
import type { IssueStatus, PatchStatus } from "@app/views/repo/router";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import { patchStatusColor } from "@app/lib/utils";
|
||||
import { issueStatusColor } from "@app/lib/utils";
|
||||
|
||||
import { storeLayout, getLayout } from "@app/views/repo/Layout.svelte";
|
||||
|
||||
@@ -61,16 +59,7 @@
|
||||
styleWidth="40px"
|
||||
styleHeight="40px"
|
||||
styleJustifyContent="center">
|
||||
<div
|
||||
style:color={activeTab.status === "all"
|
||||
? undefined
|
||||
: issueStatusColor[activeTab.status]}>
|
||||
{#if activeTab.status === "open"}
|
||||
<Icon name="issue" />
|
||||
{:else}
|
||||
<Icon name="issue-closed" />
|
||||
{/if}
|
||||
</div>
|
||||
<Icon name="issue" />
|
||||
</Border>
|
||||
{:else}
|
||||
<button
|
||||
@@ -100,16 +89,7 @@
|
||||
styleWidth="40px"
|
||||
styleHeight="40px"
|
||||
styleJustifyContent="center">
|
||||
<div
|
||||
style:color={activeTab.status
|
||||
? patchStatusColor[activeTab.status]
|
||||
: undefined}>
|
||||
{#if activeTab.status === "open" || activeTab.status === undefined}
|
||||
<Icon name="patch" />
|
||||
{:else}
|
||||
<Icon name={`patch-${activeTab.status}`} />
|
||||
{/if}
|
||||
</div>
|
||||
<Icon name="patch" />
|
||||
</Border>
|
||||
{:else}
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user