Skip to content

Commit

Permalink
Merge pull request #18058 from GordonSmith/PERSIST_TABS
Browse files Browse the repository at this point in the history
HPCC-30553 Add persistent tabs to "details" pages

Reviewed-By: Jeremy Clements <jeremy.clements@lexisnexisrisk.com>
Merged-by: Gavin Halliday <ghalliday@hpccsystems.com>
  • Loading branch information
ghalliday authored Nov 23, 2023
2 parents 780b5e2 + ebc1e92 commit 59d94a5
Show file tree
Hide file tree
Showing 11 changed files with 463 additions and 150 deletions.
147 changes: 100 additions & 47 deletions esp/src/src-react/components/FileDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import * as React from "react";
import { Pivot, PivotItem } from "@fluentui/react";
import { WsDfu } from "@hpcc-js/comms";
import { SizeMe } from "react-sizeme";
import nlsHPCC from "src/nlsHPCC";
import { QuerySortItem } from "src/store/Store";
import { FileParts } from "./FileParts";
import { useFile, useDefFile } from "../hooks/file";
import { pivotItemStyle, usePivotItemDisable } from "../layouts/pivot";
import { pushUrl, replaceUrl } from "../util/history";
import { FileBlooms } from "./FileBlooms";
import { FileHistory } from "./FileHistory";
Expand All @@ -20,23 +18,25 @@ import { SuperFileSummary } from "./SuperFileSummary";
import { DataPatterns } from "./DataPatterns";
import { Result } from "./Result";
import { Queries } from "./Queries";
import { IndexFileSummary } from "./IndexFileSummary";
import { DelayLoadedPanel, OverflowTabList, TabInfo } from "./controls/TabbedPanes/index";

import "react-reflex/styles.css";
import { IndexFileSummary } from "./IndexFileSummary";

type StringStringMap = { [key: string]: string };
interface FileDetailsProps {
cluster?: string;
logicalFile: string;
tab?: string;
sort?: QuerySortItem;
queryParams?: { [key: string]: string };
sort?: { subfiles?: QuerySortItem, superfiles?: QuerySortItem, parts?: QuerySortItem, graphs?: QuerySortItem, history?: QuerySortItem, blooms?: QuerySortItem, protectby?: QuerySortItem };
queryParams?: { contents?: StringStringMap };
}

