forked from github/plane
fix: project identifier check in project settings (#613)
This commit is contained in:
parent
b65fa89cdb
commit
16abbe0b3e
@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
@ -13,7 +13,6 @@ import { requiredAdmin } from "lib/auth";
|
|||||||
import AppLayout from "layouts/app-layout";
|
import AppLayout from "layouts/app-layout";
|
||||||
// services
|
// services
|
||||||
import projectService from "services/project.service";
|
import projectService from "services/project.service";
|
||||||
import workspaceService from "services/workspace.service";
|
|
||||||
// components
|
// components
|
||||||
import { DeleteProjectModal } from "components/project";
|
import { DeleteProjectModal } from "components/project";
|
||||||
import EmojiIconPicker from "components/emoji-icon-picker";
|
import EmojiIconPicker from "components/emoji-icon-picker";
|
||||||
@ -29,12 +28,10 @@ import {
|
|||||||
SecondaryButton,
|
SecondaryButton,
|
||||||
} from "components/ui";
|
} from "components/ui";
|
||||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||||
// helpers
|
|
||||||
import { debounce } from "helpers/common.helper";
|
|
||||||
// types
|
// types
|
||||||
import type { NextPage, GetServerSidePropsContext } from "next";
|
import type { NextPage, GetServerSidePropsContext } from "next";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { PROJECTS_LIST, PROJECT_DETAILS, WORKSPACE_DETAILS } from "constants/fetch-keys";
|
import { PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys";
|
||||||
// constants
|
// constants
|
||||||
import { NETWORK_CHOICES } from "constants/project";
|
import { NETWORK_CHOICES } from "constants/project";
|
||||||
|
|
||||||
@ -45,9 +42,7 @@ const defaultValues: Partial<IProject> = {
|
|||||||
network: 0,
|
network: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const GeneralSettings: NextPage<UserAuth> = (props) => {
|
const GeneralSettings: NextPage<UserAuth> = ({ isMember, isOwner, isViewer, isGuest }) => {
|
||||||
const { isMember, isOwner, isViewer, isGuest } = props;
|
|
||||||
|
|
||||||
const [selectProject, setSelectedProject] = useState<string | null>(null);
|
const [selectProject, setSelectedProject] = useState<string | null>(null);
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
@ -55,11 +50,6 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, projectId } = router.query;
|
||||||
|
|
||||||
const { data: activeWorkspace } = useSWR(
|
|
||||||
workspaceSlug ? WORKSPACE_DETAILS(workspaceSlug as string) : null,
|
|
||||||
() => (workspaceSlug ? workspaceService.getWorkspace(workspaceSlug as string) : null)
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data: projectDetails } = useSWR<IProject>(
|
const { data: projectDetails } = useSWR<IProject>(
|
||||||
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
||||||
workspaceSlug && projectId
|
workspaceSlug && projectId
|
||||||
@ -78,14 +68,15 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
|
|||||||
defaultValues,
|
defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
const checkIdentifier = (slug: string, value: string) => {
|
const checkIdentifier = (value: string) => {
|
||||||
projectService.checkProjectIdentifierAvailability(slug, value).then((response) => {
|
if (!workspaceSlug) return;
|
||||||
if (response.exists) setError("identifier", { message: "Identifier already exists" });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
projectService
|
||||||
const checkIdentifierAvailability = useCallback(debounce(checkIdentifier, 1500), []);
|
.checkProjectIdentifierAvailability(workspaceSlug as string, value)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.exists) setError("identifier", { message: "Identifier already exists" });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (projectDetails)
|
if (projectDetails)
|
||||||
@ -98,7 +89,7 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
|
|||||||
}, [projectDetails, reset]);
|
}, [projectDetails, reset]);
|
||||||
|
|
||||||
const onSubmit = async (formData: IProject) => {
|
const onSubmit = async (formData: IProject) => {
|
||||||
if (!activeWorkspace || !projectDetails) return;
|
if (!workspaceSlug || !projectDetails) return;
|
||||||
|
|
||||||
const payload: Partial<IProject> = {
|
const payload: Partial<IProject> = {
|
||||||
name: formData.name,
|
name: formData.name,
|
||||||
@ -111,22 +102,32 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await projectService
|
await projectService
|
||||||
.updateProject(activeWorkspace.slug, projectDetails.id, payload)
|
.checkProjectIdentifierAvailability(workspaceSlug as string, payload.identifier ?? "")
|
||||||
.then((res) => {
|
.then(async (res) => {
|
||||||
mutate<IProject>(
|
if (res.exists) setError("identifier", { message: "Identifier already exists" });
|
||||||
PROJECT_DETAILS(projectDetails.id),
|
else
|
||||||
(prevData) => ({ ...prevData, ...res }),
|
await projectService
|
||||||
false
|
.updateProject(workspaceSlug as string, projectDetails.id, payload)
|
||||||
);
|
.then((res) => {
|
||||||
mutate(PROJECTS_LIST(activeWorkspace.slug));
|
mutate<IProject>(
|
||||||
setToastAlert({
|
PROJECT_DETAILS(projectDetails.id),
|
||||||
title: "Success",
|
(prevData) => ({ ...prevData, ...res }),
|
||||||
type: "success",
|
false
|
||||||
message: "Project updated successfully",
|
);
|
||||||
});
|
mutate(PROJECTS_LIST(workspaceSlug as string));
|
||||||
})
|
setToastAlert({
|
||||||
.catch((err) => {
|
type: "success",
|
||||||
console.error(err);
|
title: "Success!",
|
||||||
|
message: "Project updated successfully",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setToastAlert({
|
||||||
|
type: "error",
|
||||||
|
title: "Error!",
|
||||||
|
message: "Project could not be updated. Please try again.",
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -233,10 +234,6 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
|
|||||||
error={errors.identifier}
|
error={errors.identifier}
|
||||||
register={register}
|
register={register}
|
||||||
placeholder="Enter identifier"
|
placeholder="Enter identifier"
|
||||||
onChange={(e: any) => {
|
|
||||||
if (!activeWorkspace || !e.target.value) return;
|
|
||||||
checkIdentifierAvailability(activeWorkspace.slug, e.target.value);
|
|
||||||
}}
|
|
||||||
validations={{
|
validations={{
|
||||||
required: "Identifier is required",
|
required: "Identifier is required",
|
||||||
minLength: {
|
minLength: {
|
||||||
|
Loading…
Reference in New Issue
Block a user