Skip to content

Commit

Permalink
Add first epic detail view (#80)
Browse files Browse the repository at this point in the history
Co-authored-by: Benedict Teutsch <bene210@web.de>
Co-authored-by: Julian Rupprecht <rupprecht.julian@web.de>
  • Loading branch information
3 people authored Dec 6, 2023
1 parent 23f3e02 commit 435c09b
Show file tree
Hide file tree
Showing 15 changed files with 442 additions and 25 deletions.
15 changes: 10 additions & 5 deletions electron/providers/jira-cloud-provider/JiraCloudProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -767,11 +767,7 @@ export class JiraCloudProvider implements IProvider {
id: projectId,
},
}),
...(reporter && {
reporter: {
id: reporter,
},
}),
...(reporter && { reporter }),
...(priority && priority.id && { priority }),
...(assignee &&
assignee.id && {
Expand Down Expand Up @@ -862,6 +858,15 @@ export class JiraCloudProvider implements IProvider {
displayName: element.fields.assignee?.displayName,
avatarUrls: element.fields.assignee?.avatarUrls,
},
subtasks: element.fields.subtasks,
created: element.fields.created,
updated: element.fields.updated,
comment: element.fields.comment ?? {
comments: [],
},
projectId: element.fields.project.id,
sprint: element.fields.sprint,
attachments: element.fields.attachment,
}))
)
resolve(epics)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const editIssueMutation = (queryClient: QueryClient, issueKey: string) =>
message: `The assignee for issue ${issueKey} has been modified!`,
color: "green",
})
queryClient.invalidateQueries({ queryKey: ["epics"] })
queryClient.invalidateQueries({ queryKey: ["issues"] })
},
})
17 changes: 10 additions & 7 deletions src/components/DetailView/Components/Labels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ import { editIssue } from "../helpers/queryFunctions"
export function Labels({
labels,
issueKey,
onMutate = () => {}
}: {
labels: string[]
issueKey: string
onMutate?: () => void
}) {
const theme = useMantineTheme()
const [defaultLabels, setdefaultLabels] = useState(labels)
const [showLabelsInput, setshowLabelsInput] = useState(false)
const [defaultLabels, setDefaultLabels] = useState(labels)
const [showLabelsInput, setShowLabelsInput] = useState(false)
const { data: allLabels } = useQuery({
queryKey: ["labels"],
queryFn: () => getLabels(),
})
const mutationLalbels = useMutation({
const mutationLabels = useMutation({
mutationFn: (issue: Issue) => editIssue(issue, issueKey),
onError: () => {
showNotification({
Expand All @@ -40,6 +42,7 @@ export function Labels({
message: `Labels for issue ${issueKey} has been modified!`,
color: "green",
})
onMutate()
},
})
return (
Expand All @@ -62,15 +65,15 @@ export function Labels({
defaultValue={defaultLabels}
data={allLabels || []}
onBlur={() => {
setshowLabelsInput(false)
mutationLalbels.mutate({
setShowLabelsInput(false)
mutationLabels.mutate({
labels: defaultLabels,
} as Issue)
}}
onChange={(value) => setdefaultLabels(value)}
onChange={(value) => setDefaultLabels(value)}
/>
) : (
<Box onClick={() => setshowLabelsInput(true)}>
<Box onClick={() => setShowLabelsInput(true)}>
{defaultLabels.length !== 0 ? (
<Group spacing={3}>
{defaultLabels.map((label) => (
Expand Down
106 changes: 106 additions & 0 deletions src/components/EpicDetailView/Components/IssueSprint.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Text, Box, Select, useMantineTheme } from "@mantine/core"
import { showNotification } from "@mantine/notifications"
import { useMutation, useQuery } from "@tanstack/react-query"
import { Issue, Sprint } from "types"
import { useState } from "react"
import { useCanvasStore } from "../../../lib/Store"
import {
getSprints,
moveIssueToBacklog,
} from "../../CreateIssue/queryFunctions"
import { editIssue } from "../helpers/queryFunctions"

export function IssueSprint(props: {
sprint: Sprint | undefined
issueKey: string
}) {
const theme = useMantineTheme()
const [defaultsprint, setdefaultsprint] = useState(props.sprint || undefined)
const [showSprintInput, setshowSprintInput] = useState(false)

const boardIds = useCanvasStore((state) => state.selectedProjectBoardIds)
const currentBoardId = boardIds[0]
const { data: sprints } = useQuery({
queryKey: ["sprints"],
queryFn: () => getSprints(currentBoardId),
enabled: !!currentBoardId,
})

const mutationSprint = useMutation({
mutationFn: (issue: Issue) => editIssue(issue, props.issueKey),
onError: () => {
showNotification({
message: `An error occured while modifing the sprint 😢`,
color: "red",
})
},
onSuccess: () => {
showNotification({
message: `The sprint for issue ${props.issueKey} has been modified!`,
color: "green",
})
},
})
const mutationBacklog = useMutation({
mutationFn: () => moveIssueToBacklog(props.issueKey),
onError: () => {
showNotification({
message: `An error occured while modifing the sprint 😢`,
color: "red",
})
},
onSuccess: () => {
showNotification({
message: `The sprint for issue ${props.issueKey} has been modified!`,
color: "green",
})
},
})
const sprintNames = sprints ? sprints?.map((sprint) => sprint.name) : []
return (
<span>
{showSprintInput ? (
<Select
nothingFound="No Options"
searchable
clearable
defaultValue={props.sprint ? props.sprint.name : ""}
data={sprintNames}
onBlur={() => {
setshowSprintInput(false)
if (defaultsprint)
mutationSprint.mutate({
sprint: defaultsprint,
} as Issue)
else mutationBacklog.mutate()
}}
onChange={(value) => {
if (value === "") setdefaultsprint(undefined)
else
setdefaultsprint(
sprints?.find((sprint) => sprint.name === value)!
)
}}
/>
) : (
<Box
onClick={() => setshowSprintInput(true)}
sx={{
":hover": {
cursor: "pointer",
boxShadow: theme.shadows.xs,
borderRadius: theme.radius.xs,
transition: "background-color .8s ease-out",
},
}}
>
{defaultsprint ? (
<Text>{defaultsprint.name}</Text>
) : (
<Text color="dimmed">None</Text>
)}
</Box>
)}
</span>
)
}
72 changes: 72 additions & 0 deletions src/components/EpicDetailView/Components/IssueSummary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Text, Textarea } from "@mantine/core"
import { Issue } from "types"
import { useState } from "react"
import { showNotification } from "@mantine/notifications"
import { useMutation } from "@tanstack/react-query"
import { editIssue } from "../helpers/queryFunctions"

export function IssueSummary({
summary,
issueKey,
onMutate = () => {},
}: {
summary: string
issueKey: string
onMutate?: () => void
}) {
const [defaultSummary, setDefaultSummary] = useState(summary)
const [showSummaryInput, setShowSummaryInput] = useState(false)

const mutationSummary = useMutation({
mutationFn: (issue: Issue) => editIssue(issue, issueKey),
onError: () => {
showNotification({
message: `An error occurred while modifying the summary 😢`,
color: "red",
})
},
onSuccess: () => {
if (defaultSummary !== summary) {
showNotification({
message: `The summary of issue ${issueKey} has been modified!`,
color: "green",
})
onMutate()
}
},
})
return (
<Text>
{showSummaryInput ? (
<Textarea
value={defaultSummary}
onChange={(e) => setDefaultSummary(e.target.value)}
onBlur={() => {
if (defaultSummary === "")
showNotification({
message: `The summary of an issue cannot be empty`,
color: "red",
})
else {
setShowSummaryInput(false)
mutationSummary.mutate({
summary: defaultSummary,
} as Issue)
}
}}
autosize
sx={{
textarea: {
fontSize: "inherit",
fontWeight: "inherit",
},
}}
/>
) : (
<Text lineClamp={1} onClick={() => setShowSummaryInput(true)}>
{defaultSummary}
</Text>
)}
</Text>
)
}
62 changes: 62 additions & 0 deletions src/components/EpicDetailView/Components/SubTask/Subtask.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Box, Group, Loader, Text, ThemeIcon } from "@mantine/core"
import { IconBinaryTree2, IconTrash } from "@tabler/icons"
import { useQueryClient } from "@tanstack/react-query"
import { IssueSummary } from "../IssueSummary"
import { deleteSubtaskMutation } from "./queries"

export function Subtask({
id,
subtaskKey,
fields,
}: {
id: string
subtaskKey: string
fields: {
summary: string
}
}) {
const queryClient = useQueryClient()
const deleteSubtask = deleteSubtaskMutation(queryClient)
return (
<Group
align="center"
key={id}
sx={(theme) => ({
borderRadius: theme.radius.sm,
transition: "background-color .8s ease-out",
boxShadow: theme.shadows.xs,
":hover": {
backgroundColor: "#ebecf0",
transition: "background-color .1s ease-in",
},
})}
p="sm"
>
<ThemeIcon size="sm" sx={{ flex: 2 }}>
<IconBinaryTree2 />
</ThemeIcon>
<Text size="sm" color="blue" span sx={{ flex: 15 }} lineClamp={1}>
{subtaskKey}
</Text>
<Box sx={{ flex: 50 }}>
<IssueSummary summary={fields.summary} issueKey={subtaskKey} />
</Box>
{deleteSubtask.isLoading && <Loader size="sm" />}
<ThemeIcon
variant="outline"
size="sm"
color="gray"
ml="auto"
sx={{
flex: 2,
":hover": { color: "red", borderColor: "red", cursor: "pointer" },
}}
onClick={() => {
deleteSubtask.mutate(subtaskKey)
}}
>
<IconTrash />
</ThemeIcon>
</Group>
)
}
1 change: 1 addition & 0 deletions src/components/EpicDetailView/Components/SubTask/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./Subtask"
21 changes: 21 additions & 0 deletions src/components/EpicDetailView/Components/SubTask/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { showNotification } from "@mantine/notifications"
import { QueryClient, useMutation } from "@tanstack/react-query"
import { deleteIssueSubtask } from "./queryFunctions"

export const deleteSubtaskMutation = (queryClient: QueryClient) =>
useMutation({
mutationFn: deleteIssueSubtask,
onError: () => {
showNotification({
message: "The subtask couldn't be deleted! 😢",
color: "red",
})
},
onSuccess: () => {
showNotification({
message: "Subtask has been deleted!",
color: "green",
})
queryClient.invalidateQueries({ queryKey: ["issues"] })
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const deleteIssueSubtask = (issueIdOrKey: string): Promise<void> =>
window.provider.deleteIssue(issueIdOrKey)
Loading

0 comments on commit 435c09b

Please sign in to comment.