diff --git a/apps/zui/package.json b/apps/zui/package.json
index c8a9530852..db0092352e 100644
--- a/apps/zui/package.json
+++ b/apps/zui/package.json
@@ -16,6 +16,7 @@
"start:main": "yarn build:main --watch",
"start:renderer": "next dev -p 4567",
"start:electron": "nodemon --watch dist ../../node_modules/electron/cli.js .",
+ "start:production": "node ../../node_modules/electron/cli.js .",
"watch-code": "run-p start:main start:renderer",
"build": "run-p -l 'build:**'",
"build:main": "node scripts/esbuild.mjs",
diff --git a/apps/zui/src/app/routes/app-wrapper/data-dropzone-controller.tsx b/apps/zui/src/app/routes/app-wrapper/data-dropzone-controller.tsx
new file mode 100644
index 0000000000..6a23481602
--- /dev/null
+++ b/apps/zui/src/app/routes/app-wrapper/data-dropzone-controller.tsx
@@ -0,0 +1,35 @@
+import {previewLoadFiles, quickLoadFiles} from "src/domain/loads/handlers"
+
+export class DataDropzoneController {
+ constructor(
+ private shift: boolean,
+ private previewing: boolean,
+ private poolId: string
+ ) {}
+
+ // prettier-ignore
+ get title() {
+ if (this.previewing) return (<>Add Files>)
+ if (this.shift) return (<>Quick Load Data>)
+ return <>Preview & Load Data>
+ }
+
+ // prettier-ignore
+ get note() {
+ if (this.previewing) return null
+ if (this.shift) return <>Release {"Shift"} to preview data first.>
+ return <>Hold {"Shift"} to quick load into new pool with defaults.>
+ }
+
+ onDrop(fileObjects: File[]) {
+ const files = fileObjects.map((f) => f.path)
+ const poolId = this.poolId
+ if (this.previewing) {
+ previewLoadFiles({files, poolId})
+ } else if (this.shift) {
+ quickLoadFiles({files})
+ } else {
+ previewLoadFiles({files, poolId})
+ }
+ }
+}
diff --git a/apps/zui/src/app/routes/app-wrapper/data-dropzone.module.css b/apps/zui/src/app/routes/app-wrapper/data-dropzone.module.css
index 1ba1055e1b..5d37752bac 100644
--- a/apps/zui/src/app/routes/app-wrapper/data-dropzone.module.css
+++ b/apps/zui/src/app/routes/app-wrapper/data-dropzone.module.css
@@ -1,17 +1,19 @@
.dropzone {
- position: relative;
+ position: relative;
}
.overlay {
- width: 100%;
- height: 100%;
- z-index: 3;
+ width: 100vw;
+ height: 100vh;
+ max-width: none;
+ max-height: none;
+ border: none;
background: var(--orange);
- position: absolute;
+ position: fixed;
top: 0;
- left:0;
- right:0;
- bottom:0;
+ left: 0;
+ right: 0;
+ bottom: 0;
display: flex;
align-items: center;
justify-content: center;
@@ -24,8 +26,8 @@
flex-direction: column;
gap: 1em;
animation:
- 700ms popup cubic-bezier(0.16, 1, 0.3, 1) forwards,
- 300ms fade-opacity ease-in forwards;
+ 700ms popup cubic-bezier(0.16, 1, 0.3, 1) forwards,
+ 300ms fade-opacity ease-in forwards;
}
.title {
@@ -33,7 +35,7 @@
font-weight: 900;
text-align: center;
color: white;
-
+
margin: 0;
}
@@ -58,11 +60,12 @@
border-radius: 3px;
margin: 0 0.2em;
border: 1px solid rgba(255, 255, 255, 0.2);
- box-shadow: 0 1px 1px 0 rgba(0,0,0,0.1);
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
text-transform: uppercase;
font-size: 0.85em;
font-weight: 500;
- letter-spacing: 1px;;
+ letter-spacing: 1px;
+ ;
}
@@ -72,7 +75,6 @@
height: 3rem;
margin: 0;
animation: 700ms margin-in cubic-bezier(0.16, 1, 0.3, 1) forwards
-
}
.hair div:first-child {
@@ -119,6 +121,7 @@
from {
opacity: 0;
}
+
to {
opacity: 1;
}
@@ -137,7 +140,8 @@
@keyframes margin-in {
from {
margin: 0;
- }
+ }
+
to {
margin: 10vmin;
}
diff --git a/apps/zui/src/app/routes/app-wrapper/data-dropzone.tsx b/apps/zui/src/app/routes/app-wrapper/data-dropzone.tsx
index d16f875440..3a773f3dc9 100644
--- a/apps/zui/src/app/routes/app-wrapper/data-dropzone.tsx
+++ b/apps/zui/src/app/routes/app-wrapper/data-dropzone.tsx
@@ -1,27 +1,22 @@
import styles from "./data-dropzone.module.css"
import {useFilesDrop} from "src/util/hooks/use-files-drop"
import usePoolId from "src/app/router/hooks/use-pool-id"
-import {previewLoadFiles, quickLoadFiles} from "src/domain/loads/handlers"
import useListener from "src/js/components/hooks/useListener"
import {useEffect, useState} from "react"
+import {Dialog} from "src/components/dialog"
+import LoadDataForm from "src/js/state/LoadDataForm"
+import {useSelector} from "react-redux"
+import {DataDropzoneController} from "./data-dropzone-controller"
export function DataDropzone({children}) {
const poolId = usePoolId()
const [shiftKey, setShiftKey] = useState(false)
- const onDrop = async (webFiles: File[]) => {
- const files = webFiles.map((f) => f.path)
- if (shiftKey) {
- quickLoadFiles({files})
- } else {
- previewLoadFiles({files, poolId})
- }
- }
-
- let [props, ref] = useFilesDrop({onDrop})
+ const previewing = useSelector(LoadDataForm.getShow)
+ const dropzone = new DataDropzoneController(shiftKey, previewing, poolId)
+ let [props, ref] = useFilesDrop({onDrop: (files) => dropzone.onDrop(files)})
useListener(document.body, "dragover", (e: KeyboardEvent) => {
- if (!props.isOver) return
- setShiftKey(e.shiftKey)
+ if (props.isOver) setShiftKey(e.shiftKey)
})
useEffect(() => {
@@ -32,49 +27,18 @@ export function DataDropzone({children}) {
{children}
{props.isOver && (
-
-
-
-
-
+
+
)}
)
diff --git a/apps/zui/src/components/dialog/dialog.tsx b/apps/zui/src/components/dialog/index.tsx
similarity index 65%
rename from apps/zui/src/components/dialog/dialog.tsx
rename to apps/zui/src/components/dialog/index.tsx
index be8224bf02..bd7678245e 100644
--- a/apps/zui/src/components/dialog/dialog.tsx
+++ b/apps/zui/src/components/dialog/index.tsx
@@ -1,13 +1,15 @@
import {HTMLAttributes, MouseEventHandler} from "react"
-import {usePosition} from "./use-position"
import {useOpener} from "./use-opener"
import {useOutsideClick} from "./use-outside-click"
import useCallbackRef from "src/js/components/hooks/useCallbackRef"
import {omit} from "lodash"
+import {call} from "src/util/call"
+import {useFixedPosition} from "src/util/hooks/use-fixed-position"
export type DialogProps = {
isOpen: boolean
- onClose: () => void
+ onClose?: () => void
+ onCancel?: () => void
modal?: boolean
onOutsideClick?: (e: globalThis.MouseEvent) => void
onClick?: MouseEventHandler
@@ -34,21 +36,33 @@ const nonHTMLProps: (keyof DialogProps)[] = [
export function Dialog(props: DialogProps) {
const [node, setNode] = useCallbackRef()
- const style = usePosition(node, props)
-
- useOpener(node, props)
+ useOpener(node, props) // Make sure we open it before positioning it
useOutsideClick(node, props)
+ const style = useFixedPosition({
+ anchor: props.anchor,
+ anchorPoint: props.anchorPoint,
+ target: node && props.isOpen ? node : null,
+ targetPoint: props.dialogPoint,
+ targetMargin: props.dialogMargin,
+ keepOnScreen: props.keepOnScreen,
+ })
function onClose(e) {
e.preventDefault()
- props.onClose()
+ call(props.onClose)
+ }
+
+ function onCancel(e) {
+ e.preventDefault()
+ call(props.onCancel)
+ call(props.onClose)
}
return (