Implemented admin pane + user permission
This commit is contained in:
+52
-1
@@ -18,10 +18,13 @@ import PlotWidget from './widgets/PlotWidget';
|
||||
import ImageWidget from './widgets/ImageWidget';
|
||||
import LinkWidget from './widgets/LinkWidget';
|
||||
import ConfigSelect from './widgets/ConfigSelect';
|
||||
import Container from './widgets/Container';
|
||||
import TableWidget from './widgets/TableWidget';
|
||||
import ContextMenu from './ContextMenu';
|
||||
import InfoPanel from './InfoPanel';
|
||||
import SplitLayout from './SplitLayout';
|
||||
import LogicDialogs from './LogicDialogs';
|
||||
import { centreInside, widgetTab, tabPanes } from './lib/containers';
|
||||
|
||||
const COMPONENTS: Record<string, any> = {
|
||||
textview: TextView,
|
||||
@@ -38,8 +41,18 @@ const COMPONENTS: Record<string, any> = {
|
||||
image: ImageWidget,
|
||||
link: LinkWidget,
|
||||
configselect: ConfigSelect,
|
||||
container: Container,
|
||||
table: TableWidget,
|
||||
};
|
||||
|
||||
// Container panes are decorative frames placed behind other widgets; render them
|
||||
// first so they paint underneath.
|
||||
function renderOrder(widgets: Widget[]): Widget[] {
|
||||
const containers = widgets.filter(w => w.type === 'container');
|
||||
const rest = widgets.filter(w => w.type !== 'container');
|
||||
return [...containers, ...rest];
|
||||
}
|
||||
|
||||
interface CtxState {
|
||||
visible: boolean;
|
||||
x: number;
|
||||
@@ -84,6 +97,26 @@ export default function Canvas({ iface, onNavigate, timeRange }: Props) {
|
||||
visible: false, x: 0, y: 0, signal: null,
|
||||
});
|
||||
const [infoSignal, setInfoSignal] = useState<SignalRef | null>(null);
|
||||
// View-mode collapse state for collapsible container panes (ephemeral, by id).
|
||||
const [collapsed, setCollapsed] = useState<Set<string>>(() => new Set());
|
||||
// View-mode active-tab state for tabbed container panes (ephemeral, by id).
|
||||
const [activeTabs, setActiveTabs] = useState<Map<string, number>>(() => new Map());
|
||||
|
||||
function toggleCollapse(id: string) {
|
||||
setCollapsed(prev => {
|
||||
const next = new Set(prev);
|
||||
next.has(id) ? next.delete(id) : next.add(id);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
|
||||
function selectTab(id: string, i: number) {
|
||||
setActiveTabs(prev => {
|
||||
const next = new Map(prev);
|
||||
next.set(id, i);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
|
||||
// Instantiate this panel's local state variables from their initial values.
|
||||
useEffect(() => {
|
||||
@@ -157,10 +190,24 @@ export default function Canvas({ iface, onNavigate, timeRange }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
// Collapsible panes currently in the collapsed state — their contents are hidden.
|
||||
const collapsedPanes = iface.widgets.filter(
|
||||
w => w.type === 'container' && w.options['collapsible'] === 'true' && collapsed.has(w.id),
|
||||
);
|
||||
// Tabbed panes — widgets inside that aren't on the active tab are hidden.
|
||||
const tPanes = tabPanes(iface.widgets);
|
||||
|
||||
return (
|
||||
<div class="canvas-container">
|
||||
<div class="canvas-area canvas-view-bare" style={`width:${iface.w}px;height:${iface.h}px;`}>
|
||||
{iface.widgets.map(widget => {
|
||||
{renderOrder(iface.widgets).map(widget => {
|
||||
// Hide widgets that fall inside a currently-collapsed container pane.
|
||||
const hidden = collapsedPanes.some(c => c.id !== widget.id && centreInside(widget, c));
|
||||
// Hide widgets inside a tabbed pane that aren't on its active tab.
|
||||
const tabHidden = tPanes.some(c =>
|
||||
c.id !== widget.id && centreInside(widget, c) && widgetTab(widget) !== (activeTabs.get(c.id) ?? 0),
|
||||
);
|
||||
if (hidden || tabHidden) return null;
|
||||
const Comp = COMPONENTS[widget.type];
|
||||
const inner = Comp
|
||||
? <Comp
|
||||
@@ -168,6 +215,10 @@ export default function Canvas({ iface, onNavigate, timeRange }: Props) {
|
||||
onContextMenu={(e: MouseEvent) => onCtxMenu(e, widget)}
|
||||
onNavigate={onNavigate}
|
||||
timeRange={timeRange}
|
||||
collapsed={collapsed.has(widget.id)}
|
||||
onToggleCollapse={() => toggleCollapse(widget.id)}
|
||||
activeTab={activeTabs.get(widget.id) ?? 0}
|
||||
onSelectTab={(i: number) => selectTab(widget.id, i)}
|
||||
/>
|
||||
: (
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user