plane/apps/app/components/issues/modal.tsx
Vamsi Kurama c9252c9713
dev: promote the develop to stage-release (#399)
* chore: new link endpoints

* chore: added created by info for link

* chore: cannot have empty state group

* feat: filtering for cycle and module issue and updated grouper function for grouping in modules and cycles (#342)

* docs: github integration (#346)

* fix: add pagination for github repositories endpoint (#345)

* fix: remove bot accounts from list api (#344)

* refactor: create new endpoints for date checking getting current upcoming and past cycles (#343)

* refactor: create new endpoints for date checking getting current upcoming and past cycles

* refactor: rename endpoint to match consistency

* fix: remove project slug (#340)

* refactor: update links to different endpoints (#338)

* chore: cycle validation services and constants added

* style: kanban board

* chore:  cycle type and services updated

* chore: completed cycle dynamic importing and refactor

* feat: cycle modal date validation

* fix: build fix

* style: redesigned sidebar, added new icons and spacing changes

* style: changed app header color to white

* feat: cover image selector for project create

* style/projects_page

* style: added dragging state design

* fix: cycle form date

* chore: draft cycle services and types

* feat: draft tab and cycle sidebar update

* style: projects list page

* fix: image aspect ratio

* style: assignee drop down label

* style: new primary button design

* style: assignee dropdown

* style: assignee dropdown stlye fix

* style: state dropdown redesign

* style: dropdown ui consisteny

* style: priority dropdown redesign

* style: label dropdown redesign

* style: issue dropdown re-order

* style: state Icon

* style: date dropdown redesign

* fix: dropdown issue label

* style: transsition

* style: color fixed

* chore: labels list file and function rename

* style: redesigned create project modal

style: changed image picker to pop-over instread of modal

* fix: upload button on workspace settings page not working, UX of workspace settings image upload

* feat: date range status function added

* style: project settings pages

* fix: merge conflicts

* fix: mutation fix and date range helper fn added

* style: workspace settings pages

* style: dropdowns, feat: favorite projects in sidebar

* feat: global component for combobox with new design

* feat: custom context menu for issues in kanban board

* refactor: global context menu component

* chore: updated context menu component

* chore: updated sidebar selects

* style: kanban horizontal scrollbar added (#372)

* style: new cycle list (#374)

* feat: short date helper function

* feat: linear progress indicator added

* style: new cyce list and cycle card design

* feat: short date function improve

* feat: linear progress indicator improvement

* style: cycle card and progress indicator

* fix: helper date function and progress indicator fix

* fix: build error

---------

Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>

* chore: updated project favorites endpoints (#375)

* feat: favorite cycle and style: style improvements (#376)

* style: consistent btn

* style: caret direction for disclosure

* fix: progress tooltip value rounded

* chore: favorite cycle serivces

* chore: favorite cycle type and constant

* feat: favorite cycle feat added

* refactor: favorite services and type

* fix: build fix

* refactor: sidebar projects menu (#377)

* feat: add endpoint for draft cycles and add validation for creating draft cycles (#355)

* feat: add endpoint for draft cycles and add validation for creating draft cycles

* fix: key error in cycle create endpoint

* feat: delete file assets from storage (#373)

* chore: rename past cycle to completed cycle (#347)

* fix: workspace member listing endpoint (#348)

* fix: module issue viewset typo (#349)

* feat: add project to favourites (#352)

* feat: add project to favourites

* feat: add project is_favourite attribute to list endpoints

* refactor: updated destroy endpoint to send project_id

* chore: nomenclature update

* feat: add cover image to project (#353)

* fix: cycle date filtering for current and upcoming cycle (#357)

* fix: update filtering for completed cycles

* fix: filter updated for upcoming cycles

* fix: cycle and module issue filtering (#363)

* feat: already exisiting  url validation (#368)

* feat: cycle favourites for user (#369)

* feat: cycle favourites for user

* chore: update nomenclature

* chore: update on nomenclature

* feat: add favorites for completed and current cycle endpoints

* feat: module favourites for user (#370)

* feat: added floating toolbar on text selection (#378)

style: re-designed create-issue modal

* dev: migrations added for ProjectFavorite, ModuleFavorite, CycleFavorite including a bunch of other attribs

* chore: cycles loading, fix: cycles favorite mutation (#379)

* style: cycle sidebar, fix: cycle card bug fix   (#383)

* style: new cycle sidebar

* style: other information section

* style: progress bar bg fix

* fix: cycle card bug fix

* style: progress chart

* style: chart tooltip

* style : module sidebar (#385)

* style: new cycle sidebar

* style: other information section

* style: progress bar bg fix

* fix: cycle card bug fix

* style: progress chart

* style: chart tooltip

* style: module link tab added in sidebar stats

* style: lead and member select

* fix: text selection moving when typing in between (#384)

* feat: added floating toolbar on text selection (#386)

style: re-designed create-issue modal

* style :module list (#387)

* chore: module favorite type and services

* style: module list

* style: module list and card

* fix: link fix

* style: truncate (#388)

* style: truncate

* fix: truncate text added to cycle and module card

* fix: custom menu link item (#390)

* fix: ui fixes (#392)

* fix: ui fixes

* chore: kanban issue title length

* style: ui fix (#393)

* style: truncate

* fix: truncate text added to cycle and module card

* fix: progress percentage

* feat: cycle card tooltip

* fix: sidebar fix

* fix: edit module mutation error (#394)

* fix: issue details mutation (#389)

* fix: ui improvement (#395)

* fix: current cycle date updation

* fix: sidebar overflow fix , date helper fn added

* chore: update module dropdowns (#396)

* fix: project member filter for bot accounts (#391)

* fix: make api token only view once (#382)

* dev: add back migration for project cover images (#381)

* fix: rename db host name for docker setup (#380)

* dev: promote to staging (#397)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
Co-authored-by: pablohashescobar <118773738+pablohashescobar@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia1001@gmail.com>
Co-authored-by: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com>
Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>
Co-authored-by: Narayana <narayana.vadapalli1996@gmail.com>

* Revert "dev: promote to staging (#397)" (#398)

This reverts commit f7405ba1d6.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>
Co-authored-by: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com>
Co-authored-by: pablohashescobar <118773738+pablohashescobar@users.noreply.github.com>
Co-authored-by: sphynxux <122926002+sphynxux@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@caravel.tech>
Co-authored-by: Dakshesh Jain <dakshesh.jain14@gmail.com>
Co-authored-by: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia1001@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Narayana <narayana.vadapalli1996@gmail.com>
2023-03-08 01:07:00 +05:30

264 lines
8.4 KiB
TypeScript

import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
import useSWR, { mutate } from "swr";
// headless ui
import { Dialog, Transition } from "@headlessui/react";
// services
import projectService from "services/project.service";
import modulesService from "services/modules.service";
import issuesService from "services/issues.service";
// hooks
import useUser from "hooks/use-user";
import useToast from "hooks/use-toast";
// components
import { IssueForm } from "components/issues";
// types
import type { IIssue } from "types";
// fetch keys
import {
PROJECT_ISSUES_DETAILS,
PROJECT_ISSUES_LIST,
CYCLE_ISSUES,
USER_ISSUE,
PROJECTS_LIST,
MODULE_ISSUES,
SUB_ISSUES,
} from "constants/fetch-keys";
export interface IssuesModalProps {
isOpen: boolean;
handleClose: () => void;
data?: IIssue | null;
prePopulateData?: Partial<IIssue>;
isUpdatingSingleIssue?: boolean;
}
export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
isOpen,
handleClose,
data,
prePopulateData,
isUpdatingSingleIssue = false,
}) => {
// states
const [createMore, setCreateMore] = useState(false);
const [activeProject, setActiveProject] = useState<string | null>(null);
const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
if (cycleId) prePopulateData = { ...prePopulateData, cycle: cycleId as string };
if (moduleId) prePopulateData = { ...prePopulateData, module: moduleId as string };
const { user } = useUser();
const { setToastAlert } = useToast();
const { data: issues } = useSWR(
workspaceSlug && activeProject
? PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? "")
: null,
workspaceSlug && activeProject
? () => issuesService.getIssues(workspaceSlug as string, activeProject ?? "")
: null
);
const { data: projects } = useSWR(
workspaceSlug ? PROJECTS_LIST(workspaceSlug as string) : null,
workspaceSlug ? () => projectService.getProjects(workspaceSlug as string) : null
);
useEffect(() => {
if (projects && projects.length > 0)
setActiveProject(projects?.find((p) => p.id === projectId)?.id ?? projects?.[0].id ?? null);
}, [projectId, projects]);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === "Escape") {
handleClose();
}
};
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [handleClose]);
const addIssueToCycle = async (issueId: string, cycleId: string) => {
if (!workspaceSlug || !projectId) return;
await issuesService
.addIssueToCycle(workspaceSlug as string, activeProject ?? "", cycleId, {
issues: [issueId],
})
.then((res) => {
mutate(CYCLE_ISSUES(cycleId));
if (isUpdatingSingleIssue) {
mutate<IIssue>(
PROJECT_ISSUES_DETAILS,
(prevData) => ({ ...(prevData as IIssue), sprints: cycleId }),
false
);
} else
mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? ""),
(prevData) =>
(prevData ?? []).map((i) => {
if (i.id === res.id) return { ...i, sprints: cycleId };
return i;
}),
false
);
})
.catch((err) => {
console.log(err);
});
};
const addIssueToModule = async (issueId: string, moduleId: string) => {
if (!workspaceSlug || !projectId) return;
await modulesService
.addIssuesToModule(workspaceSlug as string, activeProject ?? "", moduleId as string, {
issues: [issueId],
})
.then((res) => {
console.log(res);
mutate(MODULE_ISSUES(moduleId as string));
})
.catch((e) => console.log(e));
};
const createIssue = async (payload: Partial<IIssue>) => {
await issuesService
.createIssues(workspaceSlug as string, activeProject ?? "", payload)
.then((res) => {
mutate(PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? ""));
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
if (payload.module && payload.module !== "") addIssueToModule(res.id, payload.module);
if (!createMore) handleClose();
setToastAlert({
type: "success",
title: "Success!",
message: "Issue created successfully.",
});
if (payload.assignees_list?.some((assignee) => assignee === user?.id)) mutate(USER_ISSUE);
if (payload.parent && payload.parent !== "") mutate(SUB_ISSUES(payload.parent));
})
.catch(() => {
setToastAlert({
type: "error",
title: "Error!",
message: "Issue could not be created. Please try again.",
});
});
};
const updateIssue = async (payload: Partial<IIssue>) => {
await issuesService
.updateIssue(workspaceSlug as string, activeProject ?? "", data?.id ?? "", payload)
.then((res) => {
if (isUpdatingSingleIssue) {
mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
} else {
mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? ""),
(prevData) =>
(prevData ?? []).map((i) => {
if (i.id === res.id) return { ...i, ...res };
return i;
})
);
}
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
if (payload.module && payload.module !== "") addIssueToModule(res.id, payload.module);
if (!createMore) handleClose();
setToastAlert({
type: "success",
title: "Success!",
message: "Issue updated successfully.",
});
})
.catch(() => {
setToastAlert({
type: "error",
title: "Error!",
message: "Issue could not be updated. Please try again.",
});
});
};
const handleFormSubmit = async (formData: Partial<IIssue>) => {
if (!workspaceSlug || !activeProject) return;
const payload: Partial<IIssue> = {
...formData,
assignees_list: formData.assignees,
labels_list: formData.labels,
description: formData.description ?? "",
description_html: formData.description_html ?? "<p></p>",
};
if (!data) await createIssue(payload);
else await updateIssue(payload);
};
return (
<Transition.Root show={isOpen} as={React.Fragment}>
<Dialog as="div" className="relative z-20" onClose={() => {}}>
<Transition.Child
as={React.Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="mt-10 flex min-h-full items-start justify-center p-4 text-center sm:p-0 md:mt-20">
<Transition.Child
as={React.Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative transform rounded-lg bg-white p-5 text-left shadow-xl transition-all sm:w-full sm:max-w-2xl">
<IssueForm
issues={issues ?? []}
handleFormSubmit={handleFormSubmit}
initialData={prePopulateData}
createMore={createMore}
setCreateMore={setCreateMore}
handleClose={handleClose}
projectId={activeProject ?? ""}
setActiveProject={setActiveProject}
status={data ? true : false}
/>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
};