Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HPCC-30553 Add persistent tabs to "details" pages #18058

Merged
merged 1 commit into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading