{files.map((file) => (
diff --git a/components/FileSelect.tsx b/components/FileSelect.tsx
index ce8bfb0..ce78f85 100644
--- a/components/FileSelect.tsx
+++ b/components/FileSelect.tsx
@@ -2,8 +2,13 @@ import * as React from 'react';
import FileList from '@components/FileList';
-export default function FileSelect(props) {
- const [root, setRoot] = React.useState('/home/elijah');
+export default function FileSelect(props: {
+ label?: string,
+ root?: string,
+ onSelectFile?: (path: string) => void,
+ onChangeRoot?: (path: string) => void,
+}) {
+ const [root, setRoot] = React.useState('/');
return (
diff --git a/components/forms/Form.module.scss b/components/Form.module.scss
similarity index 100%
rename from components/forms/Form.module.scss
rename to components/Form.module.scss
diff --git a/components/Main.module.scss b/components/Main.module.scss
new file mode 100644
index 0000000..1fd8b0e
--- /dev/null
+++ b/components/Main.module.scss
@@ -0,0 +1,34 @@
+.body {
+ display: flex;
+ flex-direction: column;
+}
+
+.top {
+ width: 100%;
+ height: 4rem;
+ display: flex;
+ flex-direction: row;
+
+ border-bottom: 1px solid var(--color-border);
+ margin-bottom: -1px;
+}
+
+.bottom {
+ display: flex;
+
+ flex-grow: 1;
+ min-height: 100vh;
+}
+
+.left {
+ display: flex;
+
+ width: 16rem;
+ height: inherit;
+ border-right: 1px solid var(--color-border);
+ margin-right: -1px;
+}
+
+.right {
+ height: inherit;
+}
\ No newline at end of file
diff --git a/components/Main.tsx b/components/Main.tsx
new file mode 100644
index 0000000..7da61e9
--- /dev/null
+++ b/components/Main.tsx
@@ -0,0 +1,36 @@
+'use client';
+
+import React from 'react';
+import { apps } from '@root/common/navigation';
+
+import styles from './Main.module.scss';
+
+import AppDDM from '@components/apps/ddm/DDM';
+import AppPtolemy from '@components/apps/ptolemy/Ptolemy';
+import { getCookie, setCookie } from '@root/modules/cookies';
+
+export default function Main(props) {
+ const [activeApp, _setActiveApp] = React.useState(apps.ddm);
+ function setActiveApp(app: string) {
+ // TODO: app switching temporarily disabled
+ return;
+
+ _setActiveApp(app);
+ setCookie('active-app', app);
+ }
+ const appNames = Object.keys(apps);
+
+ React.useEffect(() => {
+ let savedState = getCookie('active-app');
+ if (savedState) {
+ _setActiveApp(savedState);
+ }
+ })
+
+ switch (activeApp) {
+ case apps.ddm:
+ return
+ case apps.ptolemy:
+ return
+ }
+}
\ No newline at end of file
diff --git a/components/Modal.module.scss b/components/Modal.module.scss
new file mode 100644
index 0000000..6fe6e09
--- /dev/null
+++ b/components/Modal.module.scss
@@ -0,0 +1,34 @@
+.body {
+ position: absolute;
+ border: 1px solid var(--color-border);
+ background: var(--color-background);
+ border-radius: 0.5rem;
+ transform: translateY(-3rem);
+ margin-left: 2rem;
+ box-shadow: 0px 0px 6px 4px #0004;
+ z-index: 100;
+ opacity: 100%;
+ transition: 0.15s;
+ padding: 2rem;
+
+ &::before {
+ content: "";
+ margin-top: 1rem;
+ display: block;
+ position: fixed;
+ width: 8px;
+ height: 8px;
+ left: 0;
+ transform: translate(-50%, -50%) rotate(45deg);
+ background: var(--color-background);
+ border-left: 1px solid var(--color-border);
+ border-bottom: 1px solid var(--color-border);
+ }
+}
+
+.bodyHidden {
+ @extend .body;
+
+ opacity: 0%;
+ margin-left: 1rem;
+}
\ No newline at end of file
diff --git a/components/Modal.tsx b/components/Modal.tsx
new file mode 100644
index 0000000..53378eb
--- /dev/null
+++ b/components/Modal.tsx
@@ -0,0 +1,72 @@
+import * as React from 'react';
+
+import styles from './Modal.module.scss';
+
+// The `onClose` function will pass the provided `id` back to the caller so it
+// can be compared to avoid the case of one modal closing causing another one to
+// close.
+export default function Modal(props: {
+ modalID?: any,
+ anchor: React.RefObject
,
+ children: React.ReactNode,
+ onClose: (modalID?: any) => void,
+}) {
+ const fadeSeconds = 0.15;
+
+ const ref = React.useRef(null);
+
+ const [modalPos, setModalPos] = React.useState(null);
+ const [hidden, setHidden] = React.useState(true);
+
+ function updateModalPos(node) {
+ let anchorRect = node.getBoundingClientRect();
+ let anchorOffsetParentRect = node.offsetParent.getBoundingClientRect();
+ let left = anchorRect.left - anchorOffsetParentRect.left + anchorRect.width;
+ let top = anchorRect.top - anchorOffsetParentRect.top + anchorRect.height * 0.5;
+ setModalPos({ x: left, y: top });
+ }
+
+ React.useEffect(() => {
+ function handleClickOutside(event) {
+ console.log('handle click');
+
+ if (ref.current && !ref.current.contains(event.target)) {
+ event.stopPropagation();
+
+ setHidden(true);
+
+ setTimeout(() => {
+ props.onClose(props.modalID);
+ }, fadeSeconds * 1000);
+ }
+ }
+
+ updateModalPos(props.anchor.current);
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => {
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, [ref]);
+
+ React.useEffect(() => {
+ setTimeout(e => setHidden(false), 10);
+ }, []);
+
+ if (modalPos == null) {
+ return null;
+ }
+
+ return (
+
+ {props.children}
+
+ );
+}
\ No newline at end of file
diff --git a/components/ProviderSelect.tsx b/components/ProviderSelect.tsx
index f1afa79..16cf5f6 100644
--- a/components/ProviderSelect.tsx
+++ b/components/ProviderSelect.tsx
@@ -1,15 +1,13 @@
-import Select from '@components/Select';
+import Select from '@components/basic/Select';
export default function ProviderSelect(props) {
return (
-
);
}
-function ProviderCard(props) {
+function ProviderCard(props: { provider: any, datasets: any[], updateDatasets: () => void }) {
let provider = props.provider;
let [editing, setEditing] = React.useState(false);
@@ -60,7 +63,7 @@ function ProviderCard(props) {
let [saving, setSaving] = React.useState(false);
let [allowedDatasets, setAllowedDatasets] = React.useState(provider.allowed_datasets?.map((dataset, i) => dataset.name) || []);
- let datasetNames = props.state.datasets?.map((dataset, i) => dataset.name) || [];
+ let datasetNames = props.datasets?.map((dataset, i) => dataset.name) || [];
function cancelEdit() {
setAllowSelfService(provider.allow_self_service);
@@ -82,40 +85,47 @@ function ProviderCard(props) {
setSaving(false);
}
- props.updateState();
+ props.updateDatasets();
}
- if (editing) return (
-
-
- Rename {provider.actor_id}}
- value={name}
- onChange={e => setName(e.target.value)}
- />
-
-
- {Utilities.bytesToSize(provider.bytes_replicated.padded)} (padded)
- {Utilities.bytesToSize(provider.bytes_replicated.raw)} (unpadded)
-
-
- setAllowSelfService(e.target.checked)} />
-
-
-
-
-
-
-
-
- );
+ if (editing)
+ return (
+
+
+
+ Rename {provider.actor_id}
+
+ }
+ value={name}
+ onChange={(e) => setName(e.target.value)}
+ />
+
+
+ {Utilities.bytesToSize(provider.bytes_replicated.padded)} (padded)
+ {Utilities.bytesToSize(provider.bytes_replicated.raw)} (unpadded)
+
+
+ setAllowSelfService(e.target.checked)} />
+
+
+
+
+
+
+
+
+
+
+ );
return (
);
}
function ProviderKey(props) {
-
const [copied, setCopied] = React.useState(false);
function copy() {
@@ -160,7 +168,9 @@ function ProviderKey(props) {
return (
- {props.state.wallets &&
+ {props.wallets && (
Address
@@ -26,30 +25,23 @@ export default function SceneWallets(props) {
Datacap Balance
Datasets
- {props.state.wallets.map((wallet, i) => {
+ {props.wallets.map((wallet, i) => {
return (
- dataset.name)}
- updateState={props.updateState} />
+ dataset.name)} updateDatasets={props.updateDatasets} />
);
})}
- }
- {props.state.wallets === undefined &&
}
-
- )
+ )}
+ {props.wallets === undefined &&