diff --git a/moderate_ui/src/api/assets.ts b/moderate_ui/src/api/assets.ts new file mode 100644 index 0000000..20c5a1d --- /dev/null +++ b/moderate_ui/src/api/assets.ts @@ -0,0 +1,39 @@ +import axios from "axios"; +import { buildApiUrl } from "./utils"; + +export async function fetchPygwalkerHtml({ objectId }: { objectId: string }) { + return axios.get(buildApiUrl("visualization", "object", objectId)); +} + +export async function uploadObject({ + assetId, + file, + onProgress, +}: { + assetId: string | number; + file: File; + onProgress?: (progress: number) => void; +}): Promise<{ [k: string]: any }> { + const data = new FormData(); + data.append("obj", file); + + const config = { + onUploadProgress: function (progressEvent: { [k: string]: any }) { + const percentCompleted = Math.round( + (progressEvent.loaded * 100) / progressEvent.total + ); + + console.debug("Upload progress:", percentCompleted, "%"); + + if (onProgress) { + onProgress(percentCompleted); + } + }, + }; + + return await axios.post( + buildApiUrl("asset", assetId.toString(), "object"), + data, + config + ); +} diff --git a/moderate_ui/src/api/types.ts b/moderate_ui/src/api/types.ts new file mode 100644 index 0000000..8d63aec --- /dev/null +++ b/moderate_ui/src/api/types.ts @@ -0,0 +1,5 @@ +export enum AssetAccessLevel { + PRIVATE = "private", + PUBLIC = "public", + VISIBLE = "visible", +} diff --git a/moderate_ui/src/api/visualization.ts b/moderate_ui/src/api/visualization.ts deleted file mode 100644 index 05c83f8..0000000 --- a/moderate_ui/src/api/visualization.ts +++ /dev/null @@ -1,6 +0,0 @@ -import axios from "axios"; -import { buildApiUrl } from "./utils"; - -export async function fetchPygwalkerHtml({ objectId }: { objectId: string }) { - return axios.get(buildApiUrl("visualization", "object", objectId)); -} diff --git a/moderate_ui/src/pages/asset-objects/ExploratoryDashboard.tsx b/moderate_ui/src/pages/asset-objects/ExploratoryDashboard.tsx index 900abee..bed4b10 100644 --- a/moderate_ui/src/pages/asset-objects/ExploratoryDashboard.tsx +++ b/moderate_ui/src/pages/asset-objects/ExploratoryDashboard.tsx @@ -14,7 +14,7 @@ import { } from "@refinedev/core"; import { IconFlask } from "@tabler/icons-react"; import { useEffect, useMemo, useState } from "react"; -import { fetchPygwalkerHtml } from "../../api/visualization"; +import { fetchPygwalkerHtml } from "../../api/assets"; export const AssetObjectExploratoryDashboard: React.FC = () => { const { params } = useParsed(); diff --git a/moderate_ui/src/pages/assets/create.tsx b/moderate_ui/src/pages/assets/create.tsx index 5cc6c42..9098bcc 100644 --- a/moderate_ui/src/pages/assets/create.tsx +++ b/moderate_ui/src/pages/assets/create.tsx @@ -1,6 +1,133 @@ -import { IResourceComponentsProps } from "@refinedev/core"; -import { MantineCreateInferencer } from "@refinedev/inferencer/mantine"; +import { + FileInput, + Loader, + LoadingOverlay, + Select, + Stack, + Text, + TextInput, + Textarea, +} from "@mantine/core"; +import { isNotEmpty } from "@mantine/form"; +import { useGo, useTranslate } from "@refinedev/core"; +import { Create, useForm } from "@refinedev/mantine"; +import { IconUpload } from "@tabler/icons-react"; +import _ from "lodash"; +import { useState } from "react"; +import { uploadObject } from "../../api/assets"; +import { AssetAccessLevel } from "../../api/types"; -export const AssetCreate: React.FC = () => { - return ; +export const AssetCreate = () => { + const t = useTranslate(); + + const [uploadingFile, setUploadingFile] = useState< + { name: string; progress: number } | undefined + >(undefined); + + const go = useGo(); + + const { + getInputProps, + saveButtonProps, + refineCore: { formLoading }, + } = useForm({ + initialValues: { + name: "", + description: "", + access_level: AssetAccessLevel.PRIVATE, + files: [], + }, + validate: { + name: isNotEmpty(), + description: isNotEmpty(), + access_level: isNotEmpty(), + files: isNotEmpty(), + }, + transformValues: (values) => { + console.debug("transformValues", values); + return values; + }, + refineCoreProps: { + redirect: false, + onMutationSuccess: async (data, variables) => { + const assetId = data.data.id; + + if (!assetId) { + return; + } + + for (const file of variables.files as File[]) { + setUploadingFile({ name: file.name, progress: 0 }); + + await uploadObject({ + assetId, + file, + onProgress: (progress) => { + setUploadingFile({ name: file.name, progress }); + }, + }); + + setUploadingFile(undefined); + } + + go({ + to: { + resource: "asset", + action: "show", + id: assetId, + }, + }); + }, + }, + }); + + return ( + <> + + + + {t("asset.form.uploading", "Uploading")}{" "} + {uploadingFile?.name} + + + {uploadingFile?.progress}% + + + } + /> + + +