forked from github/plane
fix: issues mutation on changing filters (#2485)
* chore: refetch issues on filters and display filters change * fix: issues list mutation after creating an issue * fix: module issues fetch * fix: build error
This commit is contained in:
parent
85a471305a
commit
0b8367a262
@ -176,7 +176,7 @@ export const InlineCreateIssueFormWrapper: React.FC<Props> = (props) => {
|
|||||||
reset({ ...defaultValues });
|
reset({ ...defaultValues });
|
||||||
|
|
||||||
await (!isDraftIssues
|
await (!isDraftIssues
|
||||||
? issueService.createIssues(workspaceSlug.toString(), projectId.toString(), formData, user)
|
? issueService.createIssue(workspaceSlug.toString(), projectId.toString(), formData, user)
|
||||||
: issueDraftService.createDraftIssue(workspaceSlug.toString(), projectId.toString(), formData)
|
: issueDraftService.createDraftIssue(workspaceSlug.toString(), projectId.toString(), formData)
|
||||||
)
|
)
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
// react-beautiful-dnd
|
|
||||||
import { DragDropContext, Draggable, DropResult } from "react-beautiful-dnd";
|
import { DragDropContext, Draggable, DropResult } from "react-beautiful-dnd";
|
||||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||||
|
import { MoreVertical } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import { useChart } from "./hooks";
|
import { useChart } from "./hooks";
|
||||||
// ui
|
// ui
|
||||||
import { Loader } from "@plane/ui";
|
import { Loader } from "@plane/ui";
|
||||||
// icons
|
|
||||||
import { MoreVertical } from "lucide-react";
|
|
||||||
// helpers
|
// helpers
|
||||||
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
import { findTotalDaysInRange } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
@ -124,8 +122,8 @@ export const GanttSidebar: React.FC<Props> = (props) => {
|
|||||||
className="rounded p-0.5 text-custom-sidebar-text-200 flex flex-shrink-0 opacity-0 group-hover:opacity-100"
|
className="rounded p-0.5 text-custom-sidebar-text-200 flex flex-shrink-0 opacity-0 group-hover:opacity-100"
|
||||||
{...provided.dragHandleProps}
|
{...provided.dragHandleProps}
|
||||||
>
|
>
|
||||||
<MoreVertical className="h-4" />
|
<MoreVertical className="h-3.5 w-3.5" />
|
||||||
<MoreVertical className="h-4 -ml-5" />
|
<MoreVertical className="h-3.5 w-3.5 -ml-5" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<div className="flex-grow truncate h-full flex items-center justify-between gap-2">
|
<div className="flex-grow truncate h-full flex items-center justify-between gap-2">
|
||||||
|
@ -304,7 +304,7 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = observer(
|
|||||||
if (!workspaceSlug || !activeProject) return;
|
if (!workspaceSlug || !activeProject) return;
|
||||||
|
|
||||||
await issueService
|
await issueService
|
||||||
.createIssues(workspaceSlug as string, activeProject ?? "", payload, user)
|
.createIssue(workspaceSlug as string, activeProject ?? "", payload, user)
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
||||||
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
|
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import React, { FC, useState, useEffect, useRef } from "react";
|
import React, { FC, useState, useEffect, useRef } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
// mobx store
|
||||||
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// services
|
// services
|
||||||
import { AIService } from "services/ai.service";
|
import { AIService } from "services/ai.service";
|
||||||
import { FileService } from "services/file.service";
|
import { FileService } from "services/file.service";
|
||||||
@ -26,7 +29,7 @@ import { Button, Input, ToggleSwitch } from "@plane/ui";
|
|||||||
// icons
|
// icons
|
||||||
import { LayoutPanelTop, Sparkle, X } from "lucide-react";
|
import { LayoutPanelTop, Sparkle, X } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import type { IUser, IIssue, ISearchIssueResponse } from "types";
|
import type { IIssue, ISearchIssueResponse } from "types";
|
||||||
// components
|
// components
|
||||||
import { RichTextEditorWithRef } from "@plane/rich-text-editor";
|
import { RichTextEditorWithRef } from "@plane/rich-text-editor";
|
||||||
|
|
||||||
@ -55,7 +58,6 @@ export interface IssueFormProps {
|
|||||||
setCreateMore: React.Dispatch<React.SetStateAction<boolean>>;
|
setCreateMore: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
handleDiscardClose: () => void;
|
handleDiscardClose: () => void;
|
||||||
status: boolean;
|
status: boolean;
|
||||||
user: IUser | undefined;
|
|
||||||
handleFormDirty: (payload: Partial<IIssue> | null) => void;
|
handleFormDirty: (payload: Partial<IIssue> | null) => void;
|
||||||
fieldsToShow: (
|
fieldsToShow: (
|
||||||
| "project"
|
| "project"
|
||||||
@ -77,7 +79,7 @@ export interface IssueFormProps {
|
|||||||
const aiService = new AIService();
|
const aiService = new AIService();
|
||||||
const fileService = new FileService();
|
const fileService = new FileService();
|
||||||
|
|
||||||
export const IssueForm: FC<IssueFormProps> = (props) => {
|
export const IssueForm: FC<IssueFormProps> = observer((props) => {
|
||||||
const {
|
const {
|
||||||
handleFormSubmit,
|
handleFormSubmit,
|
||||||
initialData,
|
initialData,
|
||||||
@ -87,7 +89,6 @@ export const IssueForm: FC<IssueFormProps> = (props) => {
|
|||||||
setCreateMore,
|
setCreateMore,
|
||||||
handleDiscardClose,
|
handleDiscardClose,
|
||||||
status,
|
status,
|
||||||
user,
|
|
||||||
fieldsToShow,
|
fieldsToShow,
|
||||||
handleFormDirty,
|
handleFormDirty,
|
||||||
} = props;
|
} = props;
|
||||||
@ -105,6 +106,10 @@ export const IssueForm: FC<IssueFormProps> = (props) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
|
|
||||||
|
const { user: userStore } = useMobxStore();
|
||||||
|
|
||||||
|
const user = userStore.currentUser;
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -174,7 +179,7 @@ export const IssueForm: FC<IssueFormProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAutoGenerateDescription = async () => {
|
const handleAutoGenerateDescription = async () => {
|
||||||
if (!workspaceSlug || !projectId) return;
|
if (!workspaceSlug || !projectId || !user) return;
|
||||||
|
|
||||||
setIAmFeelingLucky(true);
|
setIAmFeelingLucky(true);
|
||||||
|
|
||||||
@ -251,13 +256,13 @@ export const IssueForm: FC<IssueFormProps> = (props) => {
|
|||||||
isOpen={stateModal}
|
isOpen={stateModal}
|
||||||
handleClose={() => setStateModal(false)}
|
handleClose={() => setStateModal(false)}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
user={user}
|
user={user ?? undefined}
|
||||||
/>
|
/>
|
||||||
<CreateLabelModal
|
<CreateLabelModal
|
||||||
isOpen={labelModal}
|
isOpen={labelModal}
|
||||||
handleClose={() => setLabelModal(false)}
|
handleClose={() => setLabelModal(false)}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
user={user}
|
user={user ?? undefined}
|
||||||
onSuccess={(response) => {
|
onSuccess={(response) => {
|
||||||
setValue("labels", [...watch("labels"), response.id]);
|
setValue("labels", [...watch("labels"), response.id]);
|
||||||
setValue("labels_list", [...watch("labels_list"), response.id]);
|
setValue("labels_list", [...watch("labels_list"), response.id]);
|
||||||
@ -605,4 +610,4 @@ export const IssueForm: FC<IssueFormProps> = (props) => {
|
|||||||
</form>
|
</form>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
// mobx
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
// lucide icons
|
|
||||||
import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react";
|
import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react";
|
||||||
// components
|
// components
|
||||||
import { HeaderGroupByCard } from "./group-by-card";
|
import { HeaderGroupByCard } from "./group-by-card";
|
||||||
@ -44,8 +42,9 @@ const Icon = ({ priority }: any) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PriorityHeader: React.FC<IPriorityHeader> = observer(
|
export const PriorityHeader: React.FC<IPriorityHeader> = observer((props) => {
|
||||||
({ column_id, sub_group_by, group_by, header_type, issues_count, kanBanToggle, handleKanBanToggle }) => {
|
const { column_id, sub_group_by, group_by, header_type, issues_count, kanBanToggle, handleKanBanToggle } = props;
|
||||||
|
|
||||||
const priority = column_id && issuePriorityByKey(column_id);
|
const priority = column_id && issuePriorityByKey(column_id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -55,7 +54,7 @@ export const PriorityHeader: React.FC<IPriorityHeader> = observer(
|
|||||||
<HeaderSubGroupByCard
|
<HeaderSubGroupByCard
|
||||||
column_id={column_id}
|
column_id={column_id}
|
||||||
icon={<Icon priority={priority?.key} />}
|
icon={<Icon priority={priority?.key} />}
|
||||||
title={priority?.key || ""}
|
title={priority?.title || ""}
|
||||||
count={issues_count}
|
count={issues_count}
|
||||||
kanBanToggle={kanBanToggle}
|
kanBanToggle={kanBanToggle}
|
||||||
handleKanBanToggle={handleKanBanToggle}
|
handleKanBanToggle={handleKanBanToggle}
|
||||||
@ -66,7 +65,7 @@ export const PriorityHeader: React.FC<IPriorityHeader> = observer(
|
|||||||
group_by={group_by}
|
group_by={group_by}
|
||||||
column_id={column_id}
|
column_id={column_id}
|
||||||
icon={<Icon priority={priority?.key} />}
|
icon={<Icon priority={priority?.key} />}
|
||||||
title={priority?.key || ""}
|
title={priority?.title || ""}
|
||||||
count={issues_count}
|
count={issues_count}
|
||||||
kanBanToggle={kanBanToggle}
|
kanBanToggle={kanBanToggle}
|
||||||
handleKanBanToggle={handleKanBanToggle}
|
handleKanBanToggle={handleKanBanToggle}
|
||||||
@ -74,5 +73,4 @@ export const PriorityHeader: React.FC<IPriorityHeader> = observer(
|
|||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
// lucide icons
|
|
||||||
import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react";
|
import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react";
|
||||||
// components
|
// components
|
||||||
import { HeaderGroupByCard } from "./group-by-card";
|
import { HeaderGroupByCard } from "./group-by-card";
|
||||||
@ -45,7 +44,11 @@ export const PriorityHeader: FC<IPriorityHeader> = observer((props) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{priority && (
|
{priority && (
|
||||||
<HeaderGroupByCard icon={<Icon priority={priority?.key} />} title={priority?.key || ""} count={issues_count} />
|
<HeaderGroupByCard
|
||||||
|
icon={<Icon priority={priority?.key} />}
|
||||||
|
title={priority?.title || ""}
|
||||||
|
count={issues_count}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -9,29 +9,14 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
|||||||
import { ModuleService } from "services/module.service";
|
import { ModuleService } from "services/module.service";
|
||||||
import { IssueService, IssueDraftService } from "services/issue";
|
import { IssueService, IssueDraftService } from "services/issue";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "hooks/use-user";
|
|
||||||
import useIssuesView from "hooks/use-issues-view";
|
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
import useMyIssues from "hooks/my-issues/use-my-issues";
|
|
||||||
import useLocalStorage from "hooks/use-local-storage";
|
import useLocalStorage from "hooks/use-local-storage";
|
||||||
// components
|
// components
|
||||||
import { IssueForm, ConfirmIssueDiscard } from "components/issues";
|
import { IssueForm, ConfirmIssueDiscard } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import type { IIssue } from "types";
|
import type { IIssue } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import {
|
import { PROJECT_ISSUES_DETAILS, USER_ISSUE, SUB_ISSUES } from "constants/fetch-keys";
|
||||||
PROJECT_ISSUES_DETAILS,
|
|
||||||
USER_ISSUE,
|
|
||||||
SUB_ISSUES,
|
|
||||||
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
|
||||||
CYCLE_ISSUES_WITH_PARAMS,
|
|
||||||
MODULE_ISSUES_WITH_PARAMS,
|
|
||||||
CYCLE_DETAILS,
|
|
||||||
MODULE_DETAILS,
|
|
||||||
VIEW_ISSUES,
|
|
||||||
PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS,
|
|
||||||
GLOBAL_VIEW_ISSUES,
|
|
||||||
} from "constants/fetch-keys";
|
|
||||||
|
|
||||||
export interface IssuesModalProps {
|
export interface IssuesModalProps {
|
||||||
data?: IIssue | null;
|
data?: IIssue | null;
|
||||||
@ -79,19 +64,21 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
|||||||
const [prePopulateData, setPreloadedData] = useState<Partial<IIssue>>({});
|
const [prePopulateData, setPreloadedData] = useState<Partial<IIssue>>({});
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId, viewId, globalViewId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||||
|
|
||||||
const { project: projectStore } = useMobxStore();
|
const {
|
||||||
|
project: projectStore,
|
||||||
|
issue: issueStore,
|
||||||
|
issueDetail: issueDetailStore,
|
||||||
|
cycleIssue: cycleIssueStore,
|
||||||
|
moduleIssue: moduleIssueStore,
|
||||||
|
user: userStore,
|
||||||
|
} = useMobxStore();
|
||||||
|
|
||||||
|
const user = userStore.currentUser;
|
||||||
|
|
||||||
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined;
|
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined;
|
||||||
|
|
||||||
const { displayFilters, params } = useIssuesView();
|
|
||||||
const { ...viewGanttParams } = params;
|
|
||||||
|
|
||||||
const { user } = useUser();
|
|
||||||
|
|
||||||
const { groupedIssues, mutateMyIssues } = useMyIssues(workspaceSlug?.toString());
|
|
||||||
|
|
||||||
const { setValue: setValueInLocalStorage, clearValue: clearLocalStorageValue } = useLocalStorage<any>(
|
const { setValue: setValueInLocalStorage, clearValue: clearLocalStorageValue } = useLocalStorage<any>(
|
||||||
"draftedIssue",
|
"draftedIssue",
|
||||||
{}
|
{}
|
||||||
@ -192,118 +179,55 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
|||||||
}, [activeProject, data, projectId, projects, isOpen]);
|
}, [activeProject, data, projectId, projects, isOpen]);
|
||||||
|
|
||||||
const addIssueToCycle = async (issueId: string, cycleId: string) => {
|
const addIssueToCycle = async (issueId: string, cycleId: string) => {
|
||||||
if (!workspaceSlug || !activeProject) return;
|
if (!workspaceSlug || !activeProject || !user) return;
|
||||||
|
|
||||||
await issueService
|
await issueService
|
||||||
.addIssueToCycle(
|
.addIssueToCycle(
|
||||||
workspaceSlug as string,
|
workspaceSlug.toString(),
|
||||||
activeProject ?? "",
|
activeProject,
|
||||||
cycleId,
|
cycleId,
|
||||||
{
|
{
|
||||||
issues: [issueId],
|
issues: [issueId],
|
||||||
},
|
},
|
||||||
user
|
user
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => cycleIssueStore.fetchIssues(workspaceSlug.toString(), activeProject, cycleId));
|
||||||
if (cycleId) {
|
|
||||||
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId, params));
|
|
||||||
mutate(CYCLE_DETAILS(cycleId as string));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const addIssueToModule = async (issueId: string, moduleId: string) => {
|
const addIssueToModule = async (issueId: string, moduleId: string) => {
|
||||||
if (!workspaceSlug || !activeProject) return;
|
if (!workspaceSlug || !activeProject || !user) return;
|
||||||
|
|
||||||
await moduleService
|
await moduleService
|
||||||
.addIssuesToModule(
|
.addIssuesToModule(
|
||||||
workspaceSlug as string,
|
workspaceSlug.toString(),
|
||||||
activeProject ?? "",
|
activeProject,
|
||||||
moduleId as string,
|
moduleId,
|
||||||
{
|
{
|
||||||
issues: [issueId],
|
issues: [issueId],
|
||||||
},
|
},
|
||||||
user
|
user
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => moduleIssueStore.fetchIssues(workspaceSlug.toString(), activeProject, moduleId));
|
||||||
if (moduleId) {
|
|
||||||
mutate(MODULE_ISSUES_WITH_PARAMS(moduleId as string, params));
|
|
||||||
mutate(MODULE_DETAILS(moduleId as string));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const workspaceIssuesPath = [
|
|
||||||
{
|
|
||||||
params: {
|
|
||||||
sub_issue: false,
|
|
||||||
},
|
|
||||||
path: "workspace-views/all-issues",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
params: {
|
|
||||||
assignees: user?.id ?? undefined,
|
|
||||||
sub_issue: false,
|
|
||||||
},
|
|
||||||
path: "workspace-views/assigned",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
params: {
|
|
||||||
created_by: user?.id ?? undefined,
|
|
||||||
sub_issue: false,
|
|
||||||
},
|
|
||||||
path: "workspace-views/created",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
params: {
|
|
||||||
subscriber: user?.id ?? undefined,
|
|
||||||
sub_issue: false,
|
|
||||||
},
|
|
||||||
path: "workspace-views/subscribed",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const currentWorkspaceIssuePath = workspaceIssuesPath.find((path) => router.pathname.includes(path.path));
|
|
||||||
|
|
||||||
const ganttFetchKey = cycleId
|
|
||||||
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString())
|
|
||||||
: moduleId
|
|
||||||
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString())
|
|
||||||
: viewId
|
|
||||||
? VIEW_ISSUES(viewId.toString(), viewGanttParams)
|
|
||||||
: PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject?.toString() ?? "");
|
|
||||||
|
|
||||||
const createIssue = async (payload: Partial<IIssue>) => {
|
const createIssue = async (payload: Partial<IIssue>) => {
|
||||||
if (!workspaceSlug || !activeProject) return;
|
if (!workspaceSlug || !activeProject || !user) return;
|
||||||
|
|
||||||
await issueService
|
await issueDetailStore
|
||||||
.createIssues(workspaceSlug as string, activeProject ?? "", payload, user)
|
.createIssue(workspaceSlug.toString(), activeProject, payload, user)
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
issueStore.fetchIssues(workspaceSlug.toString(), activeProject);
|
||||||
|
|
||||||
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
|
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
|
||||||
if (payload.module && payload.module !== "") await addIssueToModule(res.id, payload.module);
|
if (payload.module && payload.module !== "") await addIssueToModule(res.id, payload.module);
|
||||||
|
|
||||||
if (displayFilters.layout === "gantt_chart")
|
|
||||||
mutate(ganttFetchKey, {
|
|
||||||
start_target_date: true,
|
|
||||||
order_by: "sort_order",
|
|
||||||
});
|
|
||||||
if (groupedIssues) mutateMyIssues();
|
|
||||||
|
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: "Issue created successfully.",
|
message: "Issue created successfully.",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (payload.assignees_list?.some((assignee) => assignee === user?.id))
|
|
||||||
mutate(USER_ISSUE(workspaceSlug as string));
|
|
||||||
|
|
||||||
if (payload.parent && payload.parent !== "") mutate(SUB_ISSUES(payload.parent));
|
if (payload.parent && payload.parent !== "") mutate(SUB_ISSUES(payload.parent));
|
||||||
|
|
||||||
if (globalViewId) mutate(GLOBAL_VIEW_ISSUES(globalViewId.toString()));
|
|
||||||
|
|
||||||
if (currentWorkspaceIssuePath) mutate(GLOBAL_VIEW_ISSUES(workspaceSlug.toString()));
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
@ -326,9 +250,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
|||||||
await issueDraftService
|
await issueDraftService
|
||||||
.createDraftIssue(workspaceSlug as string, activeProject ?? "", payload)
|
.createDraftIssue(workspaceSlug as string, activeProject ?? "", payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
|
||||||
if (groupedIssues) mutateMyIssues();
|
|
||||||
|
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
@ -364,7 +285,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
|||||||
mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
|
mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
|
||||||
} else {
|
} else {
|
||||||
if (payload.parent) mutate(SUB_ISSUES(payload.parent.toString()));
|
if (payload.parent) mutate(SUB_ISSUES(payload.parent.toString()));
|
||||||
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
|
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
|
||||||
@ -456,7 +376,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
|||||||
projectId={activeProject ?? ""}
|
projectId={activeProject ?? ""}
|
||||||
setActiveProject={setActiveProject}
|
setActiveProject={setActiveProject}
|
||||||
status={data ? true : false}
|
status={data ? true : false}
|
||||||
user={user}
|
|
||||||
fieldsToShow={fieldsToShow}
|
fieldsToShow={fieldsToShow}
|
||||||
handleFormDirty={handleFormDirty}
|
handleFormDirty={handleFormDirty}
|
||||||
/>
|
/>
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { FC, ReactNode } from "react";
|
import { FC, ReactNode } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
// services
|
|
||||||
import { UserService } from "services/user.service";
|
|
||||||
// ui
|
// ui
|
||||||
import { Spinner } from "@plane/ui";
|
import { Spinner } from "@plane/ui";
|
||||||
// store
|
// store
|
||||||
@ -19,7 +17,7 @@ export const UserAuthWrapper: FC<IUserAuthWrapper> = (props) => {
|
|||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
// fetching user information
|
// fetching user information
|
||||||
const { data: currentUser, error } = useSWR("CURRENT_USER", () => userStore.fetchCurrentUser());
|
const { data: currentUser, error } = useSWR("CURRENT_USER_DETAILS", () => userStore.fetchCurrentUser());
|
||||||
// fetching user settings
|
// fetching user settings
|
||||||
useSWR("CURRENT_USER_SETTINGS", () => userStore.fetchCurrentUserSettings());
|
useSWR("CURRENT_USER_SETTINGS", () => userStore.fetchCurrentUserSettings());
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ const MobxStoreInit = observer(() => {
|
|||||||
user: userStore,
|
user: userStore,
|
||||||
workspace: workspaceStore,
|
workspace: workspaceStore,
|
||||||
project: projectStore,
|
project: projectStore,
|
||||||
|
cycle: cycleStore,
|
||||||
module: moduleStore,
|
module: moduleStore,
|
||||||
globalViews: globalViewsStore,
|
globalViews: globalViewsStore,
|
||||||
projectViews: projectViewsStore,
|
projectViews: projectViewsStore,
|
||||||
@ -24,7 +25,7 @@ const MobxStoreInit = observer(() => {
|
|||||||
const { setTheme } = useTheme();
|
const { setTheme } = useTheme();
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, moduleId, globalViewId, viewId, inboxId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId, globalViewId, viewId, inboxId } = router.query;
|
||||||
|
|
||||||
// const dom = useMemo(() => window && window.document?.querySelector<HTMLElement>("[data-theme='custom']"), [document]);
|
// const dom = useMemo(() => window && window.document?.querySelector<HTMLElement>("[data-theme='custom']"), [document]);
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ const MobxStoreInit = observer(() => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspaceSlug) workspaceStore.setWorkspaceSlug(workspaceSlug.toString());
|
if (workspaceSlug) workspaceStore.setWorkspaceSlug(workspaceSlug.toString());
|
||||||
if (projectId) projectStore.setProjectId(projectId.toString());
|
if (projectId) projectStore.setProjectId(projectId.toString());
|
||||||
|
if (cycleId) cycleStore.setCycleId(cycleId.toString());
|
||||||
if (moduleId) moduleStore.setModuleId(moduleId.toString());
|
if (moduleId) moduleStore.setModuleId(moduleId.toString());
|
||||||
if (globalViewId) globalViewsStore.setGlobalViewId(globalViewId.toString());
|
if (globalViewId) globalViewsStore.setGlobalViewId(globalViewId.toString());
|
||||||
if (viewId) projectViewsStore.setViewId(viewId.toString());
|
if (viewId) projectViewsStore.setViewId(viewId.toString());
|
||||||
@ -59,12 +61,14 @@ const MobxStoreInit = observer(() => {
|
|||||||
}, [
|
}, [
|
||||||
workspaceSlug,
|
workspaceSlug,
|
||||||
projectId,
|
projectId,
|
||||||
|
cycleId,
|
||||||
moduleId,
|
moduleId,
|
||||||
globalViewId,
|
globalViewId,
|
||||||
viewId,
|
viewId,
|
||||||
inboxId,
|
inboxId,
|
||||||
workspaceStore,
|
workspaceStore,
|
||||||
projectStore,
|
projectStore,
|
||||||
|
cycleStore,
|
||||||
moduleStore,
|
moduleStore,
|
||||||
globalViewsStore,
|
globalViewsStore,
|
||||||
projectViewsStore,
|
projectViewsStore,
|
||||||
|
@ -13,7 +13,7 @@ export class IssueService extends APIService {
|
|||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createIssues(workspaceSlug: string, projectId: string, data: any, user: IUser | undefined): Promise<any> {
|
async createIssue(workspaceSlug: string, projectId: string, data: any, user: IUser | undefined): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
trackEventService.trackIssueEvent(response.data, "ISSUE_CREATE", user as IUser);
|
trackEventService.trackIssueEvent(response.data, "ISSUE_CREATE", user as IUser);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
|
||||||
// store
|
// store
|
||||||
import { RootStore } from "../root";
|
import { RootStore } from "../root";
|
||||||
// types
|
// types
|
||||||
@ -69,8 +69,24 @@ export class CycleIssueStore implements ICycleIssueStore {
|
|||||||
fetchIssues: action,
|
fetchIssues: action,
|
||||||
updateIssueStructure: action,
|
updateIssueStructure: action,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.rootStore = _rootStore;
|
this.rootStore = _rootStore;
|
||||||
this.cycleService = new CycleService();
|
this.cycleService = new CycleService();
|
||||||
|
|
||||||
|
autorun(() => {
|
||||||
|
const workspaceSlug = this.rootStore.workspace.workspaceSlug;
|
||||||
|
const projectId = this.rootStore.project.projectId;
|
||||||
|
const cycleId = this.rootStore.cycle.cycleId;
|
||||||
|
|
||||||
|
if (
|
||||||
|
workspaceSlug &&
|
||||||
|
projectId &&
|
||||||
|
cycleId &&
|
||||||
|
this.rootStore.cycleIssueFilter.cycleFilters &&
|
||||||
|
this.rootStore.issueFilter.userDisplayFilters
|
||||||
|
)
|
||||||
|
this.fetchIssues(workspaceSlug, projectId, cycleId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get getIssueType() {
|
get getIssueType() {
|
||||||
@ -156,10 +172,6 @@ export class CycleIssueStore implements ICycleIssueStore {
|
|||||||
this.loader = true;
|
this.loader = true;
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
this.rootStore.workspace.setWorkspaceSlug(workspaceSlug);
|
|
||||||
this.rootStore.project.setProjectId(projectId);
|
|
||||||
this.rootStore.cycle.setCycleId(cycleId);
|
|
||||||
|
|
||||||
const params = this.rootStore?.cycleIssueFilter?.appliedFilters;
|
const params = this.rootStore?.cycleIssueFilter?.appliedFilters;
|
||||||
const issueResponse = await this.cycleService.getCycleIssuesWithParams(workspaceSlug, projectId, cycleId, params);
|
const issueResponse = await this.cycleService.getCycleIssuesWithParams(workspaceSlug, projectId, cycleId, params);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { observable, action, makeObservable, runInAction } from "mobx";
|
import { observable, action, makeObservable, runInAction, autorun } from "mobx";
|
||||||
// services
|
// services
|
||||||
import { ProjectService } from "services/project";
|
import { ProjectService } from "services/project";
|
||||||
import { WorkspaceService } from "services/workspace.service";
|
import { WorkspaceService } from "services/workspace.service";
|
||||||
@ -55,9 +55,21 @@ export class GlobalViewIssuesStore implements IGlobalViewIssuesStore {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.rootStore = _rootStore;
|
this.rootStore = _rootStore;
|
||||||
|
|
||||||
this.projectService = new ProjectService();
|
this.projectService = new ProjectService();
|
||||||
this.workspaceService = new WorkspaceService();
|
this.workspaceService = new WorkspaceService();
|
||||||
|
|
||||||
|
autorun(() => {
|
||||||
|
const workspaceSlug = this.rootStore.workspace.workspaceSlug;
|
||||||
|
const globalViewId = this.rootStore.globalViews.globalViewId;
|
||||||
|
|
||||||
|
if (
|
||||||
|
workspaceSlug &&
|
||||||
|
globalViewId &&
|
||||||
|
this.rootStore.globalViewFilters.storedFilters[globalViewId] &&
|
||||||
|
this.rootStore.issueFilter.userDisplayFilters
|
||||||
|
)
|
||||||
|
this.fetchViewIssues(workspaceSlug, globalViewId, this.rootStore.globalViewFilters.storedFilters[globalViewId]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
computedFilter = (filters: any, filteredParams: any) => {
|
computedFilter = (filters: any, filteredParams: any) => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
|
||||||
// store
|
// store
|
||||||
import { RootStore } from "../root";
|
import { RootStore } from "../root";
|
||||||
// types
|
// types
|
||||||
@ -68,8 +68,22 @@ export class IssueStore implements IIssueStore {
|
|||||||
fetchIssues: action,
|
fetchIssues: action,
|
||||||
updateIssueStructure: action,
|
updateIssueStructure: action,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.rootStore = _rootStore;
|
this.rootStore = _rootStore;
|
||||||
this.issueService = new IssueService();
|
this.issueService = new IssueService();
|
||||||
|
|
||||||
|
autorun(() => {
|
||||||
|
const workspaceSlug = this.rootStore.workspace.workspaceSlug;
|
||||||
|
const projectId = this.rootStore.project.projectId;
|
||||||
|
|
||||||
|
if (
|
||||||
|
workspaceSlug &&
|
||||||
|
projectId &&
|
||||||
|
this.rootStore.issueFilter.userFilters &&
|
||||||
|
this.rootStore.issueFilter.userDisplayFilters
|
||||||
|
)
|
||||||
|
this.fetchIssues(workspaceSlug, projectId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get getIssueType() {
|
get getIssueType() {
|
||||||
|
@ -27,7 +27,7 @@ export interface IIssueDetailStore {
|
|||||||
// fetch issue details
|
// fetch issue details
|
||||||
fetchIssueDetails: (workspaceSlug: string, projectId: string, issueId: string) => void;
|
fetchIssueDetails: (workspaceSlug: string, projectId: string, issueId: string) => void;
|
||||||
// creating issue
|
// creating issue
|
||||||
createIssue: (workspaceSlug: string, projectId: string, data: Partial<IIssue>, user: IUser) => void;
|
createIssue: (workspaceSlug: string, projectId: string, data: Partial<IIssue>, user: IUser) => Promise<IIssue>;
|
||||||
// updating issue
|
// updating issue
|
||||||
updateIssue: (
|
updateIssue: (
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
@ -125,7 +125,7 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
this.error = null;
|
this.error = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await this.issueService.createIssues(workspaceSlug, projectId, data, user);
|
const response = await this.issueService.createIssue(workspaceSlug, projectId, data, user);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
@ -135,10 +135,13 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
[response.id]: response,
|
[response.id]: response,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return response;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
this.error = error;
|
this.error = error;
|
||||||
return error;
|
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
import { observable, action, computed, makeObservable, runInAction, autorun } from "mobx";
|
||||||
// store
|
// store
|
||||||
import { RootStore } from "../root";
|
import { RootStore } from "../root";
|
||||||
// types
|
// types
|
||||||
@ -69,8 +69,24 @@ export class ModuleIssueStore implements IModuleIssueStore {
|
|||||||
fetchIssues: action,
|
fetchIssues: action,
|
||||||
updateIssueStructure: action,
|
updateIssueStructure: action,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.rootStore = _rootStore;
|
this.rootStore = _rootStore;
|
||||||
this.moduleService = new ModuleService();
|
this.moduleService = new ModuleService();
|
||||||
|
|
||||||
|
autorun(() => {
|
||||||
|
const workspaceSlug = this.rootStore.workspace.workspaceSlug;
|
||||||
|
const projectId = this.rootStore.project.projectId;
|
||||||
|
const moduleId = this.rootStore.module.moduleId;
|
||||||
|
|
||||||
|
if (
|
||||||
|
workspaceSlug &&
|
||||||
|
projectId &&
|
||||||
|
moduleId &&
|
||||||
|
this.rootStore.moduleFilter.moduleFilters &&
|
||||||
|
this.rootStore.issueFilter.userDisplayFilters
|
||||||
|
)
|
||||||
|
this.fetchIssues(workspaceSlug, projectId, moduleId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get getIssueType() {
|
get getIssueType() {
|
||||||
@ -156,11 +172,7 @@ export class ModuleIssueStore implements IModuleIssueStore {
|
|||||||
this.loader = true;
|
this.loader = true;
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
this.rootStore.workspace.setWorkspaceSlug(workspaceSlug);
|
const params = this.rootStore?.moduleFilter?.appliedFilters;
|
||||||
this.rootStore.project.setProjectId(projectId);
|
|
||||||
this.rootStore.module.setModuleId(moduleId);
|
|
||||||
|
|
||||||
const params = this.rootStore?.cycleIssueFilter?.appliedFilters;
|
|
||||||
const issueResponse = await this.moduleService.getModuleIssuesWithParams(
|
const issueResponse = await this.moduleService.getModuleIssuesWithParams(
|
||||||
workspaceSlug,
|
workspaceSlug,
|
||||||
projectId,
|
projectId,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { observable, action, makeObservable, runInAction, computed } from "mobx";
|
import { observable, action, makeObservable, runInAction, computed, autorun } from "mobx";
|
||||||
// services
|
// services
|
||||||
import { IssueService } from "services/issue";
|
import { IssueService } from "services/issue";
|
||||||
// helpers
|
// helpers
|
||||||
@ -79,8 +79,22 @@ export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.rootStore = _rootStore;
|
this.rootStore = _rootStore;
|
||||||
|
|
||||||
this.issueService = new IssueService();
|
this.issueService = new IssueService();
|
||||||
|
|
||||||
|
autorun(() => {
|
||||||
|
const workspaceSlug = this.rootStore.workspace.workspaceSlug;
|
||||||
|
const projectId = this.rootStore.project.projectId;
|
||||||
|
const viewId = this.rootStore.projectViews.viewId;
|
||||||
|
|
||||||
|
if (
|
||||||
|
workspaceSlug &&
|
||||||
|
projectId &&
|
||||||
|
viewId &&
|
||||||
|
this.rootStore.projectViewFilters.storedFilters[viewId] &&
|
||||||
|
this.rootStore.issueFilter.userDisplayFilters
|
||||||
|
)
|
||||||
|
this.fetchViewIssues(workspaceSlug, projectId, viewId, this.rootStore.projectViewFilters.storedFilters[viewId]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
computedFilter = (filters: any, filteredParams: any) => {
|
computedFilter = (filters: any, filteredParams: any) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user