mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: mutation of project detail, removed two identifier validation and added default value for deep checking
This commit is contained in:
parent
1368fb9164
commit
a1598e7310
@ -8,6 +8,8 @@ import { Dialog, Transition } from "@headlessui/react";
|
|||||||
// services
|
// services
|
||||||
import projectServices from "lib/services/project.service";
|
import projectServices from "lib/services/project.service";
|
||||||
import workspaceService from "lib/services/workspace.service";
|
import workspaceService from "lib/services/workspace.service";
|
||||||
|
// constants
|
||||||
|
import { NETWORK_CHOICES } from "constants/";
|
||||||
// fetch keys
|
// fetch keys
|
||||||
import { PROJECTS_LIST, WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
import { PROJECTS_LIST, WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
||||||
// hooks
|
// hooks
|
||||||
@ -15,8 +17,6 @@ import useUser from "lib/hooks/useUser";
|
|||||||
import useToast from "lib/hooks/useToast";
|
import useToast from "lib/hooks/useToast";
|
||||||
// ui
|
// ui
|
||||||
import { Button, Input, TextArea, Select } from "ui";
|
import { Button, Input, TextArea, Select } from "ui";
|
||||||
// common
|
|
||||||
import { debounce } from "constants/common";
|
|
||||||
// types
|
// types
|
||||||
import { IProject, WorkspaceMember } from "types";
|
import { IProject, WorkspaceMember } from "types";
|
||||||
|
|
||||||
@ -25,11 +25,11 @@ type Props = {
|
|||||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NETWORK_CHOICES = { "0": "Secret", "2": "Public" };
|
|
||||||
|
|
||||||
const defaultValues: Partial<IProject> = {
|
const defaultValues: Partial<IProject> = {
|
||||||
name: "",
|
name: "",
|
||||||
|
identifier: "",
|
||||||
description: "",
|
description: "",
|
||||||
|
network: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const IsGuestCondition: React.FC<{
|
const IsGuestCondition: React.FC<{
|
||||||
@ -62,7 +62,10 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
|||||||
|
|
||||||
const { data: workspaceMembers } = useSWR<WorkspaceMember[]>(
|
const { data: workspaceMembers } = useSWR<WorkspaceMember[]>(
|
||||||
activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
|
activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
|
||||||
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null
|
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null,
|
||||||
|
{
|
||||||
|
shouldRetryOnError: false,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
@ -79,8 +82,6 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
|||||||
setValue,
|
setValue,
|
||||||
} = useForm<IProject>({
|
} = useForm<IProject>({
|
||||||
defaultValues,
|
defaultValues,
|
||||||
reValidateMode: "onChange",
|
|
||||||
mode: "all",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = async (formData: IProject) => {
|
const onSubmit = async (formData: IProject) => {
|
||||||
@ -111,6 +112,7 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
|||||||
handleClose();
|
handleClose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
err = err.data;
|
||||||
Object.keys(err).map((key) => {
|
Object.keys(err).map((key) => {
|
||||||
const errorMessages = err[key];
|
const errorMessages = err[key];
|
||||||
setError(key as keyof IProject, {
|
setError(key as keyof IProject, {
|
||||||
@ -123,16 +125,6 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
|||||||
const projectName = watch("name") ?? "";
|
const projectName = watch("name") ?? "";
|
||||||
const projectIdentifier = watch("identifier") ?? "";
|
const projectIdentifier = watch("identifier") ?? "";
|
||||||
|
|
||||||
const checkIdentifier = (slug: string, value: string) => {
|
|
||||||
projectServices.checkProjectIdentifierAvailability(slug, value).then((response) => {
|
|
||||||
console.log(response);
|
|
||||||
if (response.exists) setError("identifier", { message: "Identifier already exists" });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
const checkIdentifierAvailability = useCallback(debounce(checkIdentifier, 1500), []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (projectName && isChangeIdentifierRequired) {
|
if (projectName && isChangeIdentifierRequired) {
|
||||||
setValue("identifier", projectName.replace(/ /g, "-").toUpperCase().substring(0, 3));
|
setValue("identifier", projectName.replace(/ /g, "-").toUpperCase().substring(0, 3));
|
||||||
@ -234,11 +226,7 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
|
|||||||
placeholder="Enter Project Identifier"
|
placeholder="Enter Project Identifier"
|
||||||
error={errors.identifier}
|
error={errors.identifier}
|
||||||
register={register}
|
register={register}
|
||||||
onChange={(e: any) => {
|
onChange={() => setIsChangeIdentifierRequired(false)}
|
||||||
setIsChangeIdentifierRequired(false);
|
|
||||||
if (!activeWorkspace || !e.target.value) return;
|
|
||||||
checkIdentifierAvailability(activeWorkspace.slug, e.target.value);
|
|
||||||
}}
|
|
||||||
validations={{
|
validations={{
|
||||||
required: "Identifier is required",
|
required: "Identifier is required",
|
||||||
minLength: {
|
minLength: {
|
||||||
|
@ -65,6 +65,8 @@ export const PROJECT_MEMBERS = (workspaceSlug: string, projectId: string) =>
|
|||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`;
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`;
|
||||||
export const PROJECT_MEMBER_DETAIL = (workspaceSlug: string, projectId: string, memberId: string) =>
|
export const PROJECT_MEMBER_DETAIL = (workspaceSlug: string, projectId: string, memberId: string) =>
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`;
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`;
|
||||||
|
export const PROJECT_VIEW_ENDPOINT = (workspaceSlug: string, projectId: string) =>
|
||||||
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/project-views/`;
|
||||||
|
|
||||||
export const PROJECT_INVITATIONS = (workspaceSlug: string, projectId: string) =>
|
export const PROJECT_INVITATIONS = (workspaceSlug: string, projectId: string) =>
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/`;
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/`;
|
||||||
|
@ -7,7 +7,7 @@ export const WORKSPACE_INVITATIONS = "WORKSPACE_INVITATIONS";
|
|||||||
export const WORKSPACE_INVITATION = "WORKSPACE_INVITATION";
|
export const WORKSPACE_INVITATION = "WORKSPACE_INVITATION";
|
||||||
|
|
||||||
export const PROJECTS_LIST = (workspaceSlug: string) => `PROJECTS_LIST_${workspaceSlug}`;
|
export const PROJECTS_LIST = (workspaceSlug: string) => `PROJECTS_LIST_${workspaceSlug}`;
|
||||||
export const PROJECT_DETAILS = "PROJECT_DETAILS";
|
export const PROJECT_DETAILS = (projectId: string) => `PROJECT_DETAILS_${projectId}`;
|
||||||
|
|
||||||
export const PROJECT_MEMBERS = (projectId: string) => `PROJECT_MEMBERS_${projectId}`;
|
export const PROJECT_MEMBERS = (projectId: string) => `PROJECT_MEMBERS_${projectId}`;
|
||||||
export const PROJECT_INVITATIONS = "PROJECT_INVITATIONS";
|
export const PROJECT_INVITATIONS = "PROJECT_INVITATIONS";
|
||||||
|
@ -6,3 +6,5 @@ export const ROLE = {
|
|||||||
15: "Member",
|
15: "Member",
|
||||||
20: "Admin",
|
20: "Admin",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const NETWORK_CHOICES = { "0": "Secret", "2": "Public" };
|
||||||
|
@ -2,3 +2,5 @@ export const TOGGLE_SIDEBAR = "TOGGLE_SIDEBAR";
|
|||||||
export const REHYDRATE_THEME = "REHYDRATE_THEME";
|
export const REHYDRATE_THEME = "REHYDRATE_THEME";
|
||||||
export const SET_ISSUE_VIEW = "SET_ISSUE_VIEW";
|
export const SET_ISSUE_VIEW = "SET_ISSUE_VIEW";
|
||||||
export const SET_GROUP_BY_PROPERTY = "SET_GROUP_BY_PROPERTY";
|
export const SET_GROUP_BY_PROPERTY = "SET_GROUP_BY_PROPERTY";
|
||||||
|
export const SET_ORDER_BY_PROPERTY = "SET_ORDER_BY_PROPERTY";
|
||||||
|
export const SET_FILTER_ISSUES = "SET_FILTER_ISSUES";
|
||||||
|
@ -5,6 +5,8 @@ import {
|
|||||||
REHYDRATE_THEME,
|
REHYDRATE_THEME,
|
||||||
SET_ISSUE_VIEW,
|
SET_ISSUE_VIEW,
|
||||||
SET_GROUP_BY_PROPERTY,
|
SET_GROUP_BY_PROPERTY,
|
||||||
|
SET_ORDER_BY_PROPERTY,
|
||||||
|
SET_FILTER_ISSUES,
|
||||||
} from "constants/theme.context.constants";
|
} from "constants/theme.context.constants";
|
||||||
// components
|
// components
|
||||||
import ToastAlert from "components/toast-alert";
|
import ToastAlert from "components/toast-alert";
|
||||||
@ -12,30 +14,30 @@ import ToastAlert from "components/toast-alert";
|
|||||||
export const themeContext = createContext<ContextType>({} as ContextType);
|
export const themeContext = createContext<ContextType>({} as ContextType);
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import type { IIssue, NestedKeyOf } from "types";
|
import type { IIssue, NestedKeyOf, ProjectViewTheme as Theme } from "types";
|
||||||
|
|
||||||
type Theme = {
|
|
||||||
collapsed: boolean;
|
|
||||||
issueView: "list" | "kanban" | null;
|
|
||||||
groupByProperty: NestedKeyOf<IIssue> | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ReducerActionType = {
|
type ReducerActionType = {
|
||||||
type:
|
type:
|
||||||
| typeof TOGGLE_SIDEBAR
|
| typeof TOGGLE_SIDEBAR
|
||||||
| typeof REHYDRATE_THEME
|
| typeof REHYDRATE_THEME
|
||||||
| typeof SET_ISSUE_VIEW
|
| typeof SET_ISSUE_VIEW
|
||||||
|
| typeof SET_ORDER_BY_PROPERTY
|
||||||
|
| typeof SET_FILTER_ISSUES
|
||||||
| typeof SET_GROUP_BY_PROPERTY;
|
| typeof SET_GROUP_BY_PROPERTY;
|
||||||
payload?: Partial<Theme>;
|
payload?: Partial<Theme>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ContextType = {
|
type ContextType = {
|
||||||
collapsed: boolean;
|
collapsed: boolean;
|
||||||
|
orderBy: NestedKeyOf<IIssue> | null;
|
||||||
issueView: "list" | "kanban" | null;
|
issueView: "list" | "kanban" | null;
|
||||||
groupByProperty: NestedKeyOf<IIssue> | null;
|
groupByProperty: NestedKeyOf<IIssue> | null;
|
||||||
|
filterIssue: "activeIssue" | "backlogIssue" | null;
|
||||||
toggleCollapsed: () => void;
|
toggleCollapsed: () => void;
|
||||||
setIssueView: (display: "list" | "kanban") => void;
|
setIssueView: (display: "list" | "kanban") => void;
|
||||||
setGroupByProperty: (property: NestedKeyOf<IIssue> | null) => void;
|
setGroupByProperty: (property: NestedKeyOf<IIssue> | null) => void;
|
||||||
|
setOrderBy: (property: NestedKeyOf<IIssue> | null) => void;
|
||||||
|
setFilterIssue: (property: "activeIssue" | "backlogIssue" | null) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateType = Theme;
|
type StateType = Theme;
|
||||||
@ -45,6 +47,8 @@ export const initialState: StateType = {
|
|||||||
collapsed: false,
|
collapsed: false,
|
||||||
issueView: "list",
|
issueView: "list",
|
||||||
groupByProperty: null,
|
groupByProperty: null,
|
||||||
|
orderBy: null,
|
||||||
|
filterIssue: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const reducer: ReducerFunctionType = (state, action) => {
|
export const reducer: ReducerFunctionType = (state, action) => {
|
||||||
@ -87,6 +91,28 @@ export const reducer: ReducerFunctionType = (state, action) => {
|
|||||||
...newState,
|
...newState,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case SET_ORDER_BY_PROPERTY: {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
orderBy: payload?.orderBy || null,
|
||||||
|
};
|
||||||
|
localStorage.setItem("theme", JSON.stringify(newState));
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...newState,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case SET_FILTER_ISSUES: {
|
||||||
|
const newState = {
|
||||||
|
...state,
|
||||||
|
filterIssue: payload?.filterIssue || null,
|
||||||
|
};
|
||||||
|
localStorage.setItem("theme", JSON.stringify(newState));
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...newState,
|
||||||
|
};
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -120,6 +146,24 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const setOrderBy = useCallback((property: NestedKeyOf<IIssue> | null) => {
|
||||||
|
dispatch({
|
||||||
|
type: SET_ORDER_BY_PROPERTY,
|
||||||
|
payload: {
|
||||||
|
orderBy: property,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const setFilterIssue = useCallback((property: "activeIssue" | "backlogIssue" | null) => {
|
||||||
|
dispatch({
|
||||||
|
type: SET_FILTER_ISSUES,
|
||||||
|
payload: {
|
||||||
|
filterIssue: property,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: REHYDRATE_THEME,
|
type: REHYDRATE_THEME,
|
||||||
@ -135,6 +179,10 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
setIssueView,
|
setIssueView,
|
||||||
groupByProperty: state.groupByProperty,
|
groupByProperty: state.groupByProperty,
|
||||||
setGroupByProperty,
|
setGroupByProperty,
|
||||||
|
orderBy: state.orderBy,
|
||||||
|
setOrderBy,
|
||||||
|
filterIssue: state.filterIssue,
|
||||||
|
setFilterIssue,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ToastAlert />
|
<ToastAlert />
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useState } from "react";
|
|
||||||
// hooks
|
// hooks
|
||||||
import useTheme from "./useTheme";
|
import useTheme from "./useTheme";
|
||||||
import useUser from "./useUser";
|
import useUser from "./useUser";
|
||||||
@ -7,14 +6,19 @@ import { groupBy, orderArrayBy } from "constants/common";
|
|||||||
// constants
|
// constants
|
||||||
import { PRIORITIES } from "constants/";
|
import { PRIORITIES } from "constants/";
|
||||||
// types
|
// types
|
||||||
import type { IssueResponse, IIssue, NestedKeyOf } from "types";
|
import type { IssueResponse, IIssue } from "types";
|
||||||
|
|
||||||
const useIssuesFilter = (projectIssues?: IssueResponse) => {
|
const useIssuesFilter = (projectIssues?: IssueResponse) => {
|
||||||
const { issueView, setIssueView, groupByProperty, setGroupByProperty } = useTheme();
|
const {
|
||||||
|
issueView,
|
||||||
const [orderBy, setOrderBy] = useState<NestedKeyOf<IIssue> | null>(null);
|
setIssueView,
|
||||||
|
groupByProperty,
|
||||||
const [filterIssue, setFilterIssue] = useState<"activeIssue" | "backlogIssue" | null>(null);
|
setGroupByProperty,
|
||||||
|
orderBy,
|
||||||
|
setOrderBy,
|
||||||
|
filterIssue,
|
||||||
|
setFilterIssue,
|
||||||
|
} = useTheme();
|
||||||
|
|
||||||
const { states } = useUser();
|
const { states } = useUser();
|
||||||
|
|
||||||
@ -52,29 +56,29 @@ const useIssuesFilter = (projectIssues?: IssueResponse) => {
|
|||||||
|
|
||||||
if (filterIssue !== null) {
|
if (filterIssue !== null) {
|
||||||
if (filterIssue === "activeIssue") {
|
if (filterIssue === "activeIssue") {
|
||||||
groupedByIssues = Object.keys(groupedByIssues).reduce((acc, key) => {
|
const filteredStates = states?.filter(
|
||||||
const value = groupedByIssues[key];
|
(state) => state.group === "started" || state.group === "unstarted"
|
||||||
const filteredValue = value.filter(
|
);
|
||||||
(issue) =>
|
groupedByIssues = Object.fromEntries(
|
||||||
issue.state_detail.group === "started" || issue.state_detail.group === "unstarted"
|
filteredStates
|
||||||
);
|
?.sort((a, b) => a.sequence - b.sequence)
|
||||||
if (filteredValue.length > 0) {
|
?.map((state) => [
|
||||||
acc[key] = filteredValue;
|
state.name,
|
||||||
}
|
projectIssues?.results.filter((issue) => issue.state === state.id) ?? [],
|
||||||
return acc;
|
]) ?? []
|
||||||
}, {} as typeof groupedByIssues);
|
);
|
||||||
} else if (filterIssue === "backlogIssue") {
|
} else if (filterIssue === "backlogIssue") {
|
||||||
groupedByIssues = Object.keys(groupedByIssues).reduce((acc, key) => {
|
const filteredStates = states?.filter(
|
||||||
const value = groupedByIssues[key];
|
(state) => state.group === "backlog" || state.group === "cancelled"
|
||||||
const filteredValue = value.filter(
|
);
|
||||||
(issue) =>
|
groupedByIssues = Object.fromEntries(
|
||||||
issue.state_detail.group === "backlog" || issue.state_detail.group === "cancelled"
|
filteredStates
|
||||||
);
|
?.sort((a, b) => a.sequence - b.sequence)
|
||||||
if (filteredValue.length > 0) {
|
?.map((state) => [
|
||||||
acc[key] = filteredValue;
|
state.name,
|
||||||
}
|
projectIssues?.results.filter((issue) => issue.state === state.id) ?? [],
|
||||||
return acc;
|
]) ?? []
|
||||||
}, {} as typeof groupedByIssues);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,12 @@ import {
|
|||||||
PROJECT_MEMBERS,
|
PROJECT_MEMBERS,
|
||||||
PROJECT_MEMBER_DETAIL,
|
PROJECT_MEMBER_DETAIL,
|
||||||
USER_PROJECT_INVITATIONS,
|
USER_PROJECT_INVITATIONS,
|
||||||
|
PROJECT_VIEW_ENDPOINT,
|
||||||
} from "constants/api-routes";
|
} from "constants/api-routes";
|
||||||
// services
|
// services
|
||||||
import APIService from "lib/services/api.service";
|
import APIService from "lib/services/api.service";
|
||||||
|
// types
|
||||||
|
import type { ProjectViewTheme } from "types";
|
||||||
|
|
||||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||||
|
|
||||||
@ -177,6 +180,7 @@ class ProjectServices extends APIService {
|
|||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteProjectInvitation(
|
async deleteProjectInvitation(
|
||||||
workspace_slug: string,
|
workspace_slug: string,
|
||||||
project_id: string,
|
project_id: string,
|
||||||
@ -190,6 +194,20 @@ class ProjectServices extends APIService {
|
|||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setProjectView(
|
||||||
|
workspace_slug: string,
|
||||||
|
project_id: string,
|
||||||
|
data: ProjectViewTheme
|
||||||
|
): Promise<any> {
|
||||||
|
await this.patch(PROJECT_VIEW_ENDPOINT(workspace_slug, project_id), data)
|
||||||
|
.then((response) => {
|
||||||
|
return response?.data;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new ProjectServices();
|
export default new ProjectServices();
|
||||||
|
@ -8,6 +8,8 @@ import { useForm } from "react-hook-form";
|
|||||||
import workspaceService from "lib/services/workspace.service";
|
import workspaceService from "lib/services/workspace.service";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "lib/hooks/useUser";
|
import useUser from "lib/hooks/useUser";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import DefaultLayout from "layouts/DefaultLayout";
|
import DefaultLayout from "layouts/DefaultLayout";
|
||||||
// ui
|
// ui
|
||||||
@ -144,4 +146,4 @@ const CreateWorkspace: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CreateWorkspace;
|
export default withAuth(CreateWorkspace);
|
||||||
|
@ -11,6 +11,8 @@ import userService from "lib/services/user.service";
|
|||||||
import useUser from "lib/hooks/useUser";
|
import useUser from "lib/hooks/useUser";
|
||||||
// constants
|
// constants
|
||||||
import { USER_WORKSPACE_INVITATIONS } from "constants/api-routes";
|
import { USER_WORKSPACE_INVITATIONS } from "constants/api-routes";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import DefaultLayout from "layouts/DefaultLayout";
|
import DefaultLayout from "layouts/DefaultLayout";
|
||||||
// components
|
// components
|
||||||
@ -204,4 +206,4 @@ const OnBoard: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OnBoard;
|
export default withAuth(OnBoard);
|
||||||
|
@ -19,6 +19,8 @@ import { classNames } from "constants/common";
|
|||||||
// services
|
// services
|
||||||
import userService from "lib/services/user.service";
|
import userService from "lib/services/user.service";
|
||||||
import issuesServices from "lib/services/issues.services";
|
import issuesServices from "lib/services/issues.services";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// components
|
// components
|
||||||
import ChangeStateDropdown from "components/project/issues/my-issues/ChangeStateDropdown";
|
import ChangeStateDropdown from "components/project/issues/my-issues/ChangeStateDropdown";
|
||||||
// icons
|
// icons
|
||||||
@ -278,4 +280,4 @@ const MyIssues: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MyIssues;
|
export default withAuth(MyIssues);
|
||||||
|
@ -8,6 +8,8 @@ import { useForm } from "react-hook-form";
|
|||||||
import Dropzone, { useDropzone } from "react-dropzone";
|
import Dropzone, { useDropzone } from "react-dropzone";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "lib/hooks/useUser";
|
import useUser from "lib/hooks/useUser";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import AdminLayout from "layouts/AdminLayout";
|
import AdminLayout from "layouts/AdminLayout";
|
||||||
// services
|
// services
|
||||||
@ -307,4 +309,4 @@ const Profile: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Profile;
|
export default withAuth(Profile);
|
||||||
|
@ -11,6 +11,8 @@ import sprintService from "lib/services/cycles.services";
|
|||||||
import useUser from "lib/hooks/useUser";
|
import useUser from "lib/hooks/useUser";
|
||||||
// fetching keys
|
// fetching keys
|
||||||
import { CYCLE_ISSUES, CYCLE_LIST } from "constants/fetch-keys";
|
import { CYCLE_ISSUES, CYCLE_LIST } from "constants/fetch-keys";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import AdminLayout from "layouts/AdminLayout";
|
import AdminLayout from "layouts/AdminLayout";
|
||||||
// components
|
// components
|
||||||
@ -258,4 +260,4 @@ const ProjectSprints: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProjectSprints;
|
export default withAuth(ProjectSprints);
|
||||||
|
@ -22,6 +22,8 @@ import {
|
|||||||
} from "constants/fetch-keys";
|
} from "constants/fetch-keys";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "lib/hooks/useUser";
|
import useUser from "lib/hooks/useUser";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import AdminLayout from "layouts/AdminLayout";
|
import AdminLayout from "layouts/AdminLayout";
|
||||||
// components
|
// components
|
||||||
@ -606,4 +608,4 @@ const IssueDetail: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default IssueDetail;
|
export default withAuth(IssueDetail);
|
||||||
|
@ -14,6 +14,8 @@ import useUser from "lib/hooks/useUser";
|
|||||||
import useToast from "lib/hooks/useToast";
|
import useToast from "lib/hooks/useToast";
|
||||||
// fetching keys
|
// fetching keys
|
||||||
import { PROJECT_MEMBERS, PROJECT_INVITATIONS } from "constants/fetch-keys";
|
import { PROJECT_MEMBERS, PROJECT_INVITATIONS } from "constants/fetch-keys";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import AdminLayout from "layouts/AdminLayout";
|
import AdminLayout from "layouts/AdminLayout";
|
||||||
// components
|
// components
|
||||||
@ -313,4 +315,4 @@ const ProjectMembers: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProjectMembers;
|
export default withAuth(ProjectMembers);
|
||||||
|
@ -10,6 +10,8 @@ import useSWR from "swr";
|
|||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
// headless ui
|
// headless ui
|
||||||
import { Listbox, Tab, Transition } from "@headlessui/react";
|
import { Listbox, Tab, Transition } from "@headlessui/react";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import AdminLayout from "layouts/AdminLayout";
|
import AdminLayout from "layouts/AdminLayout";
|
||||||
// service
|
// service
|
||||||
@ -20,6 +22,8 @@ import useUser from "lib/hooks/useUser";
|
|||||||
import useToast from "lib/hooks/useToast";
|
import useToast from "lib/hooks/useToast";
|
||||||
// fetch keys
|
// fetch keys
|
||||||
import { PROJECT_DETAILS, PROJECTS_LIST, WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
import { PROJECT_DETAILS, PROJECTS_LIST, WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
||||||
|
// constants
|
||||||
|
import { NETWORK_CHOICES } from "constants/";
|
||||||
// commons
|
// commons
|
||||||
import { addSpaceIfCamelCase, debounce } from "constants/common";
|
import { addSpaceIfCamelCase, debounce } from "constants/common";
|
||||||
// components
|
// components
|
||||||
@ -44,8 +48,6 @@ const defaultValues: Partial<IProject> = {
|
|||||||
description: "",
|
description: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const NETWORK_CHOICES = { "0": "Secret", "2": "Public" };
|
|
||||||
|
|
||||||
const ProjectSettings: NextPage = () => {
|
const ProjectSettings: NextPage = () => {
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
@ -71,7 +73,7 @@ const ProjectSettings: NextPage = () => {
|
|||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const { data: projectDetails } = useSWR<IProject>(
|
const { data: projectDetails } = useSWR<IProject>(
|
||||||
activeWorkspace && projectId ? PROJECT_DETAILS : null,
|
activeWorkspace && projectId ? PROJECT_DETAILS(projectId as string) : null,
|
||||||
activeWorkspace
|
activeWorkspace
|
||||||
? () => projectServices.getProject(activeWorkspace.slug, projectId as string)
|
? () => projectServices.getProject(activeWorkspace.slug, projectId as string)
|
||||||
: null
|
: null
|
||||||
@ -99,7 +101,7 @@ const ProjectSettings: NextPage = () => {
|
|||||||
}, [projectDetails, reset]);
|
}, [projectDetails, reset]);
|
||||||
|
|
||||||
const onSubmit = async (formData: IProject) => {
|
const onSubmit = async (formData: IProject) => {
|
||||||
if (!activeWorkspace) return;
|
if (!activeWorkspace || !projectId) return;
|
||||||
const payload: Partial<IProject> = {
|
const payload: Partial<IProject> = {
|
||||||
name: formData.name,
|
name: formData.name,
|
||||||
network: formData.network,
|
network: formData.network,
|
||||||
@ -111,7 +113,11 @@ const ProjectSettings: NextPage = () => {
|
|||||||
await projectServices
|
await projectServices
|
||||||
.updateProject(activeWorkspace.slug, projectId as string, payload)
|
.updateProject(activeWorkspace.slug, projectId as string, payload)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutate<IProject>(PROJECT_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
|
mutate<IProject>(
|
||||||
|
PROJECT_DETAILS(projectId as string),
|
||||||
|
(prevData) => ({ ...prevData, ...res }),
|
||||||
|
false
|
||||||
|
);
|
||||||
mutate<IProject[]>(
|
mutate<IProject[]>(
|
||||||
PROJECTS_LIST(activeWorkspace.slug),
|
PROJECTS_LIST(activeWorkspace.slug),
|
||||||
(prevData) => {
|
(prevData) => {
|
||||||
@ -253,9 +259,6 @@ const ProjectSettings: NextPage = () => {
|
|||||||
register={register}
|
register={register}
|
||||||
label="Description"
|
label="Description"
|
||||||
placeholder="Enter project description"
|
placeholder="Enter project description"
|
||||||
validations={{
|
|
||||||
required: "Description is required",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
@ -547,4 +550,4 @@ const ProjectSettings: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProjectSettings;
|
export default withAuth(ProjectSettings);
|
||||||
|
@ -3,6 +3,8 @@ import React, { useEffect, useState } from "react";
|
|||||||
import type { NextPage } from "next";
|
import type { NextPage } from "next";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "lib/hooks/useUser";
|
import useUser from "lib/hooks/useUser";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import AdminLayout from "layouts/AdminLayout";
|
import AdminLayout from "layouts/AdminLayout";
|
||||||
// components
|
// components
|
||||||
@ -129,4 +131,4 @@ const Projects: NextPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Projects;
|
export default withAuth(Projects);
|
||||||
|
@ -8,9 +8,10 @@ import Dropzone from "react-dropzone";
|
|||||||
// services
|
// services
|
||||||
import workspaceService from "lib/services/workspace.service";
|
import workspaceService from "lib/services/workspace.service";
|
||||||
import fileServices from "lib/services/file.services";
|
import fileServices from "lib/services/file.services";
|
||||||
|
// hoc
|
||||||
|
import withAuth from "lib/hoc/withAuthWrapper";
|
||||||
// layouts
|
// layouts
|
||||||
import AdminLayout from "layouts/AdminLayout";
|
import AdminLayout from "layouts/AdminLayout";
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "lib/hooks/useUser";
|
import useUser from "lib/hooks/useUser";
|
||||||
import useToast from "lib/hooks/useToast";
|
import useToast from "lib/hooks/useToast";
|
||||||
@ -232,4 +233,4 @@ const WorkspaceSettings = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WorkspaceSettings;
|
export default withAuth(WorkspaceSettings);
|
||||||
|
8
apps/app/types/projects.d.ts
vendored
8
apps/app/types/projects.d.ts
vendored
@ -15,3 +15,11 @@ export interface IProject {
|
|||||||
created_by: string;
|
created_by: string;
|
||||||
updated_by: string;
|
updated_by: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProjectViewTheme = {
|
||||||
|
collapsed: boolean;
|
||||||
|
issueView: "list" | "kanban" | null;
|
||||||
|
groupByProperty: NestedKeyOf<IIssue> | null;
|
||||||
|
filterIssue: "activeIssue" | "backlogIssue" | null;
|
||||||
|
orderBy: NestedKeyOf<IIssue> | null;
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user