forked from github/plane
Compare commits
2 Commits
preview
...
dev/issue_
Author | SHA1 | Date | |
---|---|---|---|
|
b9975dfa24 | ||
|
380ad340a6 |
@ -4,8 +4,13 @@ import { useRouter } from "next/router";
|
||||
|
||||
import { mutate } from "swr";
|
||||
|
||||
// mobx
|
||||
import { useObserver } from "mobx-react-lite";
|
||||
|
||||
// react-hook-form
|
||||
import { Controller, SubmitHandler, useForm } from "react-hook-form";
|
||||
// store
|
||||
import labelStore from "store/labels";
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// react-color
|
||||
@ -58,20 +63,17 @@ export const CreateUpdateLabelInline = forwardRef<Ref, Props>(function CreateUpd
|
||||
defaultValues,
|
||||
});
|
||||
|
||||
const handleLabelCreate: SubmitHandler<IIssueLabels> = async (formData) => {
|
||||
if (!workspaceSlug || !projectId || isSubmitting) return;
|
||||
const { createLabel } = useObserver(() => ({
|
||||
createLabel: labelStore.createLabel,
|
||||
}));
|
||||
|
||||
await issuesService
|
||||
.createIssueLabel(workspaceSlug as string, projectId as string, formData, user)
|
||||
.then((res) => {
|
||||
mutate<IIssueLabels[]>(
|
||||
PROJECT_ISSUE_LABELS(projectId as string),
|
||||
(prevData) => [res, ...(prevData ?? [])],
|
||||
false
|
||||
);
|
||||
reset(defaultValues);
|
||||
setLabelForm(false);
|
||||
});
|
||||
const handleLabelCreate: SubmitHandler<IIssueLabels> = async (formData) => {
|
||||
if (!workspaceSlug || !projectId || isSubmitting || !user) return;
|
||||
|
||||
await createLabel(workspaceSlug.toString(), projectId.toString(), formData, user).then(() => {
|
||||
reset(defaultValues);
|
||||
setLabelForm(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleLabelUpdate: SubmitHandler<IIssueLabels> = async (formData) => {
|
||||
|
@ -4,7 +4,7 @@ import { RootStore } from "store/root";
|
||||
|
||||
let rootStore: any = null;
|
||||
|
||||
export const MobxStoreContext = createContext(null);
|
||||
export const MobxStoreContext = createContext<RootStore>({} as RootStore);
|
||||
|
||||
const initializeStore = () => {
|
||||
const _rootStore = rootStore ?? new RootStore();
|
||||
|
@ -1,14 +1,17 @@
|
||||
import React, { useState, useRef } from "react";
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// services
|
||||
import projectService from "services/project.service";
|
||||
import issuesService from "services/issues.service";
|
||||
// layouts
|
||||
import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
|
||||
// components
|
||||
@ -31,7 +34,7 @@ import emptyLabel from "public/empty-state/label.svg";
|
||||
import { IIssueLabels } from "types";
|
||||
import type { NextPage } from "next";
|
||||
// fetch-keys
|
||||
import { PROJECT_DETAILS, PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
|
||||
import { PROJECT_DETAILS } from "constants/fetch-keys";
|
||||
// helper
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
|
||||
@ -57,6 +60,9 @@ const LabelsSettings: NextPage = () => {
|
||||
|
||||
const scrollToRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const { labelStore } = useMobxStore();
|
||||
const { isLabelsLoading: isLoading, labels } = labelStore;
|
||||
|
||||
const { data: projectDetails } = useSWR(
|
||||
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -64,13 +70,6 @@ const LabelsSettings: NextPage = () => {
|
||||
: null
|
||||
);
|
||||
|
||||
const { data: issueLabels } = useSWR(
|
||||
workspaceSlug && projectId ? PROJECT_ISSUE_LABELS(projectId as string) : null,
|
||||
workspaceSlug && projectId
|
||||
? () => issuesService.getIssueLabels(workspaceSlug as string, projectId as string)
|
||||
: null
|
||||
);
|
||||
|
||||
const newLabel = () => {
|
||||
setIsUpdating(false);
|
||||
setLabelForm(true);
|
||||
@ -87,6 +86,11 @@ const LabelsSettings: NextPage = () => {
|
||||
setLabelToUpdate(label);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (workspaceSlug && projectId)
|
||||
labelStore.loadLabels(workspaceSlug.toString(), projectId.toString());
|
||||
}, [workspaceSlug, projectId, labelStore]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<LabelsListModal
|
||||
@ -137,10 +141,10 @@ const LabelsSettings: NextPage = () => {
|
||||
/>
|
||||
)}
|
||||
<>
|
||||
{issueLabels ? (
|
||||
issueLabels.length > 0 ? (
|
||||
issueLabels.map((label) => {
|
||||
const children = issueLabels?.filter((l) => l.parent === label.id);
|
||||
{!isLoading ? (
|
||||
labels.length > 0 ? (
|
||||
labels.map((label) => {
|
||||
const children = labels?.filter((l) => l.parent === label.id);
|
||||
|
||||
if (children && children.length === 0) {
|
||||
if (!label.parent)
|
||||
@ -148,7 +152,17 @@ const LabelsSettings: NextPage = () => {
|
||||
<SingleLabel
|
||||
key={label.id}
|
||||
label={label}
|
||||
addLabelToGroup={() => addLabelToGroup(label)}
|
||||
addLabelToGroup={() => {
|
||||
addLabelToGroup(label);
|
||||
// if (!workspaceSlug || !projectId || !user) return;
|
||||
// labelStore.updateLabel(
|
||||
// workspaceSlug.toString(),
|
||||
// projectId.toString(),
|
||||
// label.id,
|
||||
// { parent: label.id },
|
||||
// user
|
||||
// );
|
||||
}}
|
||||
editLabel={(label) => {
|
||||
editLabel(label);
|
||||
scrollToRef.current?.scrollIntoView({
|
||||
@ -205,4 +219,4 @@ const LabelsSettings: NextPage = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default LabelsSettings;
|
||||
export default observer(LabelsSettings);
|
||||
|
107
apps/app/store/labels.ts
Normal file
107
apps/app/store/labels.ts
Normal file
@ -0,0 +1,107 @@
|
||||
// mobx
|
||||
import { action, observable, runInAction, makeAutoObservable } from "mobx";
|
||||
|
||||
// services
|
||||
import issueService from "services/issues.service";
|
||||
|
||||
// types
|
||||
import type { IIssueLabels, LabelForm, ICurrentUserResponse } from "types";
|
||||
|
||||
class LabelStore {
|
||||
labels: IIssueLabels[] = [];
|
||||
isLabelsLoading: boolean = false;
|
||||
rootStore: any | null = null;
|
||||
|
||||
constructor(_rootStore: any | null = null) {
|
||||
makeAutoObservable(this, {
|
||||
labels: observable.ref,
|
||||
loadLabels: action,
|
||||
isLabelsLoading: observable,
|
||||
createLabel: action,
|
||||
updateLabel: action,
|
||||
deleteLabel: action,
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
}
|
||||
|
||||
loadLabels = async (workspaceSlug: string, projectId: string) => {
|
||||
this.isLabelsLoading = true;
|
||||
try {
|
||||
const labelsResponse: IIssueLabels[] = await issueService.getIssueLabels(
|
||||
workspaceSlug,
|
||||
projectId
|
||||
);
|
||||
runInAction(() => {
|
||||
this.labels = labelsResponse;
|
||||
this.isLabelsLoading = false;
|
||||
});
|
||||
} catch (error) {
|
||||
this.isLabelsLoading = false;
|
||||
console.error("Fetching labels error", error);
|
||||
}
|
||||
};
|
||||
|
||||
createLabel = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
labelForm: LabelForm,
|
||||
user: ICurrentUserResponse
|
||||
) => {
|
||||
try {
|
||||
const labelResponse: IIssueLabels = await issueService.createIssueLabel(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
labelForm,
|
||||
user
|
||||
);
|
||||
runInAction(() => {
|
||||
this.labels.push(labelResponse);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Creating label error", error);
|
||||
}
|
||||
};
|
||||
|
||||
updateLabel = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
labelId: string,
|
||||
labelForm: Partial<LabelForm>,
|
||||
user: ICurrentUserResponse
|
||||
) => {
|
||||
try {
|
||||
const labelResponse: IIssueLabels = await issueService.patchIssueLabel(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
labelId,
|
||||
labelForm,
|
||||
user
|
||||
);
|
||||
runInAction(() => {
|
||||
const labelIndex = this.labels.findIndex((label) => label.id === labelId);
|
||||
this.labels[labelIndex] = labelResponse;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Updating label error", error);
|
||||
}
|
||||
};
|
||||
|
||||
deleteLabel = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
labelId: string,
|
||||
user: ICurrentUserResponse
|
||||
) => {
|
||||
try {
|
||||
await issueService.deleteIssueLabel(workspaceSlug, projectId, labelId, user);
|
||||
runInAction(() => {
|
||||
this.labels = this.labels.filter((label) => label.id !== labelId);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Deleting label error", error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default LabelStore;
|
@ -3,15 +3,18 @@ import { enableStaticRendering } from "mobx-react-lite";
|
||||
// store imports
|
||||
import UserStore from "./user";
|
||||
import ThemeStore from "./theme";
|
||||
import LabelStore from "./labels";
|
||||
|
||||
enableStaticRendering(typeof window === "undefined");
|
||||
|
||||
export class RootStore {
|
||||
user;
|
||||
theme;
|
||||
labelStore: LabelStore;
|
||||
|
||||
constructor() {
|
||||
this.user = new UserStore(this);
|
||||
this.theme = new ThemeStore(this);
|
||||
this.labelStore = new LabelStore(this);
|
||||
}
|
||||
}
|
||||
|
9
apps/app/types/issues.d.ts
vendored
9
apps/app/types/issues.d.ts
vendored
@ -164,6 +164,15 @@ export interface IIssueLabels {
|
||||
parent: string | null;
|
||||
}
|
||||
|
||||
export interface LabelForm {
|
||||
name: string;
|
||||
description: string;
|
||||
color: string;
|
||||
project: string;
|
||||
workspace: string;
|
||||
parent: string | null;
|
||||
}
|
||||
|
||||
export interface IIssueActivity {
|
||||
actor: string;
|
||||
actor_detail: IUserLite;
|
||||
|
Loading…
Reference in New Issue
Block a user