export const FileDetails: React.FunctionComponent<FileDetailsProps> = ({
cluster,
logicalFile,
tab = "summary",
sort,
sort = {},
queryParams = {}
}) => {
const [file] = useFile(cluster, logicalFile);
Expand All @@ -47,59 +47,112 @@ export const FileDetails: React.FunctionComponent<FileDetailsProps> = ({
}, [cluster, file?.NodeGroup, logicalFile]);
const [defFile] = useDefFile(cluster, logicalFile, WsDfu.DFUDefFileFormat.def);
const [xmlFile] = useDefFile(cluster, logicalFile, WsDfu.DFUDefFileFormat.xml);
const wuidDisable = usePivotItemDisable(file?.Wuid?.length && file?.Wuid[0] === "D");

const onTabSelect = React.useCallback((tab: TabInfo) => {
pushUrl(tab.__state ?? `/files/${cluster}/${logicalFile}/${tab.id}`);
}, [cluster, logicalFile]);

const tabs = React.useMemo((): TabInfo[] => {
return [{
id: "summary",
label: nlsHPCC.Summary,
}, {
id: "contents",
label: nlsHPCC.Contents,
}, {
id: "datapatterns",
label: nlsHPCC.DataPatterns,
}, {
id: "ecl",
label: nlsHPCC.ECL,
}, {
id: "def",
label: nlsHPCC.DEF,
}, {
id: "xml",
label: nlsHPCC.XML,
}, file?.isSuperfile ? {
id: "subfiles",
label: nlsHPCC.Subfiles,
count: file?.subfiles?.Item.length ?? 0
} : {
id: "superfiles",
label: nlsHPCC.Superfiles,
count: file?.Superfiles?.DFULogicalFile.length ?? 0
}, {
id: "parts",
label: nlsHPCC.FileParts,
count: file?.fileParts().length ?? 0
}, {
id: "queries",
label: nlsHPCC.Queries,
}, {
id: "graphs",
label: nlsHPCC.Graphs,
count: file?.Graphs?.ECLGraph?.length ?? 0
}, {
id: "history",
label: nlsHPCC.History
}, {
id: "blooms",
label: nlsHPCC.Blooms,
count: file?.Blooms?.DFUFileBloom?.length ?? 0
}, {
id: "protectby",
label: nlsHPCC.ProtectBy
}];
}, [file]);

return <SizeMe monitorHeight>{({ size }) =>
<Pivot overflowBehavior="menu" style={{ height: "100%" }} selectedKey={tab} onLinkClick={evt => pushUrl(`/files/${cluster}/${logicalFile}/${evt.props.itemKey}`)}>
<PivotItem headerText={nlsHPCC.Summary} itemKey="summary" style={pivotItemStyle(size)}>
<div style={{ height: "100%" }}>
<OverflowTabList tabs={tabs} selectedTab={tab} onTabSelect={onTabSelect} size="medium" />
<DelayLoadedPanel visible={tab === "summary"} size={size}>
{file?.ContentType === "key"
? <IndexFileSummary cluster={cluster} logicalFile={logicalFile} />
: file?.isSuperfile
? <SuperFileSummary cluster={cluster} logicalFile={logicalFile} />
: <LogicalFileSummary cluster={cluster} logicalFile={logicalFile} />
}
</PivotItem>
<PivotItem headerText={nlsHPCC.Contents} itemKey="contents" style={pivotItemStyle(size, 0)}>
<Result cluster={cluster} logicalFile={logicalFile} filter={queryParams} />
</PivotItem>
<PivotItem headerText={nlsHPCC.DataPatterns} itemKey="datapatterns" style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "contents"} size={size}>
<Result cluster={cluster} logicalFile={logicalFile} filter={queryParams.contents} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "datapatterns"} size={size}>
<DataPatterns cluster={cluster} logicalFile={logicalFile} />
</PivotItem>
<PivotItem headerText={nlsHPCC.ECL} itemKey="ecl" style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "ecl"} size={size}>
<SourceEditor text={file?.Ecl} mode="ecl" readonly={true} />
</PivotItem>
<PivotItem headerText={nlsHPCC.DEF} itemKey="def" style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "def"} size={size}>
<XMLSourceEditor text={defFile} readonly={true} />
</PivotItem>
<PivotItem headerText={nlsHPCC.XML} itemKey="xml" style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "xml"} size={size}>
<XMLSourceEditor text={xmlFile} readonly={true} />
</PivotItem>
{file?.isSuperfile
? <PivotItem headerText={nlsHPCC.Subfiles} itemKey="subfiles" itemCount={file?.subfiles?.Item.length ?? 0} style={pivotItemStyle(size, 0)}>
<SubFiles cluster={cluster} logicalFile={logicalFile} sort={sort} />
</PivotItem>
: <PivotItem headerText={nlsHPCC.Superfiles} itemKey="superfiles" itemCount={file?.Superfiles?.DFULogicalFile.length ?? 0} style={pivotItemStyle(size, 0)}>
<SuperFiles cluster={cluster} logicalFile={logicalFile} sort={sort} />
</PivotItem>
}
<PivotItem headerText={nlsHPCC.FileParts} itemKey="parts" itemCount={file?.fileParts().length ?? 0} style={pivotItemStyle(size, 0)}>
<FileParts cluster={cluster} logicalFile={logicalFile} sort={sort} />
</PivotItem>
<PivotItem headerText={nlsHPCC.Queries} itemKey="queries" style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "subfiles"} size={size}>
<SubFiles cluster={cluster} logicalFile={logicalFile} sort={sort.subfiles} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "superfiles"} size={size}>
<SuperFiles cluster={cluster} logicalFile={logicalFile} sort={sort.superfiles} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "parts"} size={size}>
<FileParts cluster={cluster} logicalFile={logicalFile} sort={sort.parts} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "queries"} size={size}>
<Queries filter={{ FileName: logicalFile }} />
</PivotItem>
<PivotItem headerText={nlsHPCC.Graphs} itemKey="graphs" itemCount={file?.Graphs?.ECLGraph?.length ?? 0} headerButtonProps={wuidDisable} style={pivotItemStyle(size, 0)}>
<FileDetailsGraph cluster={cluster} logicalFile={logicalFile} sort={sort} />
</PivotItem>
<PivotItem headerText={nlsHPCC.History} itemKey="history" style={pivotItemStyle(size, 0)}>
<FileHistory cluster={cluster} logicalFile={logicalFile} sort={sort} />
</PivotItem>
<PivotItem headerText={nlsHPCC.Blooms} itemKey="blooms" itemCount={file?.Blooms?.DFUFileBloom?.length} style={pivotItemStyle(size, 0)}>
<FileBlooms cluster={cluster} logicalFile={logicalFile} sort={sort} />
</PivotItem>
<PivotItem headerText={nlsHPCC.ProtectBy} itemKey="protectby" style={pivotItemStyle(size, 0)}>
<ProtectedBy cluster={cluster} logicalFile={logicalFile} sort={sort} />
</PivotItem>
</Pivot>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "graphs"} size={size}>
<FileDetailsGraph cluster={cluster} logicalFile={logicalFile} sort={sort.graphs} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "history"} size={size}>
<FileHistory cluster={cluster} logicalFile={logicalFile} sort={sort.history} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "blooms"} size={size}>
<FileBlooms cluster={cluster} logicalFile={logicalFile} sort={sort.blooms} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "protectby"} size={size}>
<ProtectedBy cluster={cluster} logicalFile={logicalFile} sort={sort.protectby} />
</DelayLoadedPanel>
</div>
}</SizeMe>;
};
113 changes: 73 additions & 40 deletions esp/src/src-react/components/QueryDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import * as React from "react";
import { Pivot, PivotItem } from "@fluentui/react";
import { SizeMe } from "react-sizeme";
import nlsHPCC from "src/nlsHPCC";
import * as ESPQuery from "src/ESPQuery";
import { pivotItemStyle, usePivotItemDisable } from "../layouts/pivot";
import { pushUrl } from "../util/history";
import { QueryErrors } from "./QueryErrors";
import { QueryLibrariesUsed } from "./QueryLibrariesUsed";
Expand All @@ -14,31 +12,31 @@ import { QuerySuperFiles } from "./QuerySuperFiles";
import { QueryTests } from "./QueryTests";
import { Resources } from "./Resources";
import { QueryMetrics } from "./QueryMetrics";
import { DelayLoadedPanel, OverflowTabList, TabInfo } from "./controls/TabbedPanes/index";

interface QueryDetailsProps {
querySet: string;
queryId: string;
tab?: string;
metricsTab?: string;
metricsState?: string;
testTab?: string;
state?: string;
}

export const QueryDetails: React.FunctionComponent<QueryDetailsProps> = ({
querySet,
queryId,
tab = "summary",
metricsTab,
testTab = "form",
state
metricsState,
testTab = "form"
}) => {

const [query, setQuery] = React.useState<any>();
const [wuid, setWuid] = React.useState<string>("");
const [logicalFileCount, setLogicalFileCount] = React.useState<number>(0);
const [superFileCount, setSuperFileCount] = React.useState<number>(0);
const [libsUsedCount, setLibsUsedCount] = React.useState<number>(0);
const wuidDisable = usePivotItemDisable(wuid === "");

React.useEffect(() => {
setQuery(ESPQuery.Get(querySet, queryId));
Expand All @@ -53,47 +51,82 @@ export const QueryDetails: React.FunctionComponent<QueryDetailsProps> = ({
});
}, [query, setLogicalFileCount, setSuperFileCount, setLibsUsedCount]);

const onTabSelect = React.useCallback((tab: TabInfo) => {
switch (tab.id) {
case "testPages":
pushUrl(tab.__state ?? `/queries/${querySet}/${queryId}/testPages/${testTab}`);
break;
default:
pushUrl(tab.__state ?? `/queries/${querySet}/${queryId}/${tab.id}`);
break;
}
}, [queryId, querySet, testTab]);

const tabs = React.useMemo((): TabInfo[] => {
return [{
id: "summary",
label: nlsHPCC.Summary,
}, {
id: "errors",
label: nlsHPCC.Errors,
}, {
id: "logicalFiles",
label: nlsHPCC.LogicalFiles,
count: logicalFileCount
}, {
id: "superfiles",
label: nlsHPCC.SuperFiles,
count: superFileCount
}, {
id: "librariesUsed",
label: nlsHPCC.LibrariesUsed,
count: libsUsedCount
}, {
id: "summaryStatistics",
label: nlsHPCC.SummaryStatistics,
}, {
id: "metrics",
label: nlsHPCC.Metrics,
}, {
id: "resources",
label: nlsHPCC.Resources,
disabled: wuid === ""
}, {
id: "testPages",
label: nlsHPCC.TestPages,
}];
}, [libsUsedCount, logicalFileCount, superFileCount, wuid]);

return <SizeMe monitorHeight>{({ size }) =>
<Pivot
overflowBehavior="menu" style={{ height: "100%" }} selectedKey={tab}
onLinkClick={evt => {
switch (evt.props.itemKey) {
case "testPages":
pushUrl(`/queries/${querySet}/${queryId}/testPages/${testTab}`);
break;
default:
pushUrl(`/queries/${querySet}/${queryId}/${evt.props.itemKey}`);
break;
}
}}
>
<PivotItem headerText={queryId} itemKey="summary" style={pivotItemStyle(size)} >
<div style={{ height: "100%" }}>
<OverflowTabList tabs={tabs} selectedTab={tab} onTabSelect={onTabSelect} size="medium" />
<DelayLoadedPanel visible={tab === "summary"} size={size}>
<QuerySummary queryId={queryId} querySet={querySet} />
</PivotItem>
<PivotItem headerText={nlsHPCC.Errors} itemKey="errors" style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "errors"} size={size}>
<QueryErrors queryId={queryId} querySet={querySet} />
</PivotItem>
<PivotItem headerText={nlsHPCC.LogicalFiles} itemKey="logicalFiles" itemCount={logicalFileCount} style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "logicalFiles"} size={size}>
<QueryLogicalFiles queryId={queryId} querySet={querySet} />
</PivotItem>
<PivotItem headerText={nlsHPCC.SuperFiles} itemKey="superfiles" itemCount={superFileCount} style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "superfiles"} size={size}>
<QuerySuperFiles queryId={queryId} querySet={querySet} />
</PivotItem>
<PivotItem headerText={nlsHPCC.LibrariesUsed} itemKey="librariesUsed" itemCount={libsUsedCount} style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "librariesUsed"} size={size}>
<QueryLibrariesUsed queryId={queryId} querySet={querySet} />
</PivotItem>
<PivotItem headerText={nlsHPCC.SummaryStatistics} itemKey="summaryStatistics" style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "summaryStatistics"} size={size}>
<QuerySummaryStats queryId={queryId} querySet={querySet} />
</PivotItem>
<PivotItem headerText={nlsHPCC.Metrics} itemKey="metrics" style={pivotItemStyle(size, 0)}>
<QueryMetrics wuid={query?.Wuid} queryId={queryId} querySet={querySet} tab={metricsTab} selection={state} />
</PivotItem>
<PivotItem headerText={nlsHPCC.Resources} itemKey="resources" headerButtonProps={wuidDisable} style={pivotItemStyle(size, 0)}>
{wuid && <Resources wuid={wuid} />}
</PivotItem>
<PivotItem headerText={nlsHPCC.TestPages} itemKey="testPages" style={pivotItemStyle(size, 0)}>
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "metrics"} size={size}>
<QueryMetrics wuid={query?.Wuid} queryId={queryId} querySet={querySet} tab={metricsTab} selection={metricsState} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "resources"} size={size}>
<Resources wuid={wuid} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "testPages"} size={size}>
<QueryTests queryId={queryId} querySet={querySet} tab={testTab} />
</PivotItem>
</Pivot>
</DelayLoadedPanel>
</div>
}</SizeMe>;
};
Loading

0 comments on commit 59d94a5

Please sign in to comment.