From 29a90c2f8ff97aecca6f5b3bba47d75123cc9b29 Mon Sep 17 00:00:00 2001 From: Daven Quinn Date: Mon, 6 Nov 2023 13:23:44 -0600 Subject: [PATCH] Made data sheet the dominant object on the page --- .vscode/settings.json | 30 +++++- deps/web-components | 2 +- src/components/map-navbar/index.ts | 25 ++++- src/components/map-navbar/main.module.sass | 8 ++ src/pages/maps/@id/edit/components/index.ts | 1 + .../maps/@id/edit/components/main.module.sass | 22 +++++ src/pages/maps/@id/edit/components/panels.ts | 80 ++++++++++++++++ src/pages/maps/@id/edit/edit-interface.ts | 89 ------------------ ...menu.module.sass => edit-page.module.sass} | 41 +++++---- src/pages/maps/@id/edit/edit-page.ts | 92 +++++++++++++++++++ src/pages/maps/@id/edit/index.page.ts | 4 +- src/pages/maps/@id/edit/main.module.sass | 4 +- src/pages/maps/@id/edit/map-interface.ts | 12 +-- 13 files changed, 285 insertions(+), 125 deletions(-) create mode 100644 src/pages/maps/@id/edit/components/index.ts create mode 100644 src/pages/maps/@id/edit/components/main.module.sass create mode 100644 src/pages/maps/@id/edit/components/panels.ts delete mode 100644 src/pages/maps/@id/edit/edit-interface.ts rename src/pages/maps/@id/edit/{edit-menu.module.sass => edit-page.module.sass} (55%) create mode 100644 src/pages/maps/@id/edit/edit-page.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 97569907..211abe2d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,33 @@ }, "typescript.tsdk": ".yarn/sdks/typescript/lib", "typescript.enablePromptUseWorkspaceTsdk": true, - "prettier.prettierPath": ".yarn/sdks/prettier/index.js" + "prettier.prettierPath": ".yarn/sdks/prettier/index.js", + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/__pycache__": true, + "[!s]*/**": true, + "s[!r]*/**": true, + "sr[!c]*/**": true, + "src/[!p]*/**": true, + "src/p[!a]*/**": true, + "src/pa[!g]*/**": true, + "src/pag[!e]*/**": true, + "src/page[!s]*/**": true, + "src/pages/[!m]*/**": true, + "src/pages/m[!a]*/**": true, + "src/pages/ma[!p]*/**": true, + "src/pages/map[!s]*/**": true, + "src/pages/maps/[!@]*/**": true, + "src/pages/maps/@[!i]*/**": true, + "src/pages/maps/@i[!d]*/**": true, + "src/pages/maps/@id/[!e]*/**": true, + "src/pages/maps/@id/e[!d]*/**": true, + "src/pages/maps/@id/ed[!i]*/**": true, + "src/pages/maps/@id/edi[!t]*/**": true + } } diff --git a/deps/web-components b/deps/web-components index 3db80aee..848169e0 160000 --- a/deps/web-components +++ b/deps/web-components @@ -1 +1 @@ -Subproject commit 3db80aee7cf806011ef21fad4ae4d08ae5de956d +Subproject commit 848169e012f9366dff72aeb349b4a88d244570f7 diff --git a/src/components/map-navbar/index.ts b/src/components/map-navbar/index.ts index 315050b4..f0c9111d 100644 --- a/src/components/map-navbar/index.ts +++ b/src/components/map-navbar/index.ts @@ -20,7 +20,16 @@ export function ParentRouteButton({ return h(LinkButton, { to: "..", icon, minimal: true, ...rest }); } -export function MapNavbar({ title, isOpen, setOpen, parentRoute }) { +export function MapNavbar({ + title, + isOpen, + setOpen, + parentRoute, + minimal = false, +}) { + if (minimal) { + return MapMinimalNavbar({ isOpen, setOpen }); + } const { isLoading } = useMapStatus(); return h(FloatingNavbar, { className: "searchbar map-navbar" }, [ h([h(ParentRouteButton, { parentRoute }), h("h2.map-title", title)]), @@ -32,3 +41,17 @@ export function MapNavbar({ title, isOpen, setOpen, parentRoute }) { }), ]); } + +function MapMinimalNavbar({ isOpen, setOpen }) { + const { isLoading } = useMapStatus(); + return h("div.map-minimal-navbar map-navbar", [ + h(FloatingNavbar, { className: "searchbar" }, [ + h(MapLoadingButton, { + active: isOpen, + onClick: () => setOpen(!isOpen), + isLoading, + }), + ]), + h("div.spacer"), + ]); +} diff --git a/src/components/map-navbar/main.module.sass b/src/components/map-navbar/main.module.sass index 3ad0a2a9..2be9f8e1 100644 --- a/src/components/map-navbar/main.module.sass +++ b/src/components/map-navbar/main.module.sass @@ -12,3 +12,11 @@ .map-title // Allow the title to wrap on hover overflow-x: visible + +.map-minimal-navbar + display: flex + flex-direction: row + &>.spacer + flex-grow: 1 + .map-navbar + min-width: 0 \ No newline at end of file diff --git a/src/pages/maps/@id/edit/components/index.ts b/src/pages/maps/@id/edit/components/index.ts new file mode 100644 index 00000000..58584ec0 --- /dev/null +++ b/src/pages/maps/@id/edit/components/index.ts @@ -0,0 +1 @@ +export * from "./panels"; diff --git a/src/pages/maps/@id/edit/components/main.module.sass b/src/pages/maps/@id/edit/components/main.module.sass new file mode 100644 index 00000000..a90171cc --- /dev/null +++ b/src/pages/maps/@id/edit/components/main.module.sass @@ -0,0 +1,22 @@ +.width-adjustable-panel + transition: max-width 0.1s ease-in-out + height: 100% + display: flex + flex-direction: row + position: relative + +.width-adjustable-panel-content + overflow: scroll + height: 100% + flex-grow: 1 + padding: 1em + +.width-adjuster + cursor: col-resize + width: 6px + height: 100% + // Not sure why this defaults to shrinking + flex-shrink: 0 + background-color: #efefef + &:hover + background-color: #ddd \ No newline at end of file diff --git a/src/pages/maps/@id/edit/components/panels.ts b/src/pages/maps/@id/edit/components/panels.ts new file mode 100644 index 00000000..7e59e452 --- /dev/null +++ b/src/pages/maps/@id/edit/components/panels.ts @@ -0,0 +1,80 @@ +import { ReactNode, useEffect } from "react"; +import { useRef } from "react"; +import { useStoredState } from "@macrostrat/ui-components"; +import hyper from "@macrostrat/hyper"; +import styles from "./main.module.sass"; +import { on } from "events"; +export const h = hyper.styled(styles); + +export enum AdjustSide { + LEFT = "left", + RIGHT = "right", +} + +export function WidthAdjustablePanel({ + children, + adjustSide = AdjustSide.RIGHT, + expand, + className, + storageID = null, +}: { + children: ReactNode; + adjustSide?: AdjustSide; + expand?: boolean; + className?: string; + storageID?: string; +}) { + const [maxWidth, setMaxWidth] = useStoredState( + storageID, + 0, + (v) => typeof v === "number" + ); + + useEffect(() => { + if (typeof window === "undefined") return; + setMaxWidth(window.innerWidth / 2); + }, []); + + if (expand) { + return h("div.width-adjustable-panel", { className }, [ + h("div.width-adjustable-panel-content", {}, children), + ]); + } + return h( + "div.width-adjustable-panel", + { style: { maxWidth: maxWidth + "px" }, className }, + [ + h.if(adjustSide == AdjustSide.LEFT)(WidthAdjuster, { + onAdjust: (dx) => { + const newMaxWidth = maxWidth - dx; + setMaxWidth(newMaxWidth); + }, + }), + h("div.width-adjustable-panel-content", {}, children), + h.if(adjustSide == AdjustSide.RIGHT)(WidthAdjuster, { + onAdjust: (dx) => { + const newMaxWidth = maxWidth + dx; + setMaxWidth(newMaxWidth); + }, + }), + ] + ); +} + +function WidthAdjuster({ onAdjust }: { onAdjust: (dx: number) => void }) { + const startPosition = useRef(0); + return h( + "div.width-adjuster", + { + onDragStart: (e) => { + startPosition.current = e.clientX; + }, + onDragEnd: (e) => { + const dx = e.clientX - startPosition.current; + onAdjust(dx); + }, + draggable: true, + }, + [] + ); +} diff --git a/src/pages/maps/@id/edit/edit-interface.ts b/src/pages/maps/@id/edit/edit-interface.ts deleted file mode 100644 index 38993e2d..00000000 --- a/src/pages/maps/@id/edit/edit-interface.ts +++ /dev/null @@ -1,89 +0,0 @@ -import hyper from "@macrostrat/hyper"; -import { ReactNode, useEffect } from "react"; -import styles from "./edit-menu.module.sass"; -import { useState } from "react"; -import "~/styles/global.styl"; -import EditTable from "./edit-table"; -import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; -import { LinkButton } from "~/map-interface/components/buttons"; - -const h = hyper.styled(styles); - -interface TableProps {} - -interface EditMenuProps { - setActivePage: (page: string) => void; -} - -function EditMenu({ setActivePage }: EditMenuProps) { - return h("div.edit-menu", {}, [ - h(LinkButton, { - icon: "polygon-filter", - text: "Polygons", - large: true, - to: "polygons", - }), - ]); -} - -function WidthAdjustablePanel({ children }: { children: ReactNode }) { - const [maxWidth, setMaxWidth] = useState(0); - const [startPosition, setStartPosition] = useState(0); - - useEffect(() => { - if (typeof window === "undefined") return; - setMaxWidth(window.innerWidth / 2); - }, []); - - return h( - "div.width-adjustable-panel", - { style: { maxWidth: maxWidth + "px" } }, - [ - h( - "div.width-adjuster", - { - onDragStart: (e) => { - setStartPosition(e.clientX); - }, - onDragEnd: (e) => { - const dx = e.clientX - startPosition; - const newMaxWidth = maxWidth - dx; - setMaxWidth(newMaxWidth); - }, - draggable: true, - }, - [] - ), - h("div.width-adjustable-panel-content", {}, children), - ] - ); -} - -interface EditInterfaceProps { - title?: string; - parentRoute?: string; - source_id?: number; -} - -export default function EditInterface({ source_id }: EditInterfaceProps) { - const [activePage, setActivePage] = useState(null); - - return h( - WidthAdjustablePanel, - // TODO: make this basename dynamic - h(Router, { basename: `/maps/${source_id}/edit` }, [ - h(Routes, [ - h(Route, { - path: "", - element: h(EditMenu, { setActivePage }), - }), - h(Route, { - path: "polygons", - element: h(EditTable, { - url: `http://localhost:8000/sources/${source_id}/polygons`, - }), - }), - ]), - ]) - ); -} diff --git a/src/pages/maps/@id/edit/edit-menu.module.sass b/src/pages/maps/@id/edit/edit-page.module.sass similarity index 55% rename from src/pages/maps/@id/edit/edit-menu.module.sass rename to src/pages/maps/@id/edit/edit-page.module.sass index 3c943aa3..8c329d4d 100644 --- a/src/pages/maps/@id/edit/edit-menu.module.sass +++ b/src/pages/maps/@id/edit/edit-page.module.sass @@ -1,3 +1,24 @@ +.edit-page + display: flex + flex-direction: row + height: 100vh + width: 100vw + overflow: hidden + +.edit-page-header + display: flex + flex-direction: row + +.spacer + flex-grow: 1 + +.map-panel-container, .edit-page-content + flex: 1 + min-width: 0 + +.edit-menu + flex-grow: 1 + div.interface height: 100% background-color: #efefef @@ -17,28 +38,8 @@ button.icon-button .icon-label padding-bottom: 10px -.width-adjustable-panel - transition: max-width 0.1s ease-in-out - height: 100% - display: flex - flex-direction: row - position: relative -.width-adjustable-panel-content - overflow: scroll - height: 100% - flex-grow: 1 - padding: 1em div.edit-table-wrapper overflow: scroll width: 100% - -div.width-adjuster - cursor: col-resize - width: 6px - height: 100% - // Not sure why this defaults to shrinking - flex-shrink: 0 - &:hover - background-color: #efefef \ No newline at end of file diff --git a/src/pages/maps/@id/edit/edit-page.ts b/src/pages/maps/@id/edit/edit-page.ts new file mode 100644 index 00000000..39f2b082 --- /dev/null +++ b/src/pages/maps/@id/edit/edit-page.ts @@ -0,0 +1,92 @@ +import hyper from "@macrostrat/hyper"; +import styles from "./edit-page.module.sass"; +import { useState } from "react"; +import EditTable from "./edit-table"; +import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; +import { LinkButton } from "~/map-interface/components/buttons"; +import { WidthAdjustablePanel } from "./components"; +import MapInterface from "./map-interface"; +import { useStoredState } from "@macrostrat/ui-components"; +import { ParentRouteButton } from "~/components/map-navbar"; +import { Button } from "@blueprintjs/core"; + +export const h = hyper.styled(styles); + +function EditMenu() { + return h("div.edit-menu", {}, [ + h(LinkButton, { + icon: "polygon-filter", + text: "Polygons", + large: true, + to: "polygons", + }), + ]); +} + +interface EditInterfaceProps { + title?: string; + parentRoute?: string; + source_id?: number; + mapBounds?: any; +} + +export default function EditInterface({ + source_id, + mapBounds, +}: EditInterfaceProps) { + const [showMap, setShowMap] = useStoredState( + "edit:showMap", + true, + // Check if is valid boolean + (v) => typeof v === "boolean" + ); + + const title = mapBounds.properties.name; + + return h("div.edit-page", [ + h( + WidthAdjustablePanel, + { + expand: !showMap, + className: "edit-page-content", + storageID: "edit-panel-width", + }, + // TODO: make this basename dynamic + h([ + h("div.edit-page-header", [ + h(ParentRouteButton, { parentRoute: "/maps/" }), + h("h2", title), + h("div.spacer"), + h("div.edit-page-buttons", [ + h(ShowMapButton, { showMap, setShowMap }), + ]), + ]), + h(Router, { basename: `/maps/${source_id}/edit` }, [ + h(Routes, [ + h(Route, { + path: "", + element: h(EditMenu), + }), + h(Route, { + path: "polygons", + element: h(EditTable, { + url: `http://localhost:8000/sources/${source_id}/polygons`, + }), + }), + ]), + ]), + ]) + ), + h.if(showMap)(MapInterface, { id: source_id, map: mapBounds }), + ]); +} + +function ShowMapButton({ showMap, setShowMap }) { + return h(Button, { + minimal: true, + icon: "map", + large: true, + intent: showMap ? "primary" : "none", + onClick: () => setShowMap(!showMap), + }); +} diff --git a/src/pages/maps/@id/edit/index.page.ts b/src/pages/maps/@id/edit/index.page.ts index 209e6352..559f8e79 100644 --- a/src/pages/maps/@id/edit/index.page.ts +++ b/src/pages/maps/@id/edit/index.page.ts @@ -30,11 +30,11 @@ export async function onBeforeRender(pageContext: PageContextBuiltInServer) { }; } -const MapInterface = () => import("./map-interface"); +const EditInterface = () => import("./edit-page"); export function Page({ id, map }) { return h( "div.single-map", - h(ClientOnly, { component: MapInterface, id, map }) + h(ClientOnly, { component: EditInterface, source_id: id, mapBounds: map }) ); } diff --git a/src/pages/maps/@id/edit/main.module.sass b/src/pages/maps/@id/edit/main.module.sass index f5cf3b3d..6a9080ad 100644 --- a/src/pages/maps/@id/edit/main.module.sass +++ b/src/pages/maps/@id/edit/main.module.sass @@ -6,8 +6,8 @@ body --map-detail-stack-width: fit-content .single-map - width: 100vh - height: 100vh + flex: 1 + height: 100% margin: 0 --map-context-stack-width: 16em diff --git a/src/pages/maps/@id/edit/map-interface.ts b/src/pages/maps/@id/edit/map-interface.ts index e633d18c..cb376e55 100644 --- a/src/pages/maps/@id/edit/map-interface.ts +++ b/src/pages/maps/@id/edit/map-interface.ts @@ -16,7 +16,6 @@ import { MapNavbar } from "~/components/map-navbar"; import { SETTINGS } from "~/map-interface/settings"; import "~/styles/global.styl"; import { s3Address, tempImageIndex } from "../../raster-images"; -import EditInterface from "./edit-interface"; import styles from "./main.module.sass"; const h = hyper.styled(styles); @@ -205,16 +204,11 @@ export default function MapInterface({ id, map }) { MapAreaContainer, { className: "single-map", - navbar: h(MapNavbar, { title, parentRoute: "/maps", isOpen, setOpen }), + navbar: h(MapNavbar, { isOpen, setOpen, minimal: true }), contextPanel, contextPanelOpen: isOpen, - detailPanelOpen: true, - detailPanelStyle: "fixed", - detailPanel: h( - EditInterface, - { title: "Source 1", parentRoute: "/maps/", source_id: id }, - [] - ), + detailPanelOpen: false, + fitViewport: false, }, [ h(