Files
model-platform/frontend/app/features/platform/state/uiStore.ts
T

277 lines
7.8 KiB
TypeScript

import { create } from "zustand";
import type {
ScriptItem,
ScriptType,
StableVersion,
Visibility,
} from "../../../services/api";
export type NewScriptForm = {
name: string;
scriptType: ScriptType;
visibility: Visibility;
parentPath: string;
};
export type ContextMenuState = {
x: number;
y: number;
kind: "root" | "directory" | "file";
path: string;
script?: ScriptItem;
};
export type FolderDialogState = {
open: boolean;
parentPath: string;
name: string;
busy: boolean;
};
export type DataResourceDialogState = {
open: boolean;
file: File | null;
parentPath: string;
resourceName: string;
visibility: Visibility;
description: string;
uploading: boolean;
targetPath: string;
};
export type PublishDialogState = {
target: ScriptItem | null;
releaseNote: string;
visibility: Visibility;
publishing: boolean;
publishedVersion: StableVersion | null;
};
export type UploadState = {
parentPath: string;
uploading: boolean;
};
export const initialCreateForm: NewScriptForm = {
name: "",
scriptType: "notebook",
visibility: "workspace",
parentPath: "",
};
type UiState = {
createDialog: {
open: boolean;
creating: boolean;
form: NewScriptForm;
};
folderDialog: FolderDialogState;
contextMenu: ContextMenuState | null;
workspaceMenuOpen: boolean;
upload: UploadState;
publish: PublishDialogState;
dataResourceDialog: DataResourceDialogState;
// create dialog
openCreateDialog: (parentPath?: string, scriptType?: ScriptType) => void;
closeCreateDialog: () => void;
setCreateForm: (form: NewScriptForm) => void;
setCreating: (creating: boolean) => void;
// folder dialog
openFolderDialog: (parentPath?: string) => void;
closeFolderDialog: () => void;
setFolderName: (name: string) => void;
setFolderBusy: (busy: boolean) => void;
// context menu
showContextMenu: (
event: { clientX: number; clientY: number; preventDefault: () => void; stopPropagation: () => void },
target: Omit<ContextMenuState, "x" | "y">,
) => void;
closeContextMenu: () => void;
// workspace menu (topbar)
setWorkspaceMenuOpen: (open: boolean) => void;
// upload
chooseUpload: (parentPath?: string) => void;
setUploading: (uploading: boolean) => void;
setUploadParentPath: (parentPath: string) => void;
// publish dialog
openPublishDialog: (script: ScriptItem) => void;
closePublishDialog: () => void;
setReleaseNote: (note: string) => void;
setPublishVisibility: (visibility: Visibility) => void;
setPublishing: (publishing: boolean) => void;
setPublishedVersion: (version: StableVersion) => void;
clearPublishedVersion: () => void;
// data resource dialog
openDataResourceDialog: (file: File, parentPath?: string) => void;
closeDataResourceDialog: () => void;
setDataResourceName: (name: string) => void;
setDataResourceVisibility: (visibility: Visibility) => void;
setDataResourceDescription: (description: string) => void;
setDataResourceTargetPath: (path: string) => void;
setDataResourceUploading: (uploading: boolean) => void;
};
export const useUiStore = create<UiState>((set) => ({
createDialog: {
open: false,
creating: false,
form: initialCreateForm,
},
folderDialog: {
open: false,
parentPath: "",
name: "",
busy: false,
},
contextMenu: null,
workspaceMenuOpen: false,
upload: {
parentPath: "",
uploading: false,
},
publish: {
target: null,
releaseNote: "",
visibility: "workspace",
publishing: false,
publishedVersion: null,
},
dataResourceDialog: {
open: false,
file: null,
parentPath: "",
resourceName: "",
visibility: "workspace",
description: "",
uploading: false,
targetPath: "",
},
openCreateDialog: (parentPath = "", scriptType = "notebook") =>
set((state) => ({
contextMenu: null,
createDialog: {
open: true,
creating: false,
form: { ...initialCreateForm, parentPath, scriptType },
},
})),
closeCreateDialog: () =>
set((state) => ({
createDialog: { ...state.createDialog, open: false },
})),
setCreateForm: (form) =>
set((state) => ({ createDialog: { ...state.createDialog, form } })),
setCreating: (creating) =>
set((state) => ({ createDialog: { ...state.createDialog, creating } })),
openFolderDialog: (parentPath = "") =>
set((state) => ({
contextMenu: null,
folderDialog: {
open: true,
parentPath,
name: "",
busy: false,
},
})),
closeFolderDialog: () =>
set((state) => ({
folderDialog: { ...state.folderDialog, open: false },
})),
setFolderName: (name) =>
set((state) => ({ folderDialog: { ...state.folderDialog, name } })),
setFolderBusy: (busy) =>
set((state) => ({ folderDialog: { ...state.folderDialog, busy } })),
showContextMenu: (event, target) => {
event.preventDefault();
event.stopPropagation();
const width = 188;
const height = target.kind === "file" ? 92 : 190;
set({
contextMenu: {
...target,
x: Math.min(event.clientX, window.innerWidth - width - 8),
y: Math.min(event.clientY, window.innerHeight - height - 8),
},
});
},
closeContextMenu: () => set({ contextMenu: null }),
setWorkspaceMenuOpen: (open) => set({ workspaceMenuOpen: open }),
chooseUpload: (parentPath = "") =>
set((state) => ({
contextMenu: null,
upload: { ...state.upload, parentPath },
})),
setUploading: (uploading) =>
set((state) => ({ upload: { ...state.upload, uploading } })),
setUploadParentPath: (parentPath) =>
set((state) => ({ upload: { ...state.upload, parentPath } })),
openPublishDialog: (script) =>
set((state) => ({
publish: {
...state.publish,
target: script,
releaseNote: "",
visibility: script.visibility === "private" ? "private" : "workspace",
},
})),
closePublishDialog: () =>
set((state) => ({ publish: { ...state.publish, target: null } })),
setReleaseNote: (note) =>
set((state) => ({ publish: { ...state.publish, releaseNote: note } })),
setPublishVisibility: (visibility) =>
set((state) => ({ publish: { ...state.publish, visibility } })),
setPublishing: (publishing) =>
set((state) => ({ publish: { ...state.publish, publishing } })),
setPublishedVersion: (version) =>
set((state) => ({
publish: {
...state.publish,
target: null,
publishedVersion: version,
},
})),
clearPublishedVersion: () =>
set((state) => ({ publish: { ...state.publish, publishedVersion: null } })),
openDataResourceDialog: (file, parentPath = "") =>
set((state) => ({
contextMenu: null,
dataResourceDialog: {
open: true,
file,
parentPath,
resourceName: file.name.replace(/\.[^/.]+$/, ""),
visibility: "workspace",
description: "",
uploading: false,
// 右键"在此处上传"时,把父目录预填进子目录输入框
targetPath: parentPath,
},
})),
closeDataResourceDialog: () =>
set((state) => ({
dataResourceDialog: { ...state.dataResourceDialog, open: false, uploading: false },
})),
setDataResourceName: (name) =>
set((state) => ({ dataResourceDialog: { ...state.dataResourceDialog, resourceName: name } })),
setDataResourceVisibility: (visibility) =>
set((state) => ({ dataResourceDialog: { ...state.dataResourceDialog, visibility } })),
setDataResourceDescription: (description) =>
set((state) => ({ dataResourceDialog: { ...state.dataResourceDialog, description } })),
setDataResourceTargetPath: (path) =>
set((state) => ({ dataResourceDialog: { ...state.dataResourceDialog, targetPath: path } })),
setDataResourceUploading: (uploading) =>
set((state) => ({ dataResourceDialog: { ...state.dataResourceDialog, uploading } })),
}));