Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-2907] chore: issue store updated and code refactor #6279

Merged
merged 2 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion web/ce/components/issues/quick-add/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ export type TQuickAddIssueFormRoot = {
register: UseFormRegister<TIssue>;
onSubmit: () => void;
onClose: () => void;
isEpic: boolean;
};

export const QuickAddIssueFormRoot: FC<TQuickAddIssueFormRoot> = observer((props) => {
const { isOpen, layout, projectId, hasError = false, setFocus, register, onSubmit, onClose } = props;
const { isOpen, layout, projectId, hasError = false, setFocus, register, onSubmit, onClose, isEpic } = props;
// store hooks
const { getProjectById } = useProject();
// derived values
Expand Down Expand Up @@ -70,6 +71,7 @@ export const QuickAddIssueFormRoot: FC<TQuickAddIssueFormRoot> = observer((props
hasError={hasError}
register={register}
onSubmit={onSubmit}
isEpic={isEpic}
/>
);
});
7 changes: 4 additions & 3 deletions web/ce/store/issue/issue-details/activity.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ export class IssueActivityStore implements IIssueActivityStore {

let activityComments: TIssueActivityComment[] = [];

const currentStore = this.serviceType === EIssueServiceType.EPICS ? this.store.epic : this.store.issue;
const currentStore =
this.serviceType === EIssueServiceType.EPICS ? this.store.issue.epicDetail : this.store.issue.issueDetail;

const activities = this.getActivitiesByIssueId(issueId) || [];
const comments = currentStore.issueDetail.comment.getCommentsByIssueId(issueId) || [];
const comments = currentStore.comment.getCommentsByIssueId(issueId) || [];

activities.forEach((activityId) => {
const activity = this.getActivityById(activityId);
Expand All @@ -109,7 +110,7 @@ export class IssueActivityStore implements IIssueActivityStore {
});

comments.forEach((commentId) => {
const comment = currentStore.issueDetail.comment.getCommentById(commentId);
const comment = currentStore.comment.getCommentById(commentId);
if (!comment) return;
activityComments.push({
id: comment.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ type TCreateIssueToastActionItems = {
workspaceSlug: string;
projectId: string;
issueId: string;
isEpic?: boolean;
};

export const CreateIssueToastActionItems: FC<TCreateIssueToastActionItems> = observer((props) => {
const { workspaceSlug, projectId, issueId } = props;
const { workspaceSlug, projectId, issueId, isEpic = false } = props;
// state
const [copied, setCopied] = useState(false);
// store hooks
Expand All @@ -26,7 +27,7 @@ export const CreateIssueToastActionItems: FC<TCreateIssueToastActionItems> = obs

if (!issue) return null;

const issueLink = `${workspaceSlug}/projects/${projectId}/issues/${issueId}`;
const issueLink = `${workspaceSlug}/projects/${projectId}/${isEpic ? "epics" : "issues"}/${issueId}`;

const copyToClipboard = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
try {
Expand All @@ -43,12 +44,12 @@ export const CreateIssueToastActionItems: FC<TCreateIssueToastActionItems> = obs
return (
<div className="flex items-center gap-1 text-xs text-custom-text-200">
<a
href={`/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`}
href={`/${workspaceSlug}/projects/${projectId}/${isEpic ? "epics" : "issues"}/${issueId}/`}
target="_blank"
rel="noopener noreferrer"
className="text-custom-primary px-2 py-1 hover:bg-custom-background-90 font-medium rounded"
>
View issue
{`View ${isEpic ? "epic" : "issue"}`}
</a>

{copied ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ type TCalendarQuickAddIssueActions = {
quickAddCallback?: (projectId: string | null | undefined, data: TIssue) => Promise<TIssue | undefined>;
addIssuesToView?: (issueIds: string[]) => Promise<any>;
onOpen?: () => void;
isEpic?: boolean;
};

export const CalendarQuickAddIssueActions: FC<TCalendarQuickAddIssueActions> = observer((props) => {
const { prePopulatedData, quickAddCallback, addIssuesToView, onOpen } = props;
const { prePopulatedData, quickAddCallback, addIssuesToView, onOpen, isEpic = false } = props;
// router
const { workspaceSlug, projectId, moduleId } = useParams();
// states
Expand Down Expand Up @@ -118,15 +119,16 @@ export const CalendarQuickAddIssueActions: FC<TCalendarQuickAddIssueActions> = o
customButton={
<div className="flex w-full items-center gap-x-[6px] rounded-md px-2 py-1.5 text-custom-text-350 hover:text-custom-text-300">
<PlusIcon className="h-3.5 w-3.5 stroke-2 flex-shrink-0" />
<span className="text-sm font-medium flex-shrink-0">New issue</span>
<span className="text-sm font-medium flex-shrink-0">{`New ${isEpic ? "Epic" : "Issue"}`}</span>
</div>
}
>
<CustomMenu.MenuItem onClick={handleNewIssue}>New issue</CustomMenu.MenuItem>
<CustomMenu.MenuItem onClick={handleExistingIssue}>Add existing issue</CustomMenu.MenuItem>
<CustomMenu.MenuItem onClick={handleNewIssue}>{`New ${isEpic ? "Epic" : "Issue"}`}</CustomMenu.MenuItem>
{!isEpic && <CustomMenu.MenuItem onClick={handleExistingIssue}>Add existing issue</CustomMenu.MenuItem>}
</CustomMenu>
</div>
}
isEpic={isEpic}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
groupBy: group_by as GroupByColumnTypes,
includeNone: true,
isWorkspaceLevel: isWorkspaceLevel(storeType),
isEpic: isEpic,
});

if (!list) return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const KanbanGroup = observer((props: IKanbanGroup) => {
quickAddCallback,
scrollableContainerRef,
handleOnDrop,
isEpic =false
isEpic = false,
} = props;
// hooks
const projectState = useProjectState();
Expand Down Expand Up @@ -285,6 +285,7 @@ export const KanbanGroup = observer((props: IKanbanGroup) => {
dropErrorMessage={dropErrorMessage}
orderBy={orderBy}
isDraggingOverColumn={isDraggingOverColumn}
isEpic={isEpic}
/>
<KanbanIssueBlocksList
sub_group_id={sub_group_id}
Expand Down Expand Up @@ -312,6 +313,7 @@ export const KanbanGroup = observer((props: IKanbanGroup) => {
...(group_by && prePopulateQuickAddData(group_by, sub_group_by, groupId, sub_group_id)),
}}
quickAddCallback={quickAddCallback}
isEpic={isEpic}
/>
</div>
)}
Expand Down
1 change: 1 addition & 0 deletions web/core/components/issues/issue-layouts/list/default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export const List: React.FC<IList> = observer((props) => {
groupBy: group_by as GroupByColumnTypes,
includeNone: true,
isWorkspaceLevel: isWorkspaceLevel(storeType),
isEpic: isEpic,
});

// Enable Auto Scroll for Main Kanban
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { observer } from "mobx-react";
import { TQuickAddIssueForm } from "../root";

export const CalendarQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props) => {
const { ref, isOpen, projectDetail, register, onSubmit } = props;
const { ref, isOpen, projectDetail, register, onSubmit, isEpic } = props;

return (
<div
className={`z-20 w-full transition-all ${isOpen ? "scale-100 opacity-100" : "pointer-events-none scale-95 opacity-0"
}`}
className={`z-20 w-full transition-all ${
isOpen ? "scale-100 opacity-100" : "pointer-events-none scale-95 opacity-0"
}`}
>
<form
ref={ref}
Expand All @@ -19,9 +20,9 @@ export const CalendarQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props
<input
type="text"
autoComplete="off"
placeholder="Issue Title"
placeholder={isEpic ? "Epic Title" : "Issue Title"}
{...register("name", {
required: "Issue title is required.",
required: `${isEpic ? "Epic" : "Issue"} title is required.`,
})}
className="w-full rounded-md bg-transparent py-1.5 pr-2 text-sm md:text-xs font-medium leading-5 text-custom-text-200 outline-none"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { cn } from "@/helpers/common.helper";
import { TQuickAddIssueForm } from "../root";

export const GanttQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props) => {
const { ref, projectDetail, hasError, register, onSubmit } = props;
const { ref, projectDetail, hasError, register, onSubmit, isEpic } = props;

return (
<div className={cn("shadow-custom-shadow-sm", hasError && "border border-red-500/20 bg-red-500/10")}>
Expand All @@ -18,15 +18,15 @@ export const GanttQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props) =
<input
type="text"
autoComplete="off"
placeholder="Issue Title"
placeholder={isEpic ? "Epic Title" : "Issue Title"}
{...register("name", {
required: "Issue title is required.",
required: `${isEpic ? "Epic" : "Issue"} title is required.`,
})}
className="w-full rounded-md bg-transparent px-2 py-3 text-sm font-medium leading-5 text-custom-text-200 outline-none"
/>
</div>
</form>
<div className="px-3 py-2 text-xs bg-custom-background-100 italic text-custom-text-200">{`Press 'Enter' to add another issue`}</div>
<div className="px-3 py-2 text-xs bg-custom-background-100 italic text-custom-text-200">{`Press 'Enter' to add another ${isEpic ? "epic" : "issue"}`}</div>
</div>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import { TQuickAddIssueForm } from "../root";

export const KanbanQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props) => {
const { ref, projectDetail, register, onSubmit } = props;
const { ref, projectDetail, register, onSubmit, isEpic } = props;

return (
<div className="m-1 overflow-hidden rounded shadow-custom-shadow-sm">
Expand All @@ -12,15 +12,15 @@ export const KanbanQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props)
<h4 className="text-xs font-medium leading-5 text-custom-text-300">{projectDetail?.identifier ?? "..."}</h4>
<input
autoComplete="off"
placeholder="Issue Title"
placeholder={isEpic ? "Epic Title" : "Issue Title"}
{...register("name", {
required: "Issue title is required.",
})}
className="w-full rounded-md bg-transparent px-2 py-1.5 pl-0 text-sm font-medium leading-5 text-custom-text-200 outline-none"
/>
</div>
</form>
<div className="px-3 py-2 text-xs italic text-custom-text-200">{`Press 'Enter' to add another issue`}</div>
<div className="px-3 py-2 text-xs italic text-custom-text-200">{`Press 'Enter' to add another ${isEpic ? "epic" : "issue"}`}</div>
</div>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import { TQuickAddIssueForm } from "../root";

export const ListQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props) => {
const { ref, projectDetail, register, onSubmit } = props;
const { ref, projectDetail, register, onSubmit, isEpic } = props;

return (
<div className="shadow-custom-shadow-sm">
Expand All @@ -17,15 +17,15 @@ export const ListQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props) =>
<input
type="text"
autoComplete="off"
placeholder="Issue Title"
placeholder={isEpic ? "Epic Title" : "Issue Title"}
{...register("name", {
required: "Issue title is required.",
required: `${isEpic ? "Epic" : "Issue"} title is required.`,
})}
className="w-full rounded-md bg-transparent px-2 py-3 text-sm font-medium leading-5 text-custom-text-200 outline-none"
/>
</div>
</form>
<div className="px-3 py-2 text-xs italic text-custom-text-200">{`Press 'Enter' to add another issue`}</div>
<div className="px-3 py-2 text-xs italic text-custom-text-200">{`Press 'Enter' to add another ${isEpic ? "epic" : "issue"}`}</div>
</div>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import { TQuickAddIssueForm } from "../root";

export const SpreadsheetQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((props) => {
const { ref, projectDetail, register, onSubmit } = props;
const { ref, projectDetail, register, onSubmit, isEpic } = props;

return (
<div className="pb-2">
Expand All @@ -16,15 +16,15 @@ export const SpreadsheetQuickAddIssueForm: FC<TQuickAddIssueForm> = observer((pr
<input
type="text"
autoComplete="off"
placeholder="Issue Title"
placeholder={isEpic ? "Epic Title" : "Issue Title"}
{...register("name", {
required: "Issue title is required.",
required: `${isEpic ? "Epic" : "Issue"} title is required.`,
})}
className="w-full rounded-md bg-transparent py-3 text-sm leading-5 text-custom-text-200 outline-none"
/>
</form>
<p className="ml-3 mt-3 text-xs italic text-custom-text-200">
Press {"'"}Enter{"'"} to add another issue
{`Press Enter to add another ${isEpic ? "epic" : "issue"}`}
</p>
</div>
);
Expand Down
16 changes: 11 additions & 5 deletions web/core/components/issues/issue-layouts/quick-add/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useParams, usePathname } from "next/navigation";
import { useForm, UseFormRegister } from "react-hook-form";
import { PlusIcon } from "lucide-react";
// plane constants
import { EIssueLayoutTypes } from "@plane/constants";
import { EIssueLayoutTypes, EIssueServiceType } from "@plane/constants";
// types
import { IProject, TIssue } from "@plane/types";
// ui
Expand All @@ -30,9 +30,11 @@ export type TQuickAddIssueForm = {
hasError: boolean;
register: UseFormRegister<TIssue>;
onSubmit: () => void;
isEpic: boolean;
};

export type TQuickAddIssueButton = {
isEpic?: boolean;
onClick: () => void;
};

Expand All @@ -45,6 +47,7 @@ type TQuickAddIssueRoot = {
containerClassName?: string;
setIsQuickAddOpen?: (isOpen: boolean) => void;
quickAddCallback?: (projectId: string | null | undefined, data: TIssue) => Promise<TIssue | undefined>;
isEpic?: boolean;
};

const defaultValues: Partial<TIssue> = {
Expand All @@ -61,6 +64,7 @@ export const QuickAddIssueRoot: FC<TQuickAddIssueRoot> = observer((props) => {
containerClassName = "",
setIsQuickAddOpen,
quickAddCallback,
isEpic = false,
} = props;
// router
const { workspaceSlug, projectId } = useParams();
Expand Down Expand Up @@ -109,15 +113,16 @@ export const QuickAddIssueRoot: FC<TQuickAddIssueRoot> = observer((props) => {
if (quickAddCallback) {
const quickAddPromise = quickAddCallback(projectId.toString(), { ...payload });
setPromiseToast<any>(quickAddPromise, {
loading: "Adding issue...",
loading: `Adding ${isEpic ? "epic" : "issue"}...`,
success: {
title: "Success!",
message: () => "Issue created successfully.",
message: () => `${isEpic ? "Epic" : "Issue"} created successfully.`,
actionItems: (data) => (
<CreateIssueToastActionItems
workspaceSlug={workspaceSlug.toString()}
projectId={projectId.toString()}
issueId={data.id}
isEpic={isEpic}
/>
),
},
Expand Down Expand Up @@ -165,18 +170,19 @@ export const QuickAddIssueRoot: FC<TQuickAddIssueRoot> = observer((props) => {
register={register}
onSubmit={handleSubmit(onSubmitHandler)}
onClose={() => handleIsOpen(false)}
isEpic={isEpic}
/>
) : (
<>
{QuickAddButton && <QuickAddButton onClick={() => handleIsOpen(true)} />}
{QuickAddButton && <QuickAddButton isEpic={isEpic} onClick={() => handleIsOpen(true)} />}
{customQuickAddButton && <>{customQuickAddButton}</>}
{!QuickAddButton && !customQuickAddButton && (
<div
className="flex w-full cursor-pointer items-center gap-2 px-2 py-3 text-custom-text-350 hover:text-custom-text-300"
onClick={() => handleIsOpen(true)}
>
<PlusIcon className="h-3.5 w-3.5 stroke-2" />
<span className="text-sm font-medium">New Issue</span>
<span className="text-sm font-medium">{`New ${isEpic ? "Epic" : "Issue"}`}</span>
</div>
)}
</>
Expand Down
4 changes: 3 additions & 1 deletion web/core/components/issues/issue-layouts/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type TGetGroupByColumns = {
groupBy: GroupByColumnTypes | null;
includeNone: boolean;
isWorkspaceLevel: boolean;
isEpic?: boolean;
};

// NOTE: Type of groupBy is different compared to what's being passed from the components.
Expand All @@ -77,13 +78,14 @@ export const getGroupByColumns = ({
groupBy,
includeNone,
isWorkspaceLevel,
isEpic = false,
}: TGetGroupByColumns): IGroupByColumn[] | undefined => {
// If no groupBy is specified and includeNone is true, return "All Issues" group
if (!groupBy && includeNone) {
return [
{
id: "All Issues",
name: "All Issues",
name: isEpic ? "All Epics" : "All Issues",
payload: {},
icon: undefined,
},
Expand Down
Loading
Loading