mirror of
https://github.com/hex248/sprint.git
synced 2026-02-07 18:23:03 +00:00
nicer filter displays, bringing clarity
This commit is contained in:
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
|
import Avatar from "@/components/avatar";
|
||||||
import { IssueDetailPane } from "@/components/issue-detail-pane";
|
import { IssueDetailPane } from "@/components/issue-detail-pane";
|
||||||
import { IssueModal } from "@/components/issue-modal";
|
import { IssueModal } from "@/components/issue-modal";
|
||||||
import { defaultIssuesTableFilters, IssuesTable, type IssuesTableFilters } from "@/components/issues-table";
|
import { defaultIssuesTableFilters, IssuesTable, type IssuesTableFilters } from "@/components/issues-table";
|
||||||
import { useSelection } from "@/components/selection-provider";
|
import { useSelection } from "@/components/selection-provider";
|
||||||
|
import SmallSprintDisplay from "@/components/small-sprint-display";
|
||||||
import SmallUserDisplay from "@/components/small-user-display";
|
import SmallUserDisplay from "@/components/small-user-display";
|
||||||
import StatusTag from "@/components/status-tag";
|
import StatusTag from "@/components/status-tag";
|
||||||
import TopBar from "@/components/top-bar";
|
import TopBar from "@/components/top-bar";
|
||||||
@@ -353,12 +355,6 @@ export default function Issues() {
|
|||||||
"title-desc": "Title Z-A",
|
"title-desc": "Title Z-A",
|
||||||
status: "Status",
|
status: "Status",
|
||||||
};
|
};
|
||||||
const sprintLabel = useMemo(() => {
|
|
||||||
if (issueFilters.sprintId === "all") return "Sprint";
|
|
||||||
if (issueFilters.sprintId === "none") return "No sprint";
|
|
||||||
const sprintMatch = sprintsData.find((sprint) => sprint.id === issueFilters.sprintId);
|
|
||||||
return sprintMatch?.name ?? "Sprint";
|
|
||||||
}, [issueFilters.sprintId, sprintsData]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className={`w-full h-screen flex flex-col gap-${BREATHING_ROOM} p-${BREATHING_ROOM}`}>
|
<main className={`w-full h-screen flex flex-col gap-${BREATHING_ROOM} p-${BREATHING_ROOM}`}>
|
||||||
@@ -384,7 +380,17 @@ export default function Issues() {
|
|||||||
{selectedOrganisation?.Organisation.features.issueStatus && (
|
{selectedOrganisation?.Organisation.features.issueStatus && (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger size="default" className="h-9">
|
<DropdownMenuTrigger size="default" className="h-9">
|
||||||
Status
|
{issueFilters.statuses.length === 0 ? (
|
||||||
|
"Status"
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
{Object.entries(statuses)
|
||||||
|
.filter(([status]) => issueFilters.statuses.includes(status))
|
||||||
|
.map(([status, colour]) => (
|
||||||
|
<StatusTag key={status} status={status} colour={colour} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<DropdownMenuContent align="start">
|
||||||
<DropdownMenuLabel>Status</DropdownMenuLabel>
|
<DropdownMenuLabel>Status</DropdownMenuLabel>
|
||||||
@@ -414,7 +420,20 @@ export default function Issues() {
|
|||||||
{selectedOrganisation?.Organisation.features.issueTypes && (
|
{selectedOrganisation?.Organisation.features.issueTypes && (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger size="default" className="h-9">
|
<DropdownMenuTrigger size="default" className="h-9">
|
||||||
Type
|
{issueFilters.types.length === 0 ? (
|
||||||
|
"Type"
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
{Object.entries(issueTypes)
|
||||||
|
.filter(([type]) => issueFilters.types.includes(type))
|
||||||
|
.map(([type, definition]) => (
|
||||||
|
<div key={type} className="flex items-center gap-1.5">
|
||||||
|
<Icon icon={definition.icon} size={14} color={definition.color} />
|
||||||
|
<span>{type}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<DropdownMenuContent align="start">
|
||||||
<DropdownMenuLabel>Type</DropdownMenuLabel>
|
<DropdownMenuLabel>Type</DropdownMenuLabel>
|
||||||
@@ -446,7 +465,25 @@ export default function Issues() {
|
|||||||
)}
|
)}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger size="default" className="h-9">
|
<DropdownMenuTrigger size="default" className="h-9">
|
||||||
Assignee
|
{issueFilters.assignees.length === 0 ? (
|
||||||
|
"Assignee"
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
{issueFilters.assignees.includes("unassigned") && <span>Unassigned</span>}
|
||||||
|
{members
|
||||||
|
.filter((member) => issueFilters.assignees.includes(String(member.id)))
|
||||||
|
.map((member) => (
|
||||||
|
<Avatar
|
||||||
|
key={member.id}
|
||||||
|
name={member.name}
|
||||||
|
username={member.username}
|
||||||
|
avatarURL={member.avatarURL}
|
||||||
|
size={6}
|
||||||
|
textClass="text-[10px]"
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<DropdownMenuContent align="start">
|
||||||
<DropdownMenuLabel>Assignee</DropdownMenuLabel>
|
<DropdownMenuLabel>Assignee</DropdownMenuLabel>
|
||||||
@@ -486,7 +523,16 @@ export default function Issues() {
|
|||||||
{selectedOrganisation?.Organisation.features.sprints && (
|
{selectedOrganisation?.Organisation.features.sprints && (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger size="default" className="h-9">
|
<DropdownMenuTrigger size="default" className="h-9">
|
||||||
{sprintLabel}
|
{issueFilters.sprintId === "all" ? (
|
||||||
|
"Sprint"
|
||||||
|
) : issueFilters.sprintId === "none" ? (
|
||||||
|
<SmallSprintDisplay />
|
||||||
|
) : (
|
||||||
|
(() => {
|
||||||
|
const sprint = sprintsData.find((s) => s.id === issueFilters.sprintId);
|
||||||
|
return sprint ? <SmallSprintDisplay sprint={sprint} /> : "Sprint";
|
||||||
|
})()
|
||||||
|
)}
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<DropdownMenuContent align="start">
|
||||||
<DropdownMenuLabel>Sprint</DropdownMenuLabel>
|
<DropdownMenuLabel>Sprint</DropdownMenuLabel>
|
||||||
|
|||||||
Reference in New Issue
Block a user