Skip to content

Commit

Permalink
feat: adding global import menu
Browse files Browse the repository at this point in the history
  • Loading branch information
vojtatom committed Nov 29, 2024
1 parent 3d29e09 commit 0b69c7a
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 61 deletions.
9 changes: 0 additions & 9 deletions app/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ body {
min-height: 100vh;
}

img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}

input,
button,
textarea,
Expand Down
4 changes: 2 additions & 2 deletions app/core/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export default function Header(props: HeaderProps) {
paddingY="size-100"
backgroundColor="gray-50"
>
<Flex direction="row" width="100%" gap="size-10" justifyContent="space-between" alignItems="center">
<Breadcrumbs marginX="size-100" flex="1">
<Flex direction="row" width="100%" gap="size-10" justifyContent="start" alignItems="center">
<Breadcrumbs marginX="size-100">
{nav.map((item) => (
<Item key={item.key} href={item.link}>
{item.children}
Expand Down
13 changes: 11 additions & 2 deletions app/features/editor-metadata/components/EditorMetadataValues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { MdiSortAscending } from "@core/icons/MdiSortAscending";
import { MdiTrash } from "@core/icons/MdiTrash";
import useSelectedSubmodelCount from "@editor/hooks/useSelectedSubmodelCount";
import { useEditorContext } from "@features/editor/hooks/useEditorContext";
import { useCallback, useState } from "react";
import { useCallback, useMemo, useState } from "react";
import useMetadataContext from "../hooks/useMetadataContext";
import useMetadataEdits from "../hooks/useMetadataEdits";
import useMetadataSelection from "../hooks/useMetadataSelection";
Expand Down Expand Up @@ -71,6 +71,11 @@ export default function EditorMetadataValues() {
}
}, []);

const disabledKeysOnNoSelection = useMemo(
() => (selectedCount === 0 ? ["assignSingleValue"] : undefined),
[selectedCount]
);

return (
<PositioningContainer>
<Flex direction="column" height="100%" gap="size-100" marginX="size-200">
Expand Down Expand Up @@ -145,7 +150,11 @@ export default function EditorMetadataValues() {
>
{typeof record.value} - {record.count} items, {record.selected} selected{" "}
</Text>
<ActionGroup isQuiet onAction={(key) => handleItemAction(key, record.value)}>
<ActionGroup
isQuiet
onAction={(key) => handleItemAction(key, record.value)}
disabledKeys={disabledKeysOnNoSelection}
>
<TooltipTrigger delay={0} placement="bottom">
<Item key="assignSingleValue" textValue="Assign Value">
<MdiArrowRightBold />
Expand Down
7 changes: 3 additions & 4 deletions app/features/editor-models/components/EditorModels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import useSelectedSubmodelCount from "@features/editor/hooks/useSelectedSubmodel
import { useSplitModel } from "@features/editor/hooks/useSplitModel";
import Delete from "@spectrum-icons/workflow/Delete";
import { Key, useCallback, useState } from "react";
import EditorAddModeButton from "./EditorAddModelButton";
import EditorProjectModelDialog from "./EditorProjectModelDialog";
import EditorRenameModelDialog from "./EditorRenameModelDialog";

Expand Down Expand Up @@ -116,16 +115,16 @@ function EditorModelList() {
return (
<PositioningContainer>
<Flex direction="column" height="100%" gap="size-100" marginX="size-200">
<View position="relative" overflow="hidden" marginTop="size-200">
{/* <View position="relative" overflow="hidden" marginTop="size-200">
<EditorAddModeButton />
</View>
</View> */}
<EditorRenameModelDialog close={() => setEditingModel(null)} model={editingModel} open={!!editingModel} />
<EditorProjectModelDialog
model={projectionSourceModel}
open={!!projectionSourceModel}
close={() => setProjectionSourceModel(null)}
/>
<View position="relative" flex height="100%" overflow="hidden" marginBottom="size-100">
<View position="relative" flex height="100%" overflow="hidden" marginBottom="size-100" marginTop="size-200">
<ActionBarContainer height="100%" width="100%">
<ListView
selectionMode="multiple"
Expand Down
66 changes: 41 additions & 25 deletions app/features/editor/components/EditorHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
import {
ActionGroup,
ActionButton,
Content,
Dialog,
DialogContainer,
Flex,
Item,
Key,
Menu,
MenuTrigger,
ProgressCircle,
Text,
} from "@adobe/react-spectrum";
import Header from "@core/components/Header";
import { MdiCube } from "@core/icons/MdiCube";
import { MdiTable } from "@core/icons/MdiTable";
import { useCallback, useState } from "react";
import { useExportModels } from "../hooks/useExportModels";
import useLoadLatestVersion from "../hooks/useLoadLatestVersion";
import useModelImport from "../hooks/useModelImport";
import { useRenderer } from "../hooks/useRender";

export default function EditorHeader() {
//TODO initialize data
const data = {};
const loadLatestVersion = useLoadLatestVersion();
const [isLoadingDialogOpen, setIsLoadingDialogOpen] = useState(false);
const [isSavingDialogOpen, setIsSavingDialogOpen] = useState(false);

//TODO do this after user uploads model
// useEffect(() => {
// async function loadProject() {
// setIsLoadingDialogOpen(true);
// await loadLatestVersion();
// setIsLoadingDialogOpen(false);
// }
// void loadProject();
// // eslint-disable-next-line react-hooks/exhaustive-deps
// }, []);

const exportModels = useExportModels();
const renderer = useRenderer();

Expand All @@ -58,16 +48,24 @@ export default function EditorHeader() {
};
}, [renderer, exportModels]);

const handleModelLoad = useModelImport();

const handleAction = useCallback(
async (action: Key) => {
setIsLoadingDialogOpen(true);
switch (action) {
case "save":
saveProject();
// break;
case "share":
// Share
case "shp":
await handleModelLoad([".shp", ".shx", ".dbf", ".prj", ".cpg"]);
break;
case "gltf":
await handleModelLoad([".gltf", ".glb"]);
break;
case "metacity":
await handleModelLoad([".metacity"]);
break;
//TODO handle CSV import
}
setIsLoadingDialogOpen(false);
},
[saveProject]
);
Expand All @@ -82,17 +80,35 @@ export default function EditorHeader() {
},
]}
>
<ActionGroup isQuiet onAction={handleAction}>
<Item key="save">Save</Item>
</ActionGroup>
<MenuTrigger>
<ActionButton isQuiet>Import</ActionButton>
<Menu onAction={handleAction}>
<Item key="shp">
<MdiCube />
<Text>Import Shapefile</Text>
</Item>
<Item key="gltf">
<MdiCube />
<Text>Import GLTF</Text>
</Item>
<Item key="metacity">
<MdiCube />
<Text>Import Metacity</Text>
</Item>
<Item key="csv">
<MdiTable />
<Text>Import CSV</Text>
</Item>
</Menu>
</MenuTrigger>
</Header>
<DialogContainer onDismiss={() => {}}>
{isLoadingDialogOpen && (
<Dialog>
<Content>
<Flex direction="row" gap="size-200" alignItems="center">
<ProgressCircle aria-label="Loading…" isIndeterminate />
<Text>Loading project data</Text>
<Text>Loading model data</Text>
</Flex>
</Content>
</Dialog>
Expand Down
19 changes: 0 additions & 19 deletions app/features/editor/hooks/useLoadLatestVersion.ts

This file was deleted.

48 changes: 48 additions & 0 deletions app/features/editor/hooks/useModelImport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useImportModels } from "@features/editor/hooks/useImportModels";
import { load } from "@features/editor/utils/formats/loader";
import { ToastQueue } from "@react-spectrum/toast";
import { useCallback } from "react";

export default function useModelImport() {
const importModels = useImportModels();

const handleSubmit = useCallback(
async (files: FileList | null) => {
if (!files) return;
const modelList = Array.from(files);
if (modelList.length === 0) {
ToastQueue.info("No models selected");
return;
}
const fileMap = new Map<string, Blob>();
// Add models to project
for (const file of modelList) {
fileMap.set(file.name, file);
}
const data = await load(fileMap);
await importModels(data);
},
[importModels]
);

return useCallback(
(acceptedFormats: string[]) =>
new Promise<void>((resolve, reject) => {
const input = document.createElement("input");
input.type = "file";
input.accept = acceptedFormats.join(",");
input.multiple = true;
input.onchange = async () => {
await handleSubmit(input.files);
input.remove();
resolve();
};
input.oncancel = () => {
input.remove();
resolve();
};
input.click();
}),
[handleSubmit]
);
}

0 comments on commit 0b69c7a

Please sign in to comment.