Skip to content

Commit

Permalink
Merge pull request #18168 from GordonSmith/HPCC-31052-METRICS_LAYOUT_…
Browse files Browse the repository at this point in the history
…PERSIST

HPCC-31053 Metrics layout fails to persist on top level change
  • Loading branch information
GordonSmith authored Jan 3, 2024
2 parents 40d65bb + 71b8d11 commit ac50e39
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 49 deletions.
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 @@ -105,49 +105,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 @@ -167,9 +190,11 @@ export const DockPanel: React.FunctionComponent<DockPanelProps> = ({
}
});
setIdx(idx);
setTimeout(() => {
onDockPanelCreate(retVal);
}, 0);
if (onDockPanelCreate) {
setTimeout(() => {
onDockPanelCreate(retVal);
}, 0);
}
return retVal;
});

Expand All @@ -181,12 +206,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 ac50e39

Please sign in to comment.