Skip to content

Commit

Permalink
HPCC-31052 Metrics layout fails to persist on top level change
Browse files Browse the repository at this point in the history
Switching from Metrics to Logical Files (for example)

Signed-off-by: Gordon Smith <[email protected]>
  • Loading branch information
GordonSmith committed Jan 3, 2024
1 parent 25fd4c4 commit 99cfb53
Show file tree
Hide file tree
Showing 8 changed files with 775 additions and 1,164 deletions.
1,774 changes: 673 additions & 1,101 deletions esp/src/package-lock.json

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions esp/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@
"@fluentui/react-experiments": "8.14.95",
"@fluentui/react-hooks": "8.6.29",
"@fluentui/react-icons-mdl2": "1.3.47",
"@hpcc-js/chart": "2.81.7",
"@hpcc-js/codemirror": "2.60.12",
"@hpcc-js/common": "2.71.12",
"@hpcc-js/comms": "2.85.0",
"@hpcc-js/chart": "2.81.8",
"@hpcc-js/codemirror": "2.61.0",
"@hpcc-js/common": "2.71.13",
"@hpcc-js/comms": "2.86.0",
"@hpcc-js/dataflow": "8.1.6",
"@hpcc-js/eclwatch": "2.73.27",
"@hpcc-js/graph": "2.85.8",
"@hpcc-js/html": "2.42.13",
"@hpcc-js/layout": "2.49.12",
"@hpcc-js/map": "2.77.11",
"@hpcc-js/other": "2.15.12",
"@hpcc-js/phosphor": "2.16.12",
"@hpcc-js/react": "2.53.9",
"@hpcc-js/tree": "2.40.12",
"@hpcc-js/eclwatch": "2.73.31",
"@hpcc-js/graph": "2.85.9",
"@hpcc-js/html": "2.42.14",
"@hpcc-js/layout": "2.49.13",
"@hpcc-js/map": "2.77.12",
"@hpcc-js/other": "2.15.13",
"@hpcc-js/phosphor": "2.17.0",
"@hpcc-js/react": "2.53.10",
"@hpcc-js/tree": "2.40.13",
"@hpcc-js/util": "2.50.6",
"@kubernetes/client-node": "0.18.1",
"clipboard": "2.0.11",
Expand Down Expand Up @@ -111,4 +111,4 @@
"type": "git",
"url": "https://github.com/hpcc-systems/HPCC-Platform"
}
}
}
17 changes: 12 additions & 5 deletions esp/src/src-react/components/Metrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ export const Metrics: React.FunctionComponent<MetricsProps> = ({
const metricGraph = useConst(() => new MetricGraph());
const metricGraphWidget = useConst(() => new MetricGraphWidget()
.zoomToFitLimit(1)
.selectionGlowColor("DodgerBlue")
.on("selectionChanged", () => {
const selection = metricGraphWidget.selection().filter(id => metricGraph.item(id)).map(id => metricGraph.item(id).id);
setSelectedMetricsSource("metricGraphWidget");
Expand Down Expand Up @@ -592,10 +593,16 @@ export const Metrics: React.FunctionComponent<MetricsProps> = ({
];
}, [scopeFilter, onChangeScopeFilter, scopesTable, graphComponent, propsTable, propsTable2]);

const layoutChanged = React.useCallback((layout) => {
setOptions({ ...options, layout });
saveOptions();
}, [options, saveOptions, setOptions]);
React.useEffect(() => {

// Update layout prior to unmount ---
if (dockpanel && options && saveOptions && setOptions) {
return () => {
setOptions({ ...options, layout: dockpanel.getLayout() });
saveOptions();
};
}
}, [dockpanel, options, saveOptions, setOptions]);

// Command Bar ---
const buttons = React.useMemo((): ICommandBarItemProps[] => [
Expand Down Expand Up @@ -678,7 +685,7 @@ export const Metrics: React.FunctionComponent<MetricsProps> = ({
</>}
main={
<ErrorBoundary>
<DockPanel items={items} layout={options?.layout} layoutChanged={layoutChanged} onDockPanelCreate={setDockpanel} />
<DockPanel items={items} layout={options?.layout} onDockPanelCreate={setDockpanel} />
<MetricsOptions show={showMetricOptions} setShow={setShowMetricOptions} />
</ErrorBoundary>
}
Expand Down
4 changes: 3 additions & 1 deletion esp/src/src-react/components/MetricsOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ export const MetricsOptions: React.FunctionComponent<MetricsOptionsProps> = ({
const [scopeTypes, properties] = useMetricMeta();
const [options, setOptions, save, reset] = useMetricsOptions();

const closeOptions = () => setShow(false);
const closeOptions = React.useCallback(() => {
setShow(false);
}, [setShow]);

const allChecked = scopeTypes.length === options.scopeTypes.length;

Expand Down
15 changes: 13 additions & 2 deletions esp/src/src-react/hooks/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ const defaults = {

const options = { ...defaults };

function checkLayout(options: MetricsOptions): boolean {
if (options?.layout && !options?.layout?.["main"]) {
delete options.layout;
}
return !!options?.layout;
}

export interface MetricsOptions {
scopeTypes: string[];
properties: string[];
Expand All @@ -43,15 +50,19 @@ export function useMetricsOptions(): [MetricsOptions, (opts: MetricsOptions) =>
}, [refresh]);

const save = React.useCallback(() => {
store?.set("MetricOptions", JSON.stringify(options), true);
if (checkLayout(options)) {
store?.set("MetricOptions", JSON.stringify(options), true);
}
}, [store]);

const reset = React.useCallback((toDefaults: boolean = false) => {
if (toDefaults) {
setOptions({ ...defaults });
} else {
store?.get("MetricOptions").then(opts => {
setOptions({ ...defaults, ...JSON.parse(opts) });
const options = JSON.parse(opts);
checkLayout(options);
setOptions({ ...defaults, ...options });
});
}
}, [setOptions, store]);
Expand Down
75 changes: 47 additions & 28 deletions esp/src/src-react/layouts/DockPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,49 +107,72 @@ function isDockPanelComponent(item: DockPanelWidget | DockPanelComponent): item
return !!(item as DockPanelComponent).component;
}

export interface DockPanelLayout {
main: object;
}

function validLayout(layout?: any) {
return !!layout?.main;
}

function formatLayout(layout?: any): DockPanelLayout | undefined {
if (validLayout(layout)) {
return layout;
}
return undefined;
}

export class ResetableDockPanel extends HPCCDockPanel {

protected _origLayout;
protected _origLayout: DockPanelLayout | undefined;
protected _lastLayout: DockPanelLayout | undefined;

render() {
const retVal = super.render();
if (this._origLayout === undefined) {
this._origLayout = this.layout();
resetLayout() {
if (this._origLayout) {
this
.layout(this._origLayout)
.lazyRender()
;
}
return retVal;
}

setLayout(layout: object) {
if (this._origLayout === undefined) {
this._origLayout = this.layout();
this._origLayout = formatLayout(this.layout());
}
this.layout(layout);
return this;
}

resetLayout() {
if (this._origLayout) {
this
.layout(this._origLayout)
.lazyRender()
;
getLayout() {
return formatLayout(this.layout()) ?? this._lastLayout ?? this._origLayout;
}

render() {
const retVal = super.render();
if (this._origLayout === undefined) {
this._origLayout = formatLayout(this.layout());
}
return retVal;
}

// Events ---
layoutChanged() {
this._lastLayout = this.getLayout();
}
}

export type DockPanelItems = (DockPanelWidget | DockPanelComponent)[];

interface DockPanelProps {
items?: DockPanelItems,
layout?: object,
layoutChanged: (layout: object) => void,
onDockPanelCreate: (dockpanel: ResetableDockPanel) => void
items?: DockPanelItems;
layout?: object;
onDockPanelCreate?: (dockpanel: ResetableDockPanel) => void;
}

export const DockPanel: React.FunctionComponent<DockPanelProps> = ({
items,
items = [],
layout,
layoutChanged = layout => { },
onDockPanelCreate
}) => {

Expand All @@ -169,9 +192,11 @@ export const DockPanel: React.FunctionComponent<DockPanelProps> = ({
}
});
setIdx(idx);
setTimeout(() => {
onDockPanelCreate(retVal);
}, 0);
if (onDockPanelCreate) {
setTimeout(() => {
onDockPanelCreate(retVal);
}, 0);
}
return retVal;
});

Expand All @@ -183,12 +208,6 @@ export const DockPanel: React.FunctionComponent<DockPanelProps> = ({
}
}, [dockPanel, layout]);

React.useEffect(() => {
return () => {
layoutChanged(dockPanel?.layout());
};
}, [dockPanel, layoutChanged]);

React.useEffect(() => {
items.filter(isDockPanelComponent).forEach(item => {
(idx[item.key] as ReactWidget)
Expand Down
24 changes: 11 additions & 13 deletions esp/src/src-react/layouts/HpccJSAdapter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,15 @@ export const HpccJSComponent: React.FunctionComponent<HpccJSComponentProps> = ({
}) => {
const divID = useId("viz-component-");

React.useEffect(() => {
const w = widget?.target(divID)
.render()
;
return () => {
w?.target(null);
};
}, [divID, widget]);
const setDivRef = React.useCallback(node => {
widget?.target(node);
if (node) {
widget?.render();
}
}, [widget]);

React.useEffect(() => {
if (widget.target()) {
if (widget?.target()) {
widget.resize({ width, height });
if (debounce) {
widget.lazyRender();
Expand All @@ -40,9 +38,9 @@ export const HpccJSComponent: React.FunctionComponent<HpccJSComponentProps> = ({
}
}, [debounce, height, widget, width]);

return (isNaN(width) || isNaN(height)) ?
return (isNaN(width) || isNaN(height) || width === 0 || height === 0) ?
<></> :
<div id={divID} className="hpcc-js-component" style={{ width, height }}>
<div ref={setDivRef} id={divID} className="hpcc-js-component" style={{ width, height }}>
</div>;
};

Expand All @@ -66,7 +64,7 @@ export const AutosizeHpccJSComponent: React.FunctionComponent<AutosizeHpccJSComp
return <SizeMe monitorHeight>{({ size }) => {
const width = size?.width || padding * 2;
const height = size?.height || padding * 2;
return <div style={{ width: "100%", height: hidden ? "0px" : fixedHeight, position: "relative" }}>
return <div style={{ width: "100%", height: hidden ? "1px" : fixedHeight, position: "relative" }}>
<div style={{ position: "absolute", padding: `${padding}px`, display: hidden ? "none" : "block" }}>
<HpccJSComponent widget={widget} debounce={debounce} width={width - padding * 2} height={height - padding * 2} />
</div>
Expand Down Expand Up @@ -98,7 +96,7 @@ export const AutosizeComponent: React.FunctionComponent<AutosizeComponentProps>
return <SizeMe monitorHeight>{({ size }) => {
const width = size?.width || padding * 2;
const height = size?.height || padding * 2;
return <div style={{ width: "100%", height: hidden ? "0px" : fixedHeight, position: "relative" }}>
return <div style={{ width: "100%", height: hidden ? "1px" : fixedHeight, position: "relative" }}>
<div style={{ position: "absolute", padding: `${padding}px`, display: hidden ? "none" : "block" }}>
<div style={{ width: width - padding * 2, height: height - padding * 2, display: "flex", alignItems: "center", justifyContent: "center" }} >
{children}
Expand Down
2 changes: 2 additions & 0 deletions esp/src/src/Timings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export class WUTimelinePatched extends WUTimeline {
.bucketHeight(22)
.gutter(4)
.overlapTolerence(-100)
.oddSeriesBackground("transparent")
.evenSeriesBackground("transparent")
;
this._gantt["_series_idx"] = -1;
this.strokeWidth(0);
Expand Down

0 comments on commit 99cfb53

Please sign in to comment.