forked from github/plane
9075f9441c
* style: added cta at the bottom of sidebar, added missing icons as well, showing dynamic workspace member count on workspace dropdown * refractor: running parallel request, made create/edit label function to async function * fix: sidebar dropdown content going below kanban items outside click detection in need help dropdown * refractor: making parallel api calls fix: create state input comes at bottom, create state input gets on focus automatically, form is getting submitted on enter click * refactoring file structure and signin page * style: changed text and added spinner for signing in loading * refractor: removed unused type * fix: my issue cta in profile page sending to 404 page * fix: added new s3 bucket url in next.config.js file increased image modal height * packaging UI components * eslint config * eslint fixes * refactoring changes * build fixes * minor fixes * adding todo comments for reference * refactor: cleared unused imports and re ordered imports * refactor: removed unused imports * fix: added workspace argument to useissues hook * refactor: removed api-routes file, unnecessary constants * refactor: created helpers folder, removed unnecessary constants * refactor: new context for issue view * refactoring issues page * build fixes * refactoring * refactor: create issue modal * refactor: module ui * fix: sub-issues mutation * fix: create more option in create issue modal * description form debounce issue * refactor: global component for assignees list * fix: link module interface * fix: priority icons and sub-issues count added * fix: cycle mutation in issue details page * fix: remove issue from cycle mutation * fix: create issue modal in home page * fix: removed unnecessary props * fix: updated create issue form status * fix: settings auth breaking * refactor: issue details page Co-authored-by: Dakshesh Jain <dakshesh.jain14@gmail.com> Co-authored-by: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com> Co-authored-by: venkatesh-soulpage <venkatesh.marreboyina@soulpageit.com> Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com> Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia1001@gmail.com>
187 lines
6.1 KiB
TypeScript
187 lines
6.1 KiB
TypeScript
import React, { useState } from "react";
|
|
|
|
import { useRouter } from "next/router";
|
|
|
|
import useSWR from "swr";
|
|
|
|
// react-beautiful-dnd
|
|
import { Draggable } from "react-beautiful-dnd";
|
|
// services
|
|
import workspaceService from "services/workspace.service";
|
|
// components
|
|
import SingleIssue from "components/common/board-view/single-issue";
|
|
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
|
import BoardHeader from "components/common/board-view/board-header";
|
|
// ui
|
|
import { CustomMenu } from "components/ui";
|
|
// icons
|
|
import { PlusIcon } from "@heroicons/react/24/outline";
|
|
// types
|
|
import { IIssue, IWorkspaceMember, NestedKeyOf, Properties } from "types";
|
|
// fetch-keys
|
|
import { WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
|
|
|
type Props = {
|
|
properties: Properties;
|
|
groupedByIssues: {
|
|
[key: string]: IIssue[];
|
|
};
|
|
selectedGroup: NestedKeyOf<IIssue> | null;
|
|
groupTitle: string;
|
|
createdBy: string | null;
|
|
bgColor?: string;
|
|
openCreateIssueModal: (issue?: IIssue, actionType?: "create" | "edit" | "delete") => void;
|
|
openIssuesListModal: () => void;
|
|
removeIssueFromCycle: (bridgeId: string) => void;
|
|
partialUpdateIssue: (formData: Partial<IIssue>, issueId: string) => void;
|
|
handleDeleteIssue: React.Dispatch<React.SetStateAction<string | undefined>>;
|
|
setPreloadedData: React.Dispatch<
|
|
React.SetStateAction<
|
|
| (Partial<IIssue> & {
|
|
actionType: "createIssue" | "edit" | "delete";
|
|
})
|
|
| null
|
|
>
|
|
>;
|
|
stateId: string | null;
|
|
};
|
|
|
|
const SingleModuleBoard: React.FC<Props> = ({
|
|
properties,
|
|
groupedByIssues,
|
|
selectedGroup,
|
|
groupTitle,
|
|
createdBy,
|
|
bgColor,
|
|
openCreateIssueModal,
|
|
openIssuesListModal,
|
|
removeIssueFromCycle,
|
|
partialUpdateIssue,
|
|
handleDeleteIssue,
|
|
setPreloadedData,
|
|
stateId,
|
|
}) => {
|
|
// collapse/expand
|
|
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
|
|
const router = useRouter();
|
|
|
|
const { workspaceSlug } = router.query;
|
|
|
|
if (selectedGroup === "priority")
|
|
groupTitle === "high"
|
|
? (bgColor = "#dc2626")
|
|
: groupTitle === "medium"
|
|
? (bgColor = "#f97316")
|
|
: groupTitle === "low"
|
|
? (bgColor = "#22c55e")
|
|
: (bgColor = "#ff0000");
|
|
|
|
const { data: people } = useSWR<IWorkspaceMember[]>(
|
|
workspaceSlug ? WORKSPACE_MEMBERS : null,
|
|
workspaceSlug ? () => workspaceService.workspaceMembers(workspaceSlug as string) : null
|
|
);
|
|
|
|
return (
|
|
<div className={`h-full flex-shrink-0 rounded ${!isCollapsed ? "" : "w-80 border bg-gray-50"}`}>
|
|
<div className={`${!isCollapsed ? "" : "flex h-full flex-col space-y-3 overflow-y-auto"}`}>
|
|
<BoardHeader
|
|
addIssueToState={() => {
|
|
openCreateIssueModal();
|
|
if (selectedGroup !== null) {
|
|
setPreloadedData({
|
|
state: stateId !== null ? stateId : undefined,
|
|
[selectedGroup]: groupTitle,
|
|
actionType: "createIssue",
|
|
});
|
|
}
|
|
}}
|
|
bgColor={bgColor ?? ""}
|
|
createdBy={createdBy}
|
|
groupTitle={groupTitle}
|
|
groupedByIssues={groupedByIssues}
|
|
isCollapsed={isCollapsed}
|
|
setIsCollapsed={setIsCollapsed}
|
|
selectedGroup={selectedGroup}
|
|
/>
|
|
<StrictModeDroppable key={groupTitle} droppableId={groupTitle}>
|
|
{(provided, snapshot) => (
|
|
<div
|
|
className={`mt-3 h-full space-y-3 overflow-y-auto px-3 pb-3 ${
|
|
snapshot.isDraggingOver ? "bg-indigo-50 bg-opacity-50" : ""
|
|
} ${!isCollapsed ? "hidden" : "block"}`}
|
|
{...provided.droppableProps}
|
|
ref={provided.innerRef}
|
|
>
|
|
{groupedByIssues[groupTitle].map((childIssue, index: number) => {
|
|
const assignees = [
|
|
...(childIssue?.assignees_list ?? []),
|
|
...(childIssue?.assignees ?? []),
|
|
]?.map((assignee) => {
|
|
const tempPerson = people?.find((p) => p.member.id === assignee)?.member;
|
|
|
|
return tempPerson;
|
|
});
|
|
|
|
return (
|
|
<Draggable key={childIssue.id} draggableId={childIssue.id} index={index}>
|
|
{(provided, snapshot) => (
|
|
<div
|
|
ref={provided.innerRef}
|
|
{...provided.draggableProps}
|
|
{...provided.dragHandleProps}
|
|
>
|
|
<SingleIssue
|
|
issue={childIssue}
|
|
properties={properties}
|
|
snapshot={snapshot}
|
|
assignees={assignees}
|
|
people={people}
|
|
partialUpdateIssue={partialUpdateIssue}
|
|
handleDeleteIssue={handleDeleteIssue}
|
|
/>
|
|
</div>
|
|
)}
|
|
</Draggable>
|
|
);
|
|
})}
|
|
{provided.placeholder}
|
|
<CustomMenu
|
|
label={
|
|
<span className="flex items-center gap-1">
|
|
<PlusIcon className="h-3 w-3" />
|
|
Add issue
|
|
</span>
|
|
}
|
|
className="mt-1"
|
|
optionsPosition="left"
|
|
noBorder
|
|
>
|
|
<CustomMenu.MenuItem
|
|
onClick={() => {
|
|
openCreateIssueModal();
|
|
if (selectedGroup !== null) {
|
|
setPreloadedData({
|
|
state: stateId !== null ? stateId : undefined,
|
|
[selectedGroup]: groupTitle,
|
|
actionType: "createIssue",
|
|
});
|
|
}
|
|
}}
|
|
>
|
|
Create new
|
|
</CustomMenu.MenuItem>
|
|
<CustomMenu.MenuItem onClick={() => openIssuesListModal()}>
|
|
Add an existing issue
|
|
</CustomMenu.MenuItem>
|
|
</CustomMenu>
|
|
</div>
|
|
)}
|
|
</StrictModeDroppable>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SingleModuleBoard;
|