mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
refactor: publish project store and components
This commit is contained in:
parent
3fe9e3515b
commit
761c65830c
@ -25,6 +25,7 @@ type Props = {
|
||||
};
|
||||
|
||||
type FormData = {
|
||||
anchor: string;
|
||||
id: string | null;
|
||||
comments: boolean;
|
||||
reactions: boolean;
|
||||
@ -34,6 +35,7 @@ type FormData = {
|
||||
};
|
||||
|
||||
const defaultValues: FormData = {
|
||||
anchor: "",
|
||||
id: null,
|
||||
comments: false,
|
||||
reactions: false,
|
||||
@ -48,34 +50,27 @@ const viewOptions: {
|
||||
}[] = [
|
||||
{ key: "list", label: "List" },
|
||||
{ key: "kanban", label: "Kanban" },
|
||||
// { key: "calendar", label: "Calendar" },
|
||||
// { key: "gantt", label: "Gantt" },
|
||||
// { key: "spreadsheet", label: "Spreadsheet" },
|
||||
];
|
||||
|
||||
export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
const { isOpen, project, onClose } = props;
|
||||
// hooks
|
||||
// const { instance } = useInstance();
|
||||
// states
|
||||
const [isUnPublishing, setIsUnPublishing] = useState(false);
|
||||
const [isUpdateRequired, setIsUpdateRequired] = useState(false);
|
||||
|
||||
// const plane_deploy_url = instance?.config?.space_base_url || "";
|
||||
const SPACE_URL = (SPACE_BASE_URL === "" ? window.location.origin : SPACE_BASE_URL) + SPACE_BASE_PATH;
|
||||
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// store hooks
|
||||
const {
|
||||
projectPublishSettings,
|
||||
getProjectSettingsAsync,
|
||||
fetchPublishSettings,
|
||||
getPublishSettingsByProjectID,
|
||||
publishProject,
|
||||
updateProjectSettingsAsync,
|
||||
updatePublishSettings,
|
||||
unPublishProject,
|
||||
fetchSettingsLoader,
|
||||
} = useProjectPublish();
|
||||
// derived values
|
||||
const projectPublishSettings = getPublishSettingsByProjectID(project.id);
|
||||
// form info
|
||||
const {
|
||||
control,
|
||||
@ -97,44 +92,44 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
|
||||
// prefill form with the saved settings if the project is already published
|
||||
useEffect(() => {
|
||||
if (projectPublishSettings && projectPublishSettings !== "not-initialized") {
|
||||
let userBoards: TProjectPublishViews[] = [];
|
||||
if (!projectPublishSettings) return;
|
||||
|
||||
if (projectPublishSettings?.views) {
|
||||
const savedViews = projectPublishSettings?.views;
|
||||
let userBoards: TProjectPublishViews[] = [];
|
||||
|
||||
if (!savedViews) return;
|
||||
if (projectPublishSettings?.view_props) {
|
||||
const savedViews = projectPublishSettings?.view_props;
|
||||
|
||||
if (savedViews.list) userBoards.push("list");
|
||||
if (savedViews.kanban) userBoards.push("kanban");
|
||||
if (savedViews.calendar) userBoards.push("calendar");
|
||||
if (savedViews.gantt) userBoards.push("gantt");
|
||||
if (savedViews.spreadsheet) userBoards.push("spreadsheet");
|
||||
if (!savedViews) return;
|
||||
|
||||
userBoards = userBoards && userBoards.length > 0 ? userBoards : ["list"];
|
||||
}
|
||||
if (savedViews.list) userBoards.push("list");
|
||||
if (savedViews.kanban) userBoards.push("kanban");
|
||||
if (savedViews.calendar) userBoards.push("calendar");
|
||||
if (savedViews.gantt) userBoards.push("gantt");
|
||||
if (savedViews.spreadsheet) userBoards.push("spreadsheet");
|
||||
|
||||
const updatedData = {
|
||||
id: projectPublishSettings?.id || null,
|
||||
comments: projectPublishSettings?.comments || false,
|
||||
reactions: projectPublishSettings?.reactions || false,
|
||||
votes: projectPublishSettings?.votes || false,
|
||||
inbox: projectPublishSettings?.inbox || null,
|
||||
views: userBoards,
|
||||
};
|
||||
|
||||
reset({ ...updatedData });
|
||||
userBoards = userBoards && userBoards.length > 0 ? userBoards : ["list"];
|
||||
}
|
||||
|
||||
const updatedData = {
|
||||
id: projectPublishSettings?.id || null,
|
||||
comments: projectPublishSettings?.comments || false,
|
||||
reactions: projectPublishSettings?.reactions || false,
|
||||
votes: projectPublishSettings?.votes || false,
|
||||
inbox: projectPublishSettings?.inbox || null,
|
||||
views: userBoards,
|
||||
};
|
||||
|
||||
reset({ ...updatedData });
|
||||
}, [reset, projectPublishSettings, isOpen]);
|
||||
|
||||
// fetch publish settings
|
||||
useEffect(() => {
|
||||
if (!workspaceSlug || !isOpen) return;
|
||||
|
||||
if (projectPublishSettings === "not-initialized") {
|
||||
getProjectSettingsAsync(workspaceSlug.toString(), project.id);
|
||||
if (!projectPublishSettings) {
|
||||
fetchPublishSettings(workspaceSlug.toString(), project.id);
|
||||
}
|
||||
}, [isOpen, workspaceSlug, project, projectPublishSettings, getProjectSettingsAsync]);
|
||||
}, [fetchPublishSettings, isOpen, project, projectPublishSettings, workspaceSlug]);
|
||||
|
||||
const handlePublishProject = async (payload: IProjectPublishSettings) => {
|
||||
if (!workspaceSlug) return;
|
||||
@ -145,7 +140,7 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
const handleUpdatePublishSettings = async (payload: IProjectPublishSettings) => {
|
||||
if (!workspaceSlug) return;
|
||||
|
||||
await updateProjectSettingsAsync(workspaceSlug.toString(), project.id, payload.id ?? "", payload)
|
||||
await updatePublishSettings(workspaceSlug.toString(), project.id, payload.id ?? "", payload)
|
||||
.then((res) => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
@ -172,7 +167,7 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Something went wrong while un-publishing the project.",
|
||||
message: "Something went wrong while unpublishing the project.",
|
||||
})
|
||||
)
|
||||
.finally(() => setIsUnPublishing(false));
|
||||
@ -214,7 +209,7 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
reactions: formData.reactions,
|
||||
votes: formData.votes,
|
||||
inbox: formData.inbox,
|
||||
views: {
|
||||
view_props: {
|
||||
list: formData.views.includes("list"),
|
||||
kanban: formData.views.includes("kanban"),
|
||||
calendar: formData.views.includes("calendar"),
|
||||
@ -223,13 +218,18 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
},
|
||||
};
|
||||
|
||||
if (project.is_deployed) await handleUpdatePublishSettings({ id: watch("id") ?? "", ...payload });
|
||||
if (project.is_deployed)
|
||||
await handleUpdatePublishSettings({
|
||||
anchor: watch("anchor") ?? "",
|
||||
id: watch("id") ?? "",
|
||||
...payload,
|
||||
});
|
||||
else await handlePublishProject(payload);
|
||||
};
|
||||
|
||||
// check if an update is required or not
|
||||
const checkIfUpdateIsRequired = () => {
|
||||
if (!projectPublishSettings || projectPublishSettings === "not-initialized") return;
|
||||
if (!projectPublishSettings || !projectPublishSettings) return;
|
||||
|
||||
const currentSettings = projectPublishSettings;
|
||||
const newSettings = getValues();
|
||||
@ -245,7 +245,7 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
|
||||
let viewCheckFlag = 0;
|
||||
viewOptions.forEach((option) => {
|
||||
if (currentSettings.views[option.key] !== newSettings.views.includes(option.key)) viewCheckFlag++;
|
||||
if (currentSettings.view_props?.[option.key] !== newSettings.views.includes(option.key)) viewCheckFlag++;
|
||||
});
|
||||
|
||||
if (viewCheckFlag !== 0) {
|
||||
@ -256,6 +256,8 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
setIsUpdateRequired(false);
|
||||
};
|
||||
|
||||
const SPACE_URL = (SPACE_BASE_URL === "" ? window.location.origin : SPACE_BASE_URL) + SPACE_BASE_PATH;
|
||||
|
||||
return (
|
||||
<Transition.Root show={isOpen} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
@ -293,7 +295,7 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
onClick={() => handleUnPublishProject(watch("id") ?? "")}
|
||||
loading={isUnPublishing}
|
||||
>
|
||||
{isUnPublishing ? "Un-publishing..." : "Un-publish"}
|
||||
{isUnPublishing ? "Unpublishing" : "Unpublish"}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@ -308,12 +310,12 @@ export const PublishProjectModal: React.FC<Props> = observer((props) => {
|
||||
</Loader>
|
||||
) : (
|
||||
<div className="px-6">
|
||||
{project.is_deployed && (
|
||||
{project.is_deployed && projectPublishSettings && (
|
||||
<>
|
||||
<div className="relative flex items-center gap-2 rounded-md border border-custom-border-100 bg-custom-background-80 px-3 py-2">
|
||||
<div className="flex-grow truncate text-sm">{`${SPACE_URL}/issues/`}</div>
|
||||
<div className="flex-grow truncate text-sm">{`${SPACE_URL}/issues/${projectPublishSettings.anchor}`}</div>
|
||||
<div className="relative flex flex-shrink-0 items-center gap-1">
|
||||
<CopyLinkToClipboard copy_link={`${SPACE_URL}/issues`} />
|
||||
<CopyLinkToClipboard copy_link={`${SPACE_URL}/issues/${projectPublishSettings.anchor}`} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3 flex items-center gap-1 text-custom-primary-100">
|
||||
|
@ -34,7 +34,7 @@ export class ProjectPublishService extends APIService {
|
||||
projectID: string,
|
||||
project_publish_id: string,
|
||||
data: IProjectPublishSettings
|
||||
): Promise<any> {
|
||||
): Promise<IProjectPublishSettings> {
|
||||
return this.patch(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectID}/project-deploy-boards/${project_publish_id}/`,
|
||||
data
|
||||
|
@ -1,4 +1,5 @@
|
||||
import set from "lodash/set";
|
||||
import unset from "lodash/unset";
|
||||
import { observable, action, makeObservable, runInAction } from "mobx";
|
||||
// types
|
||||
import { ProjectPublishService } from "@/services/project";
|
||||
@ -12,12 +13,13 @@ export type TProjectPublishViewsSettings = {
|
||||
};
|
||||
|
||||
export interface IProjectPublishSettings {
|
||||
anchor?: string;
|
||||
id?: string;
|
||||
project?: string;
|
||||
comments: boolean;
|
||||
reactions: boolean;
|
||||
votes: boolean;
|
||||
views: TProjectPublishViewsSettings;
|
||||
view_props: TProjectPublishViewsSettings;
|
||||
inbox: string | null;
|
||||
}
|
||||
|
||||
@ -26,31 +28,31 @@ export interface IProjectPublishStore {
|
||||
generalLoader: boolean;
|
||||
fetchSettingsLoader: boolean;
|
||||
// observables
|
||||
projectPublishSettings: IProjectPublishSettings | "not-initialized";
|
||||
// project settings actions
|
||||
getProjectSettingsAsync: (workspaceSlug: string, projectId: string) => Promise<IProjectPublishSettings>;
|
||||
updateProjectSettingsAsync: (
|
||||
publishSettingsMap: Record<string, IProjectPublishSettings>; // projectID => IProjectPublishSettings
|
||||
// helpers
|
||||
getPublishSettingsByProjectID: (projectID: string) => IProjectPublishSettings | undefined;
|
||||
// actions
|
||||
fetchPublishSettings: (workspaceSlug: string, projectID: string) => Promise<IProjectPublishSettings>;
|
||||
updatePublishSettings: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
projectID: string,
|
||||
projectPublishId: string,
|
||||
data: IProjectPublishSettings
|
||||
) => Promise<void>;
|
||||
// project publish actions
|
||||
) => Promise<IProjectPublishSettings>;
|
||||
publishProject: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
projectID: string,
|
||||
data: IProjectPublishSettings
|
||||
) => Promise<IProjectPublishSettings>;
|
||||
unPublishProject: (workspaceSlug: string, projectId: string, projectPublishId: string) => Promise<void>;
|
||||
unPublishProject: (workspaceSlug: string, projectID: string, projectPublishId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export class ProjectPublishStore implements IProjectPublishStore {
|
||||
// states
|
||||
generalLoader: boolean = false;
|
||||
fetchSettingsLoader: boolean = false;
|
||||
// actions
|
||||
project_id: string | null = null;
|
||||
projectPublishSettings: IProjectPublishSettings | "not-initialized" = "not-initialized";
|
||||
// observables
|
||||
publishSettingsMap: Record<string, IProjectPublishSettings> = {};
|
||||
// root store
|
||||
projectRootStore: ProjectRootStore;
|
||||
// services
|
||||
@ -62,12 +64,10 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
generalLoader: observable.ref,
|
||||
fetchSettingsLoader: observable.ref,
|
||||
// observables
|
||||
project_id: observable.ref,
|
||||
projectPublishSettings: observable.ref,
|
||||
// project settings actions
|
||||
getProjectSettingsAsync: action,
|
||||
updateProjectSettingsAsync: action,
|
||||
// project publish actions
|
||||
publishSettingsMap: observable,
|
||||
// actions
|
||||
fetchPublishSettings: action,
|
||||
updatePublishSettings: action,
|
||||
publishProject: action,
|
||||
unPublishProject: action,
|
||||
});
|
||||
@ -77,29 +77,31 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
this.projectPublishService = new ProjectPublishService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description returns the publish settings of a particular project
|
||||
* @param {string} projectID
|
||||
* @returns {IProjectPublishSettings | undefined}
|
||||
*/
|
||||
getPublishSettingsByProjectID = (projectID: string): IProjectPublishSettings | undefined =>
|
||||
this.publishSettingsMap?.[projectID] ?? undefined;
|
||||
|
||||
/**
|
||||
* Fetches project publish settings
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param projectID
|
||||
* @returns
|
||||
*/
|
||||
getProjectSettingsAsync = async (workspaceSlug: string, projectId: string) => {
|
||||
fetchPublishSettings = async (workspaceSlug: string, projectID: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.fetchSettingsLoader = true;
|
||||
});
|
||||
const response = await this.projectPublishService.getProjectSettingsAsync(workspaceSlug, projectId);
|
||||
if (response) {
|
||||
runInAction(() => {
|
||||
this.projectPublishSettings = response;
|
||||
this.fetchSettingsLoader = false;
|
||||
});
|
||||
} else {
|
||||
runInAction(() => {
|
||||
this.projectPublishSettings = "not-initialized";
|
||||
this.fetchSettingsLoader = false;
|
||||
});
|
||||
}
|
||||
const response = await this.projectPublishService.getProjectSettingsAsync(workspaceSlug, projectID);
|
||||
|
||||
runInAction(() => {
|
||||
set(this.publishSettingsMap, [projectID], response);
|
||||
this.fetchSettingsLoader = false;
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
@ -112,23 +114,21 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
/**
|
||||
* Publishes project and updates project publish status in the store
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param projectID
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
publishProject = async (workspaceSlug: string, projectId: string, data: IProjectPublishSettings) => {
|
||||
publishProject = async (workspaceSlug: string, projectID: string, data: IProjectPublishSettings) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.generalLoader = true;
|
||||
});
|
||||
const response = await this.projectPublishService.createProjectSettingsAsync(workspaceSlug, projectId, data);
|
||||
if (response) {
|
||||
runInAction(() => {
|
||||
this.projectPublishSettings = response;
|
||||
set(this.projectRootStore.project.projectMap, [projectId, "is_deployed"], true);
|
||||
this.generalLoader = false;
|
||||
});
|
||||
}
|
||||
const response = await this.projectPublishService.createProjectSettingsAsync(workspaceSlug, projectID, data);
|
||||
runInAction(() => {
|
||||
set(this.publishSettingsMap, [projectID], response);
|
||||
set(this.projectRootStore.project.projectMap, [projectID, "is_deployed"], true);
|
||||
this.generalLoader = false;
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
@ -141,14 +141,14 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
/**
|
||||
* Updates project publish settings
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param projectID
|
||||
* @param projectPublishId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
updateProjectSettingsAsync = async (
|
||||
updatePublishSettings = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
projectID: string,
|
||||
projectPublishId: string,
|
||||
data: IProjectPublishSettings
|
||||
) => {
|
||||
@ -158,26 +158,15 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
});
|
||||
const response = await this.projectPublishService.updateProjectSettingsAsync(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
projectID,
|
||||
projectPublishId,
|
||||
data
|
||||
);
|
||||
if (response) {
|
||||
const _projectPublishSettings: IProjectPublishSettings = {
|
||||
id: response?.id || null,
|
||||
comments: response?.comments || false,
|
||||
reactions: response?.reactions || false,
|
||||
votes: response?.votes || false,
|
||||
views: { ...response?.views },
|
||||
inbox: response?.inbox || null,
|
||||
project: response?.project || null,
|
||||
};
|
||||
runInAction(() => {
|
||||
this.projectPublishSettings = _projectPublishSettings;
|
||||
this.generalLoader = false;
|
||||
});
|
||||
return response;
|
||||
}
|
||||
runInAction(() => {
|
||||
set(this.publishSettingsMap, [projectID], response);
|
||||
this.generalLoader = false;
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.generalLoader = false;
|
||||
@ -189,23 +178,23 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
/**
|
||||
* Unpublishes project and updates project publish status in the store
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param projectID
|
||||
* @param projectPublishId
|
||||
* @returns
|
||||
*/
|
||||
unPublishProject = async (workspaceSlug: string, projectId: string, projectPublishId: string) => {
|
||||
unPublishProject = async (workspaceSlug: string, projectID: string, projectPublishId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.generalLoader = true;
|
||||
});
|
||||
const response = await this.projectPublishService.deleteProjectSettingsAsync(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
projectID,
|
||||
projectPublishId
|
||||
);
|
||||
runInAction(() => {
|
||||
this.projectPublishSettings = "not-initialized";
|
||||
set(this.projectRootStore.project.projectMap, [projectId, "is_deployed"], false);
|
||||
unset(this.publishSettingsMap, [projectID]);
|
||||
set(this.projectRootStore.project.projectMap, [projectID, "is_deployed"], false);
|
||||
this.generalLoader = false;
|
||||
});
|
||||
return response;
|
||||
|
Loading…
Reference in New Issue
Block a user