From d2339458093479c572ad04dd7baf72b74f8e2321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20R=C3=BCsch?= Date: Wed, 20 Dec 2023 12:58:33 +0100 Subject: [PATCH 1/5] Refactor status types into common enum --- src/common/status-color.ts | 15 +++++++ .../BacklogView/Issue/IssueCard.tsx | 21 ++-------- .../IssuesWrapper/SprintsPanel.tsx | 7 ++-- .../BacklogView/helpers/backlogHelpers.ts | 3 +- .../Components/ChildIssue/ChildIssueCard.tsx | 24 +++-------- .../Components/StoryPointsHoverCard.tsx | 11 +++-- .../EpicDetailView/EpicDetailView.tsx | 40 ++++++++----------- .../helpers/storyPointsHelper.ts | 5 ++- src/components/EpicView/EpicCard.tsx | 20 ++-------- types/status.ts | 5 +++ 10 files changed, 63 insertions(+), 88 deletions(-) create mode 100644 src/common/status-color.ts create mode 100644 types/status.ts diff --git a/src/common/status-color.ts b/src/common/status-color.ts new file mode 100644 index 00000000..c2d2281e --- /dev/null +++ b/src/common/status-color.ts @@ -0,0 +1,15 @@ +import { MantineColor } from "@mantine/styles"; +import { StatusType } from "../../types/status"; + +export const getStatusTypeColor = (statusType: StatusType): MantineColor => { + switch (statusType) { + case StatusType.TODO: + return "gray.6" + case StatusType.IN_PROGRESS: + return "blue.8" + case StatusType.DONE: + return "green.9" + default: + return "gray.6" + } +} \ No newline at end of file diff --git a/src/components/BacklogView/Issue/IssueCard.tsx b/src/components/BacklogView/Issue/IssueCard.tsx index f4333642..1dfc96d3 100644 --- a/src/components/BacklogView/Issue/IssueCard.tsx +++ b/src/components/BacklogView/Issue/IssueCard.tsx @@ -20,6 +20,8 @@ import { Draggable } from "react-beautiful-dnd" import { DetailView } from "../../DetailView/DetailView" import { IssueIcon } from "./IssueIcon" import { DeleteButton } from "./DeleteButton" +import { getStatusTypeColor } from "../../../common/status-color"; +import { StatusType } from "../../../../types/status"; export function IssueCard({ issueKey, @@ -34,7 +36,6 @@ export function IssueCard({ projectId, ...props }: Issue & { index: number }) { - let storyPointsColor: string const [opened, setOpened] = useState(false) const queryClient = useQueryClient() const { ref, hovered } = useHover() @@ -51,20 +52,6 @@ export function IssueCard({ transition: "background-color .1s ease-in", } - switch (status) { - case "To Do": - storyPointsColor = "gray.6" - break - case "In Progress": - storyPointsColor = "blue.8" - break - case "Done": - storyPointsColor = "green.9" - break - default: - storyPointsColor = "gray.6" - } - return ( <> @@ -107,7 +94,7 @@ export function IssueCard({ size="sm" mr={5} color="blue" - td={status === "Done" ? "line-through" : "none"} + td={status === StatusType.DONE ? "line-through" : "none"} sx={{ ":hover": { textDecoration: "underline", @@ -183,7 +170,7 @@ export function IssueCard({ bg={ storyPointsEstimate !== undefined && storyPointsEstimate !== null - ? storyPointsColor + ? getStatusTypeColor(status as StatusType) : "transparent" } variant="filled" diff --git a/src/components/BacklogView/IssuesWrapper/SprintsPanel.tsx b/src/components/BacklogView/IssuesWrapper/SprintsPanel.tsx index 6c743a24..e8e40641 100644 --- a/src/components/BacklogView/IssuesWrapper/SprintsPanel.tsx +++ b/src/components/BacklogView/IssuesWrapper/SprintsPanel.tsx @@ -7,6 +7,7 @@ import { storyPointsAccumulator, } from "../helpers/backlogHelpers" import { DraggableIssuesWrapper } from "./DraggableIssuesWrapper" +import {StatusType} from "../../../../types/status"; export function SprintsPanel({ sprintsWithIssues, @@ -78,13 +79,13 @@ function SprintAccordionControl({ )} - {storyPointsAccumulator(issues, "To Do")} + {storyPointsAccumulator(issues, StatusType.TODO)} - {storyPointsAccumulator(issues, "In Progress")} + {storyPointsAccumulator(issues, StatusType.IN_PROGRESS)} - {storyPointsAccumulator(issues, "Done")} + {storyPointsAccumulator(issues, StatusType.DONE)} diff --git a/src/components/BacklogView/helpers/backlogHelpers.ts b/src/components/BacklogView/helpers/backlogHelpers.ts index d2cb3bcf..29d898b7 100644 --- a/src/components/BacklogView/helpers/backlogHelpers.ts +++ b/src/components/BacklogView/helpers/backlogHelpers.ts @@ -1,7 +1,8 @@ import { Issue, Sprint } from "types" import { Dispatch, SetStateAction } from "react" +import { StatusType } from "../../../../types/status"; -export const storyPointsAccumulator = (issues: Issue[], status: string) => +export const storyPointsAccumulator = (issues: Issue[], status: StatusType) => issues.reduce((accumulator, currentValue) => { if (currentValue.storyPointsEstimate && currentValue.status === status) { return accumulator + currentValue.storyPointsEstimate diff --git a/src/components/EpicDetailView/Components/ChildIssue/ChildIssueCard.tsx b/src/components/EpicDetailView/Components/ChildIssue/ChildIssueCard.tsx index 2b5b8cf3..c7847b41 100644 --- a/src/components/EpicDetailView/Components/ChildIssue/ChildIssueCard.tsx +++ b/src/components/EpicDetailView/Components/ChildIssue/ChildIssueCard.tsx @@ -19,6 +19,8 @@ import { Issue } from "../../../../../types" import { DetailView } from "../../../DetailView/DetailView" import { IssueIcon } from "../../../BacklogView/Issue/IssueIcon" import { DeleteButton } from "../../../BacklogView/Issue/DeleteButton" +import { getStatusTypeColor } from "../../../../common/status-color"; +import { StatusType } from "../../../../../types/status"; export function ChildIssueCard({ issueKey, @@ -33,7 +35,6 @@ export function ChildIssueCard({ projectId, ...props }: Issue & { index: number }) { - let storyPointsColor: string const [opened, setOpened] = useState(false) const queryClient = useQueryClient() const { hovered } = useHover() @@ -50,20 +51,6 @@ export function ChildIssueCard({ transition: "background-color .1s ease-in", } - switch (status) { - case "To Do": - storyPointsColor = "gray.6" - break - case "In Progress": - storyPointsColor = "blue.8" - break - case "Done": - storyPointsColor = "green.9" - break - default: - storyPointsColor = "gray.6" - } - return ( <> setOpened(true)} sx={{ position: "relative" }}> @@ -98,7 +85,7 @@ export function ChildIssueCard({ size="sm" mr={5} color="blue" - td={status === "Done" ? "line-through" : "none"} + td={status === StatusType.DONE ? "line-through" : "none"} sx={{ ":hover": { textDecoration: "underline", @@ -140,9 +127,8 @@ export function ChildIssueCard({ { resizeDivider() @@ -201,29 +203,22 @@ export function EpicDetailView({ }} sections={[ { - value: - (tasksDone / (tasksDone + tasksOpen + tasksInProgress)) * - 100, + value: (tasksDone / totalTaskCount) * 100, color: "#10df10", label: `${tasksDone}`, tooltip: `${tasksDone} Done`, }, { - value: - (tasksInProgress / - (tasksDone + tasksOpen + tasksInProgress)) * - 100, + value: (tasksInProgress / totalTaskCount) * 100, color: "#6ba5d8", label: `${tasksInProgress}`, tooltip: `${tasksInProgress} In progress`, }, { - value: - (tasksOpen / (tasksDone + tasksOpen + tasksInProgress)) * - 100, + value: (tasksTodo / totalTaskCount) * 100, color: "rgb(225,223,223)", - label: `${tasksOpen}`, - tooltip: `${tasksOpen} ToDo`, + label: `${tasksTodo}`, + tooltip: `${tasksTodo} ToDo`, }, { value: 100, @@ -234,19 +229,16 @@ export function EpicDetailView({ ]} /> diff --git a/src/components/EpicDetailView/helpers/storyPointsHelper.ts b/src/components/EpicDetailView/helpers/storyPointsHelper.ts index 51a77340..fa90e594 100644 --- a/src/components/EpicDetailView/helpers/storyPointsHelper.ts +++ b/src/components/EpicDetailView/helpers/storyPointsHelper.ts @@ -1,12 +1,13 @@ import { Issue } from "../../../../types" +import { StatusType } from "../../../../types/status"; -export const storyPointsAccumulator = (issues: Issue[], status: string) => +export const storyPointsAccumulator = (issues: Issue[], status: StatusType) => issues.reduce( (accumulator, currentValue) => accumulator + (currentValue.status === status ? currentValue.storyPointsEstimate ?? 0 : 0) ?? 0, 0, ) -export const inProgressAccumulator = (issues: Issue[], status: string) => +export const inProgressAccumulator = (issues: Issue[], status: StatusType) => issues.reduce( (accumulator, currentValue) => accumulator + (currentValue.status === status ? 1 : 0), 0, diff --git a/src/components/EpicView/EpicCard.tsx b/src/components/EpicView/EpicCard.tsx index f7f2cc8b..0e34be6f 100644 --- a/src/components/EpicView/EpicCard.tsx +++ b/src/components/EpicView/EpicCard.tsx @@ -19,6 +19,8 @@ import {useQueryClient} from "@tanstack/react-query"; import {IconBolt} from "@tabler/icons"; import {DeleteButton} from "../BacklogView/Issue/DeleteButton"; import {EpicDetailView} from "../EpicDetailView/EpicDetailView"; +import {getStatusTypeColor} from "../../common/status-color"; +import {StatusType} from "../../../types/status"; export function EpicCard ({ issueKey, @@ -32,7 +34,6 @@ export function EpicCard ({ projectId, ...props }: Issue) { - let storyPointsColor: string const [opened, setOpened] = useState(false) const queryClient = useQueryClient() const {hovered} = useHover() @@ -47,19 +48,6 @@ export function EpicCard ({ backgroundColor: theme.colors.gray[1], transition: "background-color .1s ease-in", } - switch (status) { - case "To Do": - storyPointsColor = "gray.6" - break - case "In Progress": - storyPointsColor = "blue.8" - break - case "Done": - storyPointsColor = "green.9" - break - default: - storyPointsColor = "gray.6" - } return ( <> @@ -104,7 +92,7 @@ export function EpicCard ({ size="sm" mr={5} color="blue" - td={status === "Done" ? "line-through" : "none"} + td={status === StatusType.DONE ? "line-through" : "none"} sx={{ ":hover": { textDecoration: "underline", @@ -170,7 +158,7 @@ export function EpicCard ({ bg={ storyPointsEstimate !== undefined && storyPointsEstimate !== null - ? storyPointsColor + ? getStatusTypeColor(status as StatusType) : "transparent" } variant="filled" diff --git a/types/status.ts b/types/status.ts new file mode 100644 index 00000000..3db4441f --- /dev/null +++ b/types/status.ts @@ -0,0 +1,5 @@ +export enum StatusType { + TODO = "To Do", + IN_PROGRESS = "In Progress", + DONE = "Done" +} From f2d1910cc7e9c0dd8f20776ad4445c01accd7554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20R=C3=BCsch?= Date: Wed, 20 Dec 2023 13:01:30 +0100 Subject: [PATCH 2/5] Move story points hover card --- src/components/EpicDetailView/EpicDetailView.tsx | 2 +- .../Components => common/StoryPoints}/StoryPointsHoverCard.tsx | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/components/{EpicDetailView/Components => common/StoryPoints}/StoryPointsHoverCard.tsx (100%) diff --git a/src/components/EpicDetailView/EpicDetailView.tsx b/src/components/EpicDetailView/EpicDetailView.tsx index b964222f..671b0b53 100644 --- a/src/components/EpicDetailView/EpicDetailView.tsx +++ b/src/components/EpicDetailView/EpicDetailView.tsx @@ -36,7 +36,7 @@ import { inProgressAccumulator, storyPointsAccumulator, } from "./helpers/storyPointsHelper" -import { StoryPointsHoverCard } from "./Components/StoryPointsHoverCard"; +import { StoryPointsHoverCard } from "../common/StoryPoints/StoryPointsHoverCard"; import { CommentSection } from "../DetailView/Components/CommentSection"; import { getIssueTypes, setStatus } from "../CreateIssue/queryFunctions"; import { StatusType } from "../../../types/status"; diff --git a/src/components/EpicDetailView/Components/StoryPointsHoverCard.tsx b/src/components/common/StoryPoints/StoryPointsHoverCard.tsx similarity index 100% rename from src/components/EpicDetailView/Components/StoryPointsHoverCard.tsx rename to src/components/common/StoryPoints/StoryPointsHoverCard.tsx From ecbeb3df9c3363a6f278093a58a4f74dc869b2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20R=C3=BCsch?= Date: Wed, 20 Dec 2023 13:11:56 +0100 Subject: [PATCH 3/5] Add story points badge component --- .../common/StoryPoints/StoryPointsBadge.tsx | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/components/common/StoryPoints/StoryPointsBadge.tsx diff --git a/src/components/common/StoryPoints/StoryPointsBadge.tsx b/src/components/common/StoryPoints/StoryPointsBadge.tsx new file mode 100644 index 00000000..adbb3271 --- /dev/null +++ b/src/components/common/StoryPoints/StoryPointsBadge.tsx @@ -0,0 +1,22 @@ +import { Badge } from "@mantine/core" +import { getStatusTypeColor } from "../../../common/status-color"; +import { StatusType } from "../../../../types/status"; + +export function StoryPointsBadge({ + statusType, + storyPointsEstimate + }: { + statusType: StatusType + storyPointsEstimate: number +}) { + return ( + + {storyPointsEstimate} + + ) +} From a42dabe24d3fc492866ce3f4fe93af726f334367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20R=C3=BCsch?= Date: Wed, 20 Dec 2023 13:20:58 +0100 Subject: [PATCH 4/5] Use story points badge wherever applicable --- .../BacklogView/Issue/IssueCard.tsx | 17 +++----------- .../IssuesWrapper/SprintsPanel.tsx | 22 +++++++++++-------- .../Components/ChildIssue/ChildIssueCard.tsx | 15 +++---------- src/components/EpicView/EpicCard.tsx | 20 +++++------------ .../StoryPoints/StoryPointsHoverCard.tsx | 22 +++++-------------- 5 files changed, 31 insertions(+), 65 deletions(-) diff --git a/src/components/BacklogView/Issue/IssueCard.tsx b/src/components/BacklogView/Issue/IssueCard.tsx index 1dfc96d3..4082407e 100644 --- a/src/components/BacklogView/Issue/IssueCard.tsx +++ b/src/components/BacklogView/Issue/IssueCard.tsx @@ -20,8 +20,8 @@ import { Draggable } from "react-beautiful-dnd" import { DetailView } from "../../DetailView/DetailView" import { IssueIcon } from "./IssueIcon" import { DeleteButton } from "./DeleteButton" -import { getStatusTypeColor } from "../../../common/status-color"; import { StatusType } from "../../../../types/status"; +import { StoryPointsBadge } from "../../common/StoryPoints/StoryPointsBadge"; export function IssueCard({ issueKey, @@ -164,19 +164,8 @@ export function IssueCard({ - - {storyPointsEstimate} - + {storyPointsEstimate && + } diff --git a/src/components/BacklogView/IssuesWrapper/SprintsPanel.tsx b/src/components/BacklogView/IssuesWrapper/SprintsPanel.tsx index e8e40641..83f34a65 100644 --- a/src/components/BacklogView/IssuesWrapper/SprintsPanel.tsx +++ b/src/components/BacklogView/IssuesWrapper/SprintsPanel.tsx @@ -8,6 +8,7 @@ import { } from "../helpers/backlogHelpers" import { DraggableIssuesWrapper } from "./DraggableIssuesWrapper" import {StatusType} from "../../../../types/status"; +import {StoryPointsBadge} from "../../common/StoryPoints/StoryPointsBadge"; export function SprintsPanel({ sprintsWithIssues, @@ -78,15 +79,18 @@ function SprintAccordionControl({ )} - - {storyPointsAccumulator(issues, StatusType.TODO)} - - - {storyPointsAccumulator(issues, StatusType.IN_PROGRESS)} - - - {storyPointsAccumulator(issues, StatusType.DONE)} - + + + diff --git a/src/components/EpicDetailView/Components/ChildIssue/ChildIssueCard.tsx b/src/components/EpicDetailView/Components/ChildIssue/ChildIssueCard.tsx index c7847b41..63114a2e 100644 --- a/src/components/EpicDetailView/Components/ChildIssue/ChildIssueCard.tsx +++ b/src/components/EpicDetailView/Components/ChildIssue/ChildIssueCard.tsx @@ -19,8 +19,8 @@ import { Issue } from "../../../../../types" import { DetailView } from "../../../DetailView/DetailView" import { IssueIcon } from "../../../BacklogView/Issue/IssueIcon" import { DeleteButton } from "../../../BacklogView/Issue/DeleteButton" -import { getStatusTypeColor } from "../../../../common/status-color"; import { StatusType } from "../../../../../types/status"; +import { StoryPointsBadge } from "../../../common/StoryPoints/StoryPointsBadge"; export function ChildIssueCard({ issueKey, @@ -124,17 +124,8 @@ export function ChildIssueCard({ }} > - - {storyPointsEstimate} - + {storyPointsEstimate && + } - - {storyPointsEstimate} - + {storyPointsEstimate && + } diff --git a/src/components/common/StoryPoints/StoryPointsHoverCard.tsx b/src/components/common/StoryPoints/StoryPointsHoverCard.tsx index f07c3441..3b6db690 100644 --- a/src/components/common/StoryPoints/StoryPointsHoverCard.tsx +++ b/src/components/common/StoryPoints/StoryPointsHoverCard.tsx @@ -1,6 +1,6 @@ -import { Text, HoverCard, Badge } from "@mantine/core" -import { getStatusTypeColor } from "../../../common/status-color"; +import { Text, HoverCard, Box } from "@mantine/core" import { StatusType } from "../../../../types/status"; +import { StoryPointsBadge } from "./StoryPointsBadge"; export function StoryPointsHoverCard({ statusType, @@ -12,24 +12,14 @@ export function StoryPointsHoverCard({ return ( - - {count} - + + + Total story points for {statusType} issues: {count} From ebcdd4e9aa53c32ae0d1a6ad45dcea9b62dc1c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ru=CC=88sch?= Date: Wed, 20 Dec 2023 19:02:47 +0100 Subject: [PATCH 5/5] Fix styling on progress bar and point badges --- .../EpicDetailView/EpicDetailView.tsx | 18 ++++++----------- .../common/StoryPoints/StoryPointsBadge.tsx | 20 ++++++++++--------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/components/EpicDetailView/EpicDetailView.tsx b/src/components/EpicDetailView/EpicDetailView.tsx index 671b0b53..29bca3a6 100644 --- a/src/components/EpicDetailView/EpicDetailView.tsx +++ b/src/components/EpicDetailView/EpicDetailView.tsx @@ -40,6 +40,7 @@ import { StoryPointsHoverCard } from "../common/StoryPoints/StoryPointsHoverCard import { CommentSection } from "../DetailView/Components/CommentSection"; import { getIssueTypes, setStatus } from "../CreateIssue/queryFunctions"; import { StatusType } from "../../../types/status"; +import { getStatusTypeColor } from "../../common/status-color" export function EpicDetailView({ issueKey, @@ -188,13 +189,6 @@ export function EpicDetailView({ radius="md" size={20} label="hello" - styles={{ - label: { - color: "black", - fontSize: "14px", - fontWeight: "normal", - }, - }} sx={{ width: "400px", marginRight: "5px", @@ -204,25 +198,25 @@ export function EpicDetailView({ sections={[ { value: (tasksDone / totalTaskCount) * 100, - color: "#10df10", + color: getStatusTypeColor(StatusType.DONE), label: `${tasksDone}`, tooltip: `${tasksDone} Done`, }, { value: (tasksInProgress / totalTaskCount) * 100, - color: "#6ba5d8", + color: getStatusTypeColor(StatusType.IN_PROGRESS), label: `${tasksInProgress}`, tooltip: `${tasksInProgress} In progress`, }, { value: (tasksTodo / totalTaskCount) * 100, - color: "rgb(225,223,223)", + color: getStatusTypeColor(StatusType.TODO), label: `${tasksTodo}`, tooltip: `${tasksTodo} ToDo`, }, { value: 100, - color: "rgb(225,223,223)", + color: getStatusTypeColor(StatusType.TODO), label: `0`, tooltip: "Currently no child issues", }, @@ -242,7 +236,7 @@ export function EpicDetailView({ /> - + diff --git a/src/components/common/StoryPoints/StoryPointsBadge.tsx b/src/components/common/StoryPoints/StoryPointsBadge.tsx index adbb3271..b2c59520 100644 --- a/src/components/common/StoryPoints/StoryPointsBadge.tsx +++ b/src/components/common/StoryPoints/StoryPointsBadge.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@mantine/core" +import { Badge, Box } from "@mantine/core"; import { getStatusTypeColor } from "../../../common/status-color"; import { StatusType } from "../../../../types/status"; @@ -10,13 +10,15 @@ export function StoryPointsBadge({ storyPointsEstimate: number }) { return ( - - {storyPointsEstimate} - + + + {storyPointsEstimate} + + ) }