Testing
This commit is contained in:
+26
-1
@@ -1,6 +1,6 @@
|
||||
import { h, Fragment } from 'preact';
|
||||
import { useState, useCallback, useRef, useEffect } from 'preact/hooks';
|
||||
import type { Interface, Widget, PlotLayout, StateVar, LogicGraph } from './lib/types';
|
||||
import type { Interface, Widget, PlotLayout, StateVar, LogicGraph, Folder } from './lib/types';
|
||||
import { serializeInterface, parseInterface } from './lib/xml';
|
||||
import { initLocalState } from './lib/localstate';
|
||||
import SignalTree from './SignalTree';
|
||||
@@ -8,6 +8,7 @@ import EditCanvas, { genWidgetId, DEFAULT_SIZES } from './EditCanvas';
|
||||
import PlotPanelCanvas from './PlotPanelCanvas';
|
||||
import LogicEditor from './LogicEditor';
|
||||
import PropertiesPane from './PropertiesPane';
|
||||
import ShareDialog from './ShareDialog';
|
||||
import HelpModal from './HelpModal';
|
||||
import ZoomControl from './ZoomControl';
|
||||
import { useAuth, canWrite } from './lib/auth';
|
||||
@@ -121,6 +122,10 @@ export default function EditMode({ initial, onDone }: Props) {
|
||||
const [showGroupMenu, setShowGroupMenu] = useState(false);
|
||||
const [showHelp, setShowHelp] = useState(false);
|
||||
const [helpSection, setHelpSection] = useState('edit');
|
||||
// Panel sharing (folder, public visibility, grants). The folders list feeds
|
||||
// ShareDialog's folder picker; fetched lazily the first time Share is opened.
|
||||
const [showShare, setShowShare] = useState(false);
|
||||
const [folders, setFolders] = useState<Folder[]>([]);
|
||||
const [leftW, setLeftW] = useState(220);
|
||||
const [rightW, setRightW] = useState(260);
|
||||
// Center column tab: the drag-and-drop layout editor, or the panel-logic editor.
|
||||
@@ -163,6 +168,15 @@ export default function EditMode({ initial, onDone }: Props) {
|
||||
setShowHelp(true);
|
||||
}, []);
|
||||
|
||||
// Open the panel-sharing dialog, refreshing the folder list it offers first.
|
||||
const openShare = useCallback(() => {
|
||||
fetch('/api/v1/folders')
|
||||
.then(r => r.ok ? r.json() : [])
|
||||
.then(data => setFolders(Array.isArray(data) ? data : []))
|
||||
.catch(() => {})
|
||||
.finally(() => setShowShare(true));
|
||||
}, []);
|
||||
|
||||
// Undo / redo. Snapshots capture both widgets and (for plot panels) the split
|
||||
// layout, so split/close/resize operations are undone atomically.
|
||||
type Snapshot = { widgets: Widget[]; layout?: PlotLayout };
|
||||
@@ -748,6 +762,7 @@ export default function EditMode({ initial, onDone }: Props) {
|
||||
onChange={handleWidgetChange}
|
||||
onRenameId={handleWidgetRename}
|
||||
onIfaceChange={handleIfaceChange}
|
||||
onShare={writable && iface.id ? openShare : undefined}
|
||||
width={rightW}
|
||||
/>
|
||||
</Fragment>
|
||||
@@ -797,6 +812,16 @@ export default function EditMode({ initial, onDone }: Props) {
|
||||
{showHelp && (
|
||||
<HelpModal initialSection={helpSection} onClose={() => setShowHelp(false)} />
|
||||
)}
|
||||
|
||||
{showShare && iface.id && (
|
||||
<ShareDialog
|
||||
ifaceId={iface.id}
|
||||
ifaceName={iface.name}
|
||||
folders={folders}
|
||||
onClose={() => setShowShare(false)}
|
||||
onSaved={() => window.dispatchEvent(new CustomEvent('uopi:refresh-interfaces'))}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ interface Props {
|
||||
onChange: (updated: Widget) => void;
|
||||
onRenameId: (oldId: string, newId: string) => void;
|
||||
onIfaceChange: (updated: Interface) => void;
|
||||
// When provided, a "Share…" button is shown in the canvas-level section that
|
||||
// opens the panel's sharing settings (folder, public visibility, grants).
|
||||
onShare?: () => void;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
@@ -86,7 +89,7 @@ const LABEL_WIDGETS = new Set(['textview', 'gauge', 'barh', 'barv', 'setvalue',
|
||||
// Widgets with multiple signals
|
||||
const MULTI_SIGNAL_WIDGETS = new Set(['plot', 'multiled', 'table']);
|
||||
|
||||
export default function PropertiesPane({ selected, multiCount, iface, onChange, onRenameId, onIfaceChange, width }: Props) {
|
||||
export default function PropertiesPane({ selected, multiCount, iface, onChange, onRenameId, onIfaceChange, onShare, width }: Props) {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [configSets, setConfigSets] = useState<{ id: string; name: string }[]>([]);
|
||||
|
||||
@@ -173,6 +176,11 @@ export default function PropertiesPane({ selected, multiCount, iface, onChange,
|
||||
</Field>
|
||||
</div>
|
||||
)}
|
||||
{onShare && (
|
||||
<button class="panel-btn props-share-btn" onClick={onShare} title="Manage folder, public visibility and per-user/group sharing">
|
||||
Share…
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{w && (
|
||||
|
||||
@@ -3016,6 +3016,11 @@ body {
|
||||
|
||||
.props-section:last-child { border-bottom: none; }
|
||||
|
||||
.props-share-btn {
|
||||
margin: 0.4rem 0.6rem 0;
|
||||
width: calc(100% - 1.2rem);
|
||||
}
|
||||
|
||||
.props-section-title {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
|
||||
Reference in New Issue
Block a user