code refactor kanban for better mainatinability

This commit is contained in:
rahulramesha 2023-12-13 18:51:09 +05:30
parent 71381330b1
commit 56ac4d8ab1
16 changed files with 301 additions and 1631 deletions

View File

@ -26,8 +26,6 @@ import { IQuickActionProps } from "../list/list-view-types";
import { IIssueKanBanViewStore } from "store_legacy/issue";
// hooks
import useToast from "hooks/use-toast";
// constants
import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
//components
import { KanBan } from "./default";
import { KanBanSwimLanes } from "./swimlanes";
@ -95,13 +93,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
const router = useRouter();
const { workspaceSlug, peekIssueId, peekProjectId } = router.query;
// mobx store
const {
project: { workspaceProjects },
projectLabel: { projectLabels },
projectMember: { projectMembers },
projectState: projectStateStore,
user: userStore,
} = useMobxStore();
const { user: userStore } = useMobxStore();
// hooks
const { setToastAlert } = useToast();
@ -185,7 +177,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
};
const handleIssues = useCallback(
async (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => {
async (issue: IIssue, action: EIssueActions) => {
if (issueActions[action]) {
await issueActions[action]!(issue);
}
@ -193,6 +185,20 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
[issueActions]
);
const renderQuickActions = (issue: IIssue, customActionButton?: React.ReactElement) => (
<QuickActions
customActionButton={customActionButton}
issue={issue}
handleDelete={async () => handleIssues(issue, EIssueActions.DELETE)}
handleUpdate={
issueActions[EIssueActions.UPDATE] ? async (data) => handleIssues(data, EIssueActions.UPDATE) : undefined
}
handleRemoveFromView={
issueActions[EIssueActions.REMOVE] ? async () => handleIssues(issue, EIssueActions.REMOVE) : undefined
}
/>
);
const handleDeleteIssue = async () => {
if (!handleDragDrop) return;
await handleDragDrop(dragState.source, dragState.destination, sub_group_by, group_by, issues, issueIds).finally(
@ -207,10 +213,6 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
kanbanViewStore.handleKanBanToggle(toggle, value);
};
const states = projectStateStore?.projectStates || null;
const priorities = ISSUE_PRIORITIES || null;
const stateGroups = ISSUE_STATE_GROUPS || null;
return (
<>
<DeleteIssueModal
@ -256,37 +258,13 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue, customActionButton) => (
<QuickActions
customActionButton={customActionButton}
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, EIssueActions.DELETE)}
handleUpdate={
issueActions[EIssueActions.UPDATE]
? async (data) => handleIssues(sub_group_by, group_by, data, EIssueActions.UPDATE)
: undefined
}
handleRemoveFromView={
issueActions[EIssueActions.REMOVE]
? async () => handleIssues(sub_group_by, group_by, issue, EIssueActions.REMOVE)
: undefined
}
/>
)}
quickActions={renderQuickActions}
displayProperties={displayProperties}
kanBanToggle={kanbanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={projectLabels}
members={projectMembers?.map((m) => m.member) ?? null}
projects={workspaceProjects}
enableQuickIssueCreate={enableQuickAdd}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
quickAddCallback={issueStore?.quickAddIssue}
viewId={viewId}
disableIssueCreation={!enableIssueCreation || !isEditingAllowed}
@ -302,32 +280,10 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
group_by={group_by}
order_by={order_by}
handleIssues={handleIssues}
quickActions={(sub_group_by, group_by, issue, customActionButton) => (
<QuickActions
customActionButton={customActionButton}
issue={issue}
handleDelete={async () => handleIssues(sub_group_by, group_by, issue, EIssueActions.DELETE)}
handleUpdate={
issueActions[EIssueActions.UPDATE]
? async (data) => handleIssues(sub_group_by, group_by, data, EIssueActions.UPDATE)
: undefined
}
handleRemoveFromView={
issueActions[EIssueActions.REMOVE]
? async () => handleIssues(sub_group_by, group_by, issue, EIssueActions.REMOVE)
: undefined
}
/>
)}
quickActions={renderQuickActions}
displayProperties={displayProperties}
kanBanToggle={kanbanViewStore?.kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={projectLabels}
members={projectMembers?.map((m) => m.member) ?? null}
projects={workspaceProjects}
showEmptyGroup={userDisplayFilters?.show_empty_groups || true}
isDragStarted={isDragStarted}
disableIssueCreation={!enableIssueCreation || !isEditingAllowed}
@ -346,9 +302,7 @@ export const BaseKanBanRoot: React.FC<IBaseKanBanLayout> = observer((props: IBas
workspaceSlug={workspaceSlug.toString()}
projectId={peekProjectId.toString()}
issueId={peekIssueId.toString()}
handleIssue={async (issueToUpdate) =>
await handleIssues(sub_group_by, group_by, issueToUpdate as IIssue, EIssueActions.UPDATE)
}
handleIssue={async (issueToUpdate) => await handleIssues(issueToUpdate as IIssue, EIssueActions.UPDATE)}
/>
)}
</>

View File

@ -17,31 +17,28 @@ interface IssueBlockProps {
issue: IIssue;
isDragDisabled: boolean;
showEmptyGroup: boolean;
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
handleIssues: (issue: IIssue, action: EIssueActions) => void;
quickActions: (issue: IIssue) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null;
canEditProperties: (projectId: string | undefined) => boolean;
}
interface IssueDetailsBlockProps {
sub_group_id: string;
columnId: string;
issue: IIssue;
showEmptyGroup: boolean;
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
handleIssues: (issue: IIssue, action: EIssueActions) => void;
quickActions: (issue: IIssue) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null;
isReadOnly: boolean;
}
const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = (props) => {
const { sub_group_id, columnId, issue, showEmptyGroup, handleIssues, quickActions, displayProperties, isReadOnly } =
props;
const { issue, showEmptyGroup, handleIssues, quickActions, displayProperties, isReadOnly } = props;
const router = useRouter();
const updateIssue = (sub_group_by: string | null, group_by: string | null, issueToUpdate: IIssue) => {
if (issueToUpdate) handleIssues(sub_group_by, group_by, issueToUpdate, EIssueActions.UPDATE);
const updateIssue = (issueToUpdate: IIssue) => {
if (issueToUpdate) handleIssues(issueToUpdate, EIssueActions.UPDATE);
};
const handleIssuePeekOverview = () => {
@ -60,13 +57,7 @@ const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = (props) => {
<div className="line-clamp-1 text-xs text-custom-text-300">
{issue.project_detail.identifier}-{issue.sequence_id}
</div>
<div className="absolute -top-1 right-0 hidden group-hover/kanban-block:block">
{quickActions(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!columnId && columnId === "null" ? null : columnId,
issue
)}
</div>
<div className="absolute -top-1 right-0 hidden group-hover/kanban-block:block">{quickActions(issue)}</div>
</div>
)}
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
@ -76,8 +67,6 @@ const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = (props) => {
</Tooltip>
<div>
<KanBanProperties
sub_group_id={sub_group_id}
columnId={columnId}
issue={issue}
handleIssues={updateIssue}
displayProperties={displayProperties}
@ -138,8 +127,6 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
} ${snapshot.isDragging ? `border-custom-primary-100` : `border-transparent`}`}
>
<KanbanIssueMemoBlock
sub_group_id={sub_group_id}
columnId={columnId}
issue={issue}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}

View File

@ -11,13 +11,8 @@ interface IssueBlocksListProps {
issueIds: string[];
isDragDisabled: boolean;
showEmptyGroup: boolean;
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
quickActions: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
customActionButton?: React.ReactElement
) => React.ReactNode;
handleIssues: (issue: IIssue, action: EIssueActions) => void;
quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null;
canEditProperties: (projectId: string | undefined) => boolean;
}
@ -62,13 +57,7 @@ export const KanbanIssueBlocksList: React.FC<IssueBlocksListProps> = (props) =>
);
})}
</>
) : (
!isDragDisabled && (
<div className="absolute left-0 top-0 flex h-full w-full items-center justify-center">
{/* <div className="text-custom-text-300 text-sm">Drop here</div> */}
</div>
)
)}
) : null}
</>
);
};

View File

@ -4,12 +4,12 @@ import { Droppable } from "@hello-pangea/dnd";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { KanBanGroupByHeaderRoot } from "./headers/group-by-root";
import { KanbanIssueBlocksList, KanBanQuickAddIssueForm } from "components/issues";
import { HeaderGroupByCard } from "./headers/group-by-card";
// types
import { IIssueDisplayProperties, IIssue, IState } from "types";
import { IIssueDisplayProperties, IIssue } from "types";
// constants
import { getValueFromObject } from "constants/issue";
import { columnTypes, getKanbanColumns, IKanbanColumn } from "./utils";
import { EIssueActions } from "../types";
import { IIssueResponse, IGroupedIssues, ISubGroupedIssues, TUnGroupedIssues } from "store_legacy/issues/types";
import { EProjectStore } from "store_legacy/command-palette.store";
@ -19,25 +19,15 @@ export interface IGroupByKanBan {
issueIds: any;
sub_group_by: string | null;
group_by: string | null;
order_by: string | null;
sub_group_id: string;
list: any;
listKey: string;
states: IState[] | null;
isDragDisabled: boolean;
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
handleIssues: (issue: IIssue, action: EIssueActions) => void;
showEmptyGroup: boolean;
quickActions: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
customActionButton?: React.ReactElement
) => React.ReactNode;
quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null;
kanBanToggle: any;
handleKanBanToggle: any;
enableQuickIssueCreate?: boolean;
isDragStarted?: boolean;
quickAddCallback?: (
workspaceSlug: string,
projectId: string,
@ -57,11 +47,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
issueIds,
sub_group_by,
group_by,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
order_by,
sub_group_id = "null",
list,
listKey,
isDragDisabled,
handleIssues,
showEmptyGroup,
@ -70,8 +56,6 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
kanBanToggle,
handleKanBanToggle,
enableQuickIssueCreate,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isDragStarted,
quickAddCallback,
viewId,
disableIssueCreation,
@ -80,27 +64,34 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
canEditProperties,
} = props;
const verticalAlignPosition = (_list: any) =>
kanBanToggle?.groupByHeaderMinMax.includes(getValueFromObject(_list, listKey) as string);
const { project, projectLabel, projectMember, projectState } = useMobxStore();
const list = getKanbanColumns(group_by as columnTypes, project, projectLabel, projectMember, projectState);
if (!list) return null;
const verticalAlignPosition = (_list: IKanbanColumn) => kanBanToggle?.groupByHeaderMinMax.includes(_list.id);
return (
<div className="relative flex h-full w-full gap-3">
{list &&
list.length > 0 &&
list.map((_list: any) => (
list.map((_list: IKanbanColumn) => (
<div
className={`relative flex flex-shrink-0 flex-col ${!verticalAlignPosition(_list) ? `w-[340px]` : ``} group`}
>
{sub_group_by === null && (
<div className="sticky top-0 z-[2] w-full flex-shrink-0 bg-custom-background-90 py-1">
<KanBanGroupByHeaderRoot
column_id={getValueFromObject(_list, listKey) as string}
column_value={_list}
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
issues_count={issueIds?.[getValueFromObject(_list, listKey) as string]?.length || 0}
column_id={_list.id}
icon={_list.Icon}
title={_list.name}
count={issueIds?.[_list.id]?.length || 0}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
issuePayload={_list.payload}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
@ -113,7 +104,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
verticalAlignPosition(_list) ? `min-h-[150px] w-[0px] overflow-hidden` : `w-full transition-all`
}`}
>
<Droppable droppableId={`${getValueFromObject(_list, listKey) as string}__${sub_group_id}`}>
<Droppable droppableId={`${_list.id}__${sub_group_id}`}>
{(provided: any, snapshot: any) => (
<div
className={`relative h-full w-full transition-all ${
@ -125,9 +116,9 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
{issues && !verticalAlignPosition(_list) ? (
<KanbanIssueBlocksList
sub_group_id={sub_group_id}
columnId={getValueFromObject(_list, listKey) as string}
columnId={_list.id}
issues={issues}
issueIds={issueIds?.[getValueFromObject(_list, listKey) as string] || []}
issueIds={issueIds?.[_list.id] || []}
isDragDisabled={isDragDisabled}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
@ -135,13 +126,7 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
displayProperties={displayProperties}
canEditProperties={canEditProperties}
/>
) : (
isDragDisabled && (
<div className="absolute left-0 top-0 flex h-full w-full items-center justify-center text-sm">
{/* <div className="text-custom-text-300 text-sm">Drop here</div> */}
</div>
)
)}
) : null}
{provided.placeholder}
</div>
@ -152,10 +137,10 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
{enableQuickIssueCreate && !disableIssueCreation && (
<KanBanQuickAddIssueForm
formKey="name"
groupId={getValueFromObject(_list, listKey) as string}
groupId={_list.id}
subGroupId={sub_group_id}
prePopulatedData={{
...(group_by && { [group_by]: getValueFromObject(_list, listKey) }),
...(group_by && { [group_by]: _list.id }),
...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }),
}}
quickAddCallback={quickAddCallback}
@ -164,16 +149,6 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
)}
</div>
</div>
{/* {isDragStarted && isDragDisabled && (
<div className="invisible group-hover:visible transition-all text-sm absolute top-12 bottom-10 left-0 right-0 bg-custom-background-100/40 text-center">
<div className="rounded inline-flex mt-80 h-8 px-3 justify-center items-center bg-custom-background-80 text-custom-text-100 font-medium">
{`This board is ordered by "${replaceUnderscoreIfSnakeCase(
order_by ? (order_by[0] === "-" ? order_by.slice(1) : order_by) : "created_at"
)}"`}
</div>
</div>
)} */}
</div>
))}
</div>
@ -185,27 +160,14 @@ export interface IKanBan {
issueIds: IGroupedIssues | ISubGroupedIssues | TUnGroupedIssues;
sub_group_by: string | null;
group_by: string | null;
order_by: string | null;
sub_group_id?: string;
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
quickActions: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
customActionButton?: React.ReactElement
) => React.ReactNode;
handleIssues: (issue: IIssue, action: EIssueActions) => void;
quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null;
kanBanToggle: any;
handleKanBanToggle: any;
showEmptyGroup: boolean;
states: any;
stateGroups: any;
priorities: any;
labels: any;
members: any;
projects: any;
enableQuickIssueCreate?: boolean;
isDragStarted?: boolean;
quickAddCallback?: (
workspaceSlug: string,
projectId: string,
@ -225,7 +187,6 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
issueIds,
sub_group_by,
group_by,
order_by,
sub_group_id = "null",
handleIssues,
quickActions,
@ -233,14 +194,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
kanBanToggle,
handleKanBanToggle,
showEmptyGroup,
states,
stateGroups,
priorities,
labels,
members,
projects,
enableQuickIssueCreate,
isDragStarted,
quickAddCallback,
viewId,
disableIssueCreation,
@ -253,208 +207,27 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
return (
<div className="relative h-full w-full">
{group_by && group_by === "project" && (
<GroupByKanBan
issues={issues}
issueIds={issueIds}
group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by}
sub_group_id={sub_group_id}
list={projects}
listKey={`id`}
states={states}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
quickAddCallback={quickAddCallback}
viewId={viewId}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/>
)}
{group_by && group_by === "state" && (
<GroupByKanBan
issues={issues}
issueIds={issueIds}
group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by}
sub_group_id={sub_group_id}
list={states}
listKey={`id`}
states={states}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
quickAddCallback={quickAddCallback}
viewId={viewId}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/>
)}
{group_by && group_by === "state_detail.group" && (
<GroupByKanBan
issues={issues}
issueIds={issueIds}
group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by}
sub_group_id={sub_group_id}
list={stateGroups}
listKey={`key`}
states={states}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
quickAddCallback={quickAddCallback}
viewId={viewId}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/>
)}
{group_by && group_by === "priority" && (
<GroupByKanBan
issues={issues}
issueIds={issueIds}
group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by}
sub_group_id={sub_group_id}
list={priorities}
listKey={`key`}
states={states}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
quickAddCallback={quickAddCallback}
viewId={viewId}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/>
)}
{group_by && group_by === "labels" && (
<GroupByKanBan
issues={issues}
issueIds={issueIds}
group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by}
sub_group_id={sub_group_id}
list={labels ? [...labels, { id: "None", name: "None" }] : labels}
listKey={`id`}
states={states}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
quickAddCallback={quickAddCallback}
viewId={viewId}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/>
)}
{group_by && group_by === "assignees" && (
<GroupByKanBan
issues={issues}
issueIds={issueIds}
group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by}
sub_group_id={sub_group_id}
list={members ? [...members, { id: "None", display_name: "None" }] : members}
listKey={`id`}
states={states}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
quickAddCallback={quickAddCallback}
viewId={viewId}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/>
)}
{group_by && group_by === "created_by" && (
<GroupByKanBan
issues={issues}
issueIds={issueIds}
group_by={group_by}
order_by={order_by}
sub_group_by={sub_group_by}
sub_group_id={sub_group_id}
list={members}
listKey={`id`}
states={states}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
quickAddCallback={quickAddCallback}
viewId={viewId}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/>
)}
<GroupByKanBan
issues={issues}
issueIds={issueIds}
group_by={group_by}
sub_group_by={sub_group_by}
sub_group_id={sub_group_id}
isDragDisabled={!issueKanBanViewStore?.canUserDragDrop}
showEmptyGroup={showEmptyGroup}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
enableQuickIssueCreate={enableQuickIssueCreate}
quickAddCallback={quickAddCallback}
viewId={viewId}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
/>
</div>
);
});

View File

@ -1,74 +0,0 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
// components
import { HeaderGroupByCard } from "./group-by-card";
import { HeaderSubGroupByCard } from "./sub-group-by-card";
// ui
import { Avatar } from "@plane/ui";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface IAssigneesHeader {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
header_type: "group_by" | "sub_group_by";
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
export const Icon = ({ user }: any) => <Avatar name={user.display_name} src={user.avatar} size="md" />;
export const AssigneesHeader: FC<IAssigneesHeader> = observer((props) => {
const {
column_id,
column_value,
sub_group_by,
group_by,
header_type,
issues_count,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
} = props;
const assignee = column_value ?? null;
return (
<>
{assignee &&
(sub_group_by && header_type === "sub_group_by" ? (
<HeaderSubGroupByCard
column_id={column_id}
icon={<Icon user={assignee} />}
title={assignee?.display_name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
) : (
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
column_id={column_id}
icon={<Icon user={assignee} />}
title={assignee?.display_name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
issuePayload={{ assignees: [assignee?.id] }}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
))}
</>
);
});

View File

@ -1,71 +0,0 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
// components
import { HeaderGroupByCard } from "./group-by-card";
import { HeaderSubGroupByCard } from "./sub-group-by-card";
import { Icon } from "./assignee";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface ICreatedByHeader {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
header_type: "group_by" | "sub_group_by";
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
export const CreatedByHeader: FC<ICreatedByHeader> = observer((props) => {
const {
column_id,
column_value,
sub_group_by,
group_by,
header_type,
issues_count,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
} = props;
const createdBy = column_value ?? null;
return (
<>
{createdBy &&
(sub_group_by && header_type === "sub_group_by" ? (
<HeaderSubGroupByCard
column_id={column_id}
icon={<Icon user={createdBy} />}
title={createdBy?.display_name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
) : (
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
column_id={column_id}
icon={<Icon user={createdBy} />}
title={createdBy?.display_name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
issuePayload={{ created_by: createdBy?.id }}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
))}
</>
);
});

View File

@ -1,149 +0,0 @@
// components
import { ProjectHeader } from "./project";
import { StateHeader } from "./state";
import { StateGroupHeader } from "./state-group";
import { AssigneesHeader } from "./assignee";
import { PriorityHeader } from "./priority";
import { LabelHeader } from "./label";
import { CreatedByHeader } from "./created_by";
// mobx
import { observer } from "mobx-react-lite";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface IKanBanGroupByHeaderRoot {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
export const KanBanGroupByHeaderRoot: React.FC<IKanBanGroupByHeaderRoot> = observer(
({
column_id,
column_value,
sub_group_by,
group_by,
issues_count,
kanBanToggle,
disableIssueCreation,
handleKanBanToggle,
currentStore,
addIssuesToView,
}) => (
<>
{group_by && group_by === "project" && (
<ProjectHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "state" && (
<StateHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "state_detail.group" && (
<StateGroupHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "priority" && (
<PriorityHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "labels" && (
<LabelHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "assignees" && (
<AssigneesHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "created_by" && (
<CreatedByHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
</>
)
);

View File

@ -1,74 +0,0 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
// components
import { HeaderGroupByCard } from "./group-by-card";
import { HeaderSubGroupByCard } from "./sub-group-by-card";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface ILabelHeader {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
header_type: "group_by" | "sub_group_by";
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
const Icon = ({ color }: any) => (
<div className="h-[12px] w-[12px] rounded-full" style={{ backgroundColor: color ? color : "#666" }} />
);
export const LabelHeader: FC<ILabelHeader> = observer((props) => {
const {
column_id,
column_value,
sub_group_by,
group_by,
header_type,
issues_count,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
} = props;
const label = column_value ?? null;
return (
<>
{label &&
(sub_group_by && header_type === "sub_group_by" ? (
<HeaderSubGroupByCard
column_id={column_id}
icon={<Icon color={label?.color} />}
title={label?.name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
) : (
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
column_id={column_id}
icon={<Icon />}
title={label?.name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
issuePayload={{ labels: [label?.id] }}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
))}
</>
);
});

View File

@ -1,73 +0,0 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
// components
import { HeaderGroupByCard } from "./group-by-card";
import { HeaderSubGroupByCard } from "./sub-group-by-card";
// Icons
import { PriorityIcon } from "@plane/ui";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface IPriorityHeader {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
header_type: "group_by" | "sub_group_by";
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
export const PriorityHeader: FC<IPriorityHeader> = observer((props) => {
const {
column_id,
column_value,
sub_group_by,
group_by,
header_type,
issues_count,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
} = props;
const priority = column_value || null;
return (
<>
{priority &&
(sub_group_by && header_type === "sub_group_by" ? (
<HeaderSubGroupByCard
column_id={column_id}
icon={<PriorityIcon priority={priority?.key} />}
title={priority?.title || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
) : (
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
column_id={column_id}
icon={<PriorityIcon priority={priority?.key} />}
title={priority?.title || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
issuePayload={{ priority: priority?.key }}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
))}
</>
);
});

View File

@ -1,74 +0,0 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
// components
import { HeaderGroupByCard } from "./group-by-card";
import { HeaderSubGroupByCard } from "./sub-group-by-card";
// emoji helper
import { renderEmoji } from "helpers/emoji.helper";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface IProjectHeader {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
header_type: "group_by" | "sub_group_by";
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
const Icon = ({ emoji }: any) => <div className="h-6 w-6">{renderEmoji(emoji)}</div>;
export const ProjectHeader: FC<IProjectHeader> = observer((props) => {
const {
column_id,
column_value,
sub_group_by,
group_by,
header_type,
issues_count,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
} = props;
const project = column_value ?? null;
return (
<>
{project &&
(sub_group_by && header_type === "sub_group_by" ? (
<HeaderSubGroupByCard
column_id={column_id}
icon={<Icon emoji={project?.emoji} />}
title={project?.name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
) : (
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
column_id={column_id}
icon={<Icon emoji={project?.emoji} />}
title={project?.name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
issuePayload={{ project: project?.id }}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
))}
</>
);
});

View File

@ -1,77 +0,0 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
// components
import { HeaderGroupByCard } from "./group-by-card";
import { HeaderSubGroupByCard } from "./sub-group-by-card";
import { StateGroupIcon } from "@plane/ui";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface IStateGroupHeader {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
header_type: "group_by" | "sub_group_by";
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
export const Icon = ({ stateGroup, color }: { stateGroup: any; color?: any }) => (
<div className="h-3.5 w-3.5 rounded-full">
<StateGroupIcon stateGroup={stateGroup} color={color || null} width="14" height="14" />
</div>
);
export const StateGroupHeader: FC<IStateGroupHeader> = observer((props) => {
const {
column_id,
column_value,
sub_group_by,
group_by,
header_type,
issues_count,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
} = props;
const stateGroup = column_value || null;
return (
<>
{stateGroup &&
(sub_group_by && header_type === "sub_group_by" ? (
<HeaderSubGroupByCard
column_id={column_id}
icon={<Icon stateGroup={stateGroup?.key} />}
title={stateGroup?.key || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
) : (
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
column_id={column_id}
icon={<Icon stateGroup={stateGroup?.key} />}
title={stateGroup?.key || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
issuePayload={{}}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
))}
</>
);
});

View File

@ -1,71 +0,0 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
// components
import { HeaderGroupByCard } from "./group-by-card";
import { HeaderSubGroupByCard } from "./sub-group-by-card";
import { Icon } from "./state-group";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface IStateHeader {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
header_type: "group_by" | "sub_group_by";
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
export const StateHeader: FC<IStateHeader> = observer((props) => {
const {
column_id,
column_value,
sub_group_by,
group_by,
header_type,
issues_count,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
} = props;
const state = column_value ?? null;
return (
<>
{state &&
(sub_group_by && header_type === "sub_group_by" ? (
<HeaderSubGroupByCard
column_id={column_id}
icon={<Icon stateGroup={state?.group} color={state?.color} />}
title={state?.name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
/>
) : (
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
column_id={column_id}
icon={<Icon stateGroup={state?.group} color={state?.color} />}
title={state?.name || ""}
count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
issuePayload={{ state: state?.id }}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
))}
</>
);
});

View File

@ -1,134 +0,0 @@
// mobx
import { observer } from "mobx-react-lite";
// components
import { StateHeader } from "./state";
import { StateGroupHeader } from "./state-group";
import { AssigneesHeader } from "./assignee";
import { PriorityHeader } from "./priority";
import { LabelHeader } from "./label";
import { CreatedByHeader } from "./created_by";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IIssue } from "types";
export interface IKanBanSubGroupByHeaderRoot {
column_id: string;
column_value: any;
sub_group_by: string | null;
group_by: string | null;
issues_count: number;
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
export const KanBanSubGroupByHeaderRoot: React.FC<IKanBanSubGroupByHeaderRoot> = observer((props) => {
const {
column_id,
column_value,
sub_group_by,
group_by,
issues_count,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
} = props;
return (
<>
{sub_group_by && sub_group_by === "state" && (
<StateHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`sub_group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{sub_group_by && sub_group_by === "state_detail.group" && (
<StateGroupHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`sub_group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{sub_group_by && sub_group_by === "priority" && (
<PriorityHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`sub_group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{sub_group_by && sub_group_by === "labels" && (
<LabelHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`sub_group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{sub_group_by && sub_group_by === "assignees" && (
<AssigneesHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`sub_group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{sub_group_by && sub_group_by === "created_by" && (
<CreatedByHeader
column_id={column_id}
column_value={column_value}
sub_group_by={sub_group_by}
group_by={group_by}
header_type={`sub_group_by`}
issues_count={issues_count}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
</>
);
});

View File

@ -13,72 +13,42 @@ import { Tooltip } from "@plane/ui";
import { IIssue, IIssueDisplayProperties, IState, TIssuePriorities } from "types";
export interface IKanBanProperties {
sub_group_id: string;
columnId: string;
issue: IIssue;
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => void;
handleIssues: (issue: IIssue) => void;
displayProperties: IIssueDisplayProperties | null;
showEmptyGroup: boolean;
isReadOnly: boolean;
}
export const KanBanProperties: React.FC<IKanBanProperties> = observer((props) => {
const { sub_group_id, columnId: group_id, issue, handleIssues, displayProperties, isReadOnly } = props;
const { issue, handleIssues, displayProperties, isReadOnly } = props;
const handleState = (state: IState) => {
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, state: state.id }
);
handleIssues({ ...issue, state: state.id });
};
const handlePriority = (value: TIssuePriorities) => {
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, priority: value }
);
handleIssues({ ...issue, priority: value });
};
const handleLabel = (ids: string[]) => {
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, labels: ids }
);
handleIssues({ ...issue, labels: ids });
};
const handleAssignee = (ids: string[]) => {
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, assignees: ids }
);
handleIssues({ ...issue, assignees: ids });
};
const handleStartDate = (date: string) => {
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, start_date: date }
);
handleIssues({ ...issue, start_date: date });
};
const handleTargetDate = (date: string) => {
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, target_date: date }
);
handleIssues({ ...issue, target_date: date });
};
const handleEstimate = (value: number | null) => {
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, estimate_point: value }
);
handleIssues({ ...issue, estimate_point: value });
};
return (

View File

@ -1,71 +1,50 @@
import React from "react";
import { observer } from "mobx-react-lite";
// components
import { KanBanGroupByHeaderRoot } from "./headers/group-by-root";
import { KanBanSubGroupByHeaderRoot } from "./headers/sub-group-by-root";
import { KanBan } from "./default";
import { HeaderSubGroupByCard } from "./headers/sub-group-by-card";
import { HeaderGroupByCard } from "./headers/group-by-card";
// types
import { IIssue, IIssueDisplayProperties, IIssueLabel, IProject, IState, IUserLite } from "types";
import { IIssue, IIssueDisplayProperties } from "types";
import { IIssueResponse, IGroupedIssues, ISubGroupedIssues, TUnGroupedIssues } from "store_legacy/issues/types";
// constants
import { getValueFromObject } from "constants/issue";
import { EIssueActions } from "../types";
import { EProjectStore } from "store_legacy/command-palette.store";
import { IKanbanColumn, columnTypes, getKanbanColumns } from "./utils";
import { useMobxStore } from "lib/mobx/store-provider";
interface ISubGroupSwimlaneHeader {
issues: IIssueResponse;
issueIds: any;
sub_group_by: string | null;
group_by: string | null;
list: any;
listKey: string;
list: IKanbanColumn[];
kanBanToggle: any;
handleKanBanToggle: any;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
}
const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = ({
issueIds,
sub_group_by,
group_by,
list,
listKey,
kanBanToggle,
handleKanBanToggle,
disableIssueCreation,
currentStore,
addIssuesToView,
}) => {
const calculateIssueCount = (column_id: string) => {
let issueCount = 0;
issueIds &&
Object.keys(issueIds)?.forEach((_issueKey: any) => {
issueCount += issueIds?.[_issueKey]?.[column_id]?.length || 0;
});
return issueCount;
};
return (
<div className="relative flex h-max min-h-full w-full items-center">
{list &&
list.length > 0 &&
list.map((_list: any) => (
<div
key={`${sub_group_by}_${getValueFromObject(_list, listKey) as string}`}
className="flex w-[340px] flex-shrink-0 flex-col"
>
<KanBanGroupByHeaderRoot
column_id={getValueFromObject(_list, listKey) as string}
column_value={_list}
list.map((_list: IKanbanColumn) => (
<div key={`${sub_group_by}_${_list.id}`} className="flex w-[340px] flex-shrink-0 flex-col">
<HeaderGroupByCard
sub_group_by={sub_group_by}
group_by={group_by}
issues_count={calculateIssueCount(getValueFromObject(_list, listKey) as string)}
column_id={_list.id}
icon={_list.Icon}
title={_list.name}
count={issueIds?.[_list.id]?.length || 0}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
issuePayload={_list.payload}
/>
</div>
))}
@ -78,19 +57,8 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
issueIds: any;
order_by: string | null;
showEmptyGroup: boolean;
states: IState[] | null;
stateGroups: any;
priorities: any;
labels: IIssueLabel[] | null;
members: IUserLite[] | null;
projects: IProject[] | null;
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
quickActions: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
customActionButton?: React.ReactElement
) => React.ReactNode;
handleIssues: (issue: IIssue, action: EIssueActions) => void;
quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null;
kanBanToggle: any;
handleKanBanToggle: any;
@ -99,6 +67,7 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
currentStore?: EProjectStore;
enableQuickIssueCreate: boolean;
canEditProperties: (projectId: string | undefined) => boolean;
addIssuesToView?: (issueIds: string[]) => Promise<IIssue>;
quickAddCallback?: (
workspaceSlug: string,
projectId: string,
@ -112,23 +81,13 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
issueIds,
sub_group_by,
group_by,
order_by,
list,
listKey,
handleIssues,
quickActions,
displayProperties,
kanBanToggle,
handleKanBanToggle,
showEmptyGroup,
states,
stateGroups,
priorities,
labels,
members,
projects,
isDragStarted,
disableIssueCreation,
enableQuickIssueCreate,
canEditProperties,
addIssuesToView,
@ -152,43 +111,32 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
<div className="flex flex-shrink-0 flex-col">
<div className="sticky top-[50px] z-[1] flex w-full items-center bg-custom-background-90 py-1">
<div className="sticky left-0 flex-shrink-0 bg-custom-background-90 pr-2">
<KanBanSubGroupByHeaderRoot
column_id={getValueFromObject(_list, listKey) as string}
column_value={_list}
sub_group_by={sub_group_by}
group_by={group_by}
issues_count={calculateIssueCount(getValueFromObject(_list, listKey) as string)}
<HeaderSubGroupByCard
column_id={_list.id}
icon={_list.Icon}
title={_list.name || ""}
count={calculateIssueCount(_list.id)}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
addIssuesToView={addIssuesToView}
/>
</div>
<div className="w-full border-b border-dashed border-custom-border-400" />
</div>
{!kanBanToggle?.subgroupByIssuesVisibility.includes(getValueFromObject(_list, listKey) as string) && (
{!kanBanToggle?.subgroupByIssuesVisibility.includes(_list.id) && (
<div className="relative">
<KanBan
issues={issues}
issueIds={issueIds?.[getValueFromObject(_list, listKey) as string]}
issueIds={issueIds?.[_list.id]}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
sub_group_id={getValueFromObject(_list, listKey) as string}
sub_group_id={_list.id}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
enableQuickIssueCreate={enableQuickIssueCreate}
isDragStarted={isDragStarted}
canEditProperties={canEditProperties}
addIssuesToView={addIssuesToView}
quickAddCallback={quickAddCallback}
@ -207,23 +155,12 @@ export interface IKanBanSwimLanes {
sub_group_by: string | null;
group_by: string | null;
order_by: string | null;
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
quickActions: (
sub_group_by: string | null,
group_by: string | null,
issue: IIssue,
customActionButton?: React.ReactElement
) => React.ReactNode;
handleIssues: (issue: IIssue, action: EIssueActions) => void;
quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode;
displayProperties: IIssueDisplayProperties | null;
kanBanToggle: any;
handleKanBanToggle: any;
showEmptyGroup: boolean;
states: IState[] | null;
stateGroups: any;
priorities: any;
labels: IIssueLabel[] | null;
members: IUserLite[] | null;
projects: IProject[] | null;
isDragStarted?: boolean;
disableIssueCreation?: boolean;
currentStore?: EProjectStore;
@ -251,363 +188,58 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
kanBanToggle,
handleKanBanToggle,
showEmptyGroup,
states,
stateGroups,
priorities,
labels,
members,
projects,
isDragStarted,
disableIssueCreation,
enableQuickIssueCreate,
canEditProperties,
currentStore,
addIssuesToView,
quickAddCallback,
} = props;
const { project, projectLabel, projectMember, projectState } = useMobxStore();
const groupByList = getKanbanColumns(group_by as columnTypes, project, projectLabel, projectMember, projectState);
const subGroupByList = getKanbanColumns(
sub_group_by as columnTypes,
project,
projectLabel,
projectMember,
projectState
);
if (!groupByList || !subGroupByList) return null;
return (
<div className="relative">
<div className="sticky top-0 z-[2] h-[50px] bg-custom-background-90">
{group_by && group_by === "project" && (
<SubGroupSwimlaneHeader
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
list={projects}
listKey={`id`}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "state" && (
<SubGroupSwimlaneHeader
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
list={states}
listKey={`id`}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "state_detail.group" && (
<SubGroupSwimlaneHeader
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
list={stateGroups}
listKey={`key`}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "priority" && (
<SubGroupSwimlaneHeader
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
list={priorities}
listKey={`key`}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "labels" && (
<SubGroupSwimlaneHeader
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
list={labels ? [...labels, { id: "None", name: "None" }] : labels}
listKey={`id`}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "assignees" && (
<SubGroupSwimlaneHeader
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
list={members ? [...members, { id: "None", display_name: "None" }] : members}
listKey={`id`}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
{group_by && group_by === "created_by" && (
<SubGroupSwimlaneHeader
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
list={members}
listKey={`id`}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
disableIssueCreation={disableIssueCreation}
currentStore={currentStore}
addIssuesToView={addIssuesToView}
/>
)}
<SubGroupSwimlaneHeader
issueIds={issueIds}
group_by={group_by}
sub_group_by={sub_group_by}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
list={groupByList}
/>
</div>
{sub_group_by && sub_group_by === "project" && (
{sub_group_by && (
<SubGroupSwimlane
issues={issues}
list={subGroupByList}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
sub_group_by={sub_group_by}
order_by={order_by}
list={projects}
listKey={`id`}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
/>
)}
{sub_group_by && sub_group_by === "state" && (
<SubGroupSwimlane
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
list={states}
listKey={`id`}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
/>
)}
{sub_group_by && sub_group_by === "state" && (
<SubGroupSwimlane
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
list={states}
listKey={`id`}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
/>
)}
{sub_group_by && sub_group_by === "state_detail.group" && (
<SubGroupSwimlane
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
list={stateGroups}
listKey={`key`}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
/>
)}
{sub_group_by && sub_group_by === "priority" && (
<SubGroupSwimlane
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
list={priorities}
listKey={`key`}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
/>
)}
{sub_group_by && sub_group_by === "labels" && (
<SubGroupSwimlane
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
list={labels ? [...labels, { id: "None", name: "None" }] : labels}
listKey={`id`}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
/>
)}
{sub_group_by && sub_group_by === "assignees" && (
<SubGroupSwimlane
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
list={members ? [...members, { id: "None", display_name: "None" }] : members}
listKey={`id`}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate}
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
/>
)}
{sub_group_by && sub_group_by === "created_by" && (
<SubGroupSwimlane
issues={issues}
issueIds={issueIds}
sub_group_by={sub_group_by}
group_by={group_by}
order_by={order_by}
list={members}
listKey={`id`}
handleIssues={handleIssues}
quickActions={quickActions}
displayProperties={displayProperties}
kanBanToggle={kanBanToggle}
handleKanBanToggle={handleKanBanToggle}
showEmptyGroup={showEmptyGroup}
states={states}
stateGroups={stateGroups}
priorities={priorities}
labels={labels}
members={members}
projects={projects}
isDragStarted={isDragStarted}
disableIssueCreation={disableIssueCreation}
enableQuickIssueCreate={enableQuickIssueCreate}
addIssuesToView={addIssuesToView}
canEditProperties={canEditProperties}
quickAddCallback={quickAddCallback}
/>

View File

@ -0,0 +1,162 @@
import { Avatar, PriorityIcon, StateGroupIcon } from "@plane/ui";
import { ISSUE_PRIORITIES, ISSUE_STATE_GROUPS } from "constants/issue";
import { renderEmoji } from "helpers/emoji.helper";
import { ReactElement } from "react";
import { IProjectLabelStore, IProjectMemberStore, IProjectStateStore, IProjectStore } from "store_legacy/project";
import { IIssue } from "types";
export type columnTypes =
| "project"
| "state"
| "state_detail.group"
| "priority"
| "labels"
| "assignees"
| "created_by";
export interface IKanbanColumn {
id: string;
name: string;
Icon: ReactElement;
payload: Partial<IIssue>;
}
export const getKanbanColumns = (
groupBy: columnTypes | null,
project: IProjectStore,
projectLabel: IProjectLabelStore,
projectMember: IProjectMemberStore,
projectState: IProjectStateStore
): IKanbanColumn[] | undefined => {
switch (groupBy) {
case "project":
return getProjectColumns(project);
case "state":
return getStateColumns(projectState);
case "state_detail.group":
return getStateGroupColumns();
case "priority":
return getPriorityColumns();
case "labels":
return getLabelsColumns(projectLabel);
case "assignees":
return getAssigneeColumns(projectMember);
case "created_by":
return getCreatedByColumns(projectMember);
}
};
const getProjectColumns = (project: IProjectStore): IKanbanColumn[] | undefined => {
const { workspaceProjects: projects } = project;
if (!projects) return;
return projects.map((project) => {
return {
id: project.id,
name: project.name,
Icon: <div className="w-6 h-6">{renderEmoji(project.emoji || "")}</div>,
payload: { project: project.id },
};
});
};
const getStateColumns = (projectState: IProjectStateStore): IKanbanColumn[] | undefined => {
const { projectStates } = projectState;
if (!projectStates) return;
return projectStates.map((state) => {
return {
id: state.id,
name: state.name,
Icon: (
<div className="w-3.5 h-3.5 rounded-full">
<StateGroupIcon stateGroup={state.group} color={state.color} width="14" height="14" />
</div>
),
payload: { state: state.id },
};
});
};
const getStateGroupColumns = () => {
const stateGroups = ISSUE_STATE_GROUPS;
return stateGroups.map((stateGroup) => {
return {
id: stateGroup.key,
name: stateGroup.title,
Icon: (
<div className="w-3.5 h-3.5 rounded-full">
<StateGroupIcon stateGroup={stateGroup.key} width="14" height="14" />
</div>
),
payload: {},
};
});
};
const getPriorityColumns = () => {
const priorities = ISSUE_PRIORITIES;
return priorities.map((priority) => {
return {
id: priority.key,
name: priority.title,
Icon: <PriorityIcon priority={priority?.key} />,
payload: { priority: priority.key },
};
});
};
const getLabelsColumns = (projectLabel: IProjectLabelStore) => {
const { projectLabels } = projectLabel;
if (!projectLabels) return;
const labels = [...projectLabels, { id: "None", name: "None", color: "#666" }];
return labels.map((label) => {
return {
id: label.id,
name: label.name,
Icon: (
<div
className="w-[12px] h-[12px] rounded-full"
style={{ backgroundColor: label.color ? label.color : "#666" }}
/>
),
payload: { labels: [label.id] },
};
});
};
const getAssigneeColumns = (projectMember: IProjectMemberStore) => {
const { projectMembers: users } = projectMember;
if (!users) return;
return users.map((user) => {
const member = user.member;
return {
id: member?.id,
name: member?.display_name || "",
Icon: <Avatar name={member?.display_name} src={member?.avatar} size="md" />,
payload: { assignees: [member?.id] },
};
});
};
const getCreatedByColumns = (projectMember: IProjectMemberStore) => {
const { projectMembers: users } = projectMember;
if (!users) return;
return users.map((user) => {
const member = user.member;
return {
id: member?.id,
name: member?.display_name || "",
Icon: <Avatar name={member?.display_name} src={member?.avatar} size="md" />,
payload: { created_by: member?.id },
};
});
};