Skip to content

Commit

Permalink
Merge pull request #19248 from GordonSmith/HPCC-32834-WU_FULLSCREEN_III
Browse files Browse the repository at this point in the history
HPCC-32834 Refactor WU Details fullscreen

Reviewed-By: Jeremy Clements <[email protected]>
Merged-by: Gavin Halliday <[email protected]>
  • Loading branch information
ghalliday authored Nov 11, 2024
2 parents 0087edc + 38756f0 commit 0732f57
Show file tree
Hide file tree
Showing 12 changed files with 426 additions and 216 deletions.
118 changes: 63 additions & 55 deletions esp/src/src-react/components/FileDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ 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 { pushUrl, replaceUrl } from "../util/history";
import { pushUrl, replaceUrl, updateFullscreen } from "../util/history";
import { FullscreenFrame, FullscreenStack } from "../layouts/Fullscreen";
import { FileParts } from "./FileParts";
import { FileBlooms } from "./FileBlooms";
import { FileHistory } from "./FileHistory";
import { ProtectedBy } from "./ProtectedBy";
Expand All @@ -28,6 +29,7 @@ interface FileDetailsProps {
cluster?: string;
logicalFile: string;
tab?: string;
fullscreen?: boolean;
sort?: { subfiles?: QuerySortItem, superfiles?: QuerySortItem, parts?: QuerySortItem, graphs?: QuerySortItem, history?: QuerySortItem, blooms?: QuerySortItem, protectby?: QuerySortItem };
queryParams?: { contents?: StringStringMap };
}
Expand All @@ -36,6 +38,7 @@ export const FileDetails: React.FunctionComponent<FileDetailsProps> = ({
cluster,
logicalFile,
tab = "summary",
fullscreen = false,
sort = {},
queryParams = {}
}) => {
Expand All @@ -50,7 +53,8 @@ export const FileDetails: React.FunctionComponent<FileDetailsProps> = ({

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

const tabs = React.useMemo((): TabInfo[] => {
return [{
Expand Down Expand Up @@ -103,56 +107,60 @@ export const FileDetails: React.FunctionComponent<FileDetailsProps> = ({
}];
}, [file]);

return <SizeMe monitorHeight>{({ size }) =>
<div style={{ height: "100%" }}>
<OverflowTabList tabs={tabs} selected={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} />
}
</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} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "ecl"} size={size}>
<SourceEditor text={file?.Ecl} mode="ecl" readonly={true} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "def"} size={size}>
<XMLSourceEditor text={defFile} readonly={true} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "xml"} size={size}>
<XMLSourceEditor text={xmlFile} readonly={true} />
</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 }} />
</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>;
return <FullscreenFrame fullscreen={fullscreen}>
<SizeMe monitorHeight>{({ size }) =>
<div style={{ height: "100%" }}>
<FullscreenStack fullscreen={fullscreen}>
<OverflowTabList tabs={tabs} selected={tab} onTabSelect={onTabSelect} size="medium" />
</FullscreenStack>
<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} />
}
</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} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "ecl"} size={size}>
<SourceEditor text={file?.Ecl} mode="ecl" readonly={true} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "def"} size={size}>
<XMLSourceEditor text={defFile} readonly={true} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "xml"} size={size}>
<XMLSourceEditor text={xmlFile} readonly={true} />
</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 }} />
</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>
</FullscreenFrame>;
};
7 changes: 6 additions & 1 deletion esp/src/src-react/components/Helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { HelperRow, useWorkunitHelpers } from "../hooks/workunit";
import { HolyGrail } from "../layouts/HolyGrail";
import { FluentGrid, useCopyButtons, useFluentStoreState, FluentColumns } from "./controls/Grid";
import { ShortVerticalDivider } from "./Common";
import { SearchParams } from "../util/hashUrl";
import { hashHistory } from "../util/history";

function canShowContent(type: string) {
switch (type) {
Expand Down Expand Up @@ -135,8 +137,11 @@ export const Helpers: React.FunctionComponent<HelpersProps> = ({
formatter: (Type, row) => {
const target = getTarget(row.id, row);
if (target) {
const searchParams = new SearchParams(hashHistory.location.search);
searchParams.param("mode", encodeURIComponent(target.sourceMode));
searchParams.param("src", encodeURIComponent(target.url));
const linkText = Type.replace("Slave", "Worker") + (row?.Description ? " (" + row.Description + ")" : "");
return <Link href={`#/workunits/${row?.workunit?.Wuid}/helpers/${row.Type}?mode=${encodeURIComponent(target.sourceMode)}&src=${encodeURIComponent(target.url)}`}>{linkText}</Link>;
return <Link href={`#/workunits/${row?.workunit?.Wuid}/helpers/${row.Type}?${searchParams.serialize()}`}>{linkText}</Link>;
}
return Type;
}
Expand Down
28 changes: 6 additions & 22 deletions esp/src/src-react/components/Metrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { HolyGrail } from "../layouts/HolyGrail";
import { AutosizeComponent, AutosizeHpccJSComponent } from "../layouts/HpccJSAdapter";
import { DockPanel, DockPanelItem, ResetableDockPanel } from "../layouts/DockPanel";
import { LayoutStatus, MetricGraph, MetricGraphWidget, isGraphvizWorkerResponse, layoutCache } from "../util/metricGraph";
import { pushUrl as _pushUrl } from "../util/history";
import { pushUrl } from "../util/history";
import { debounce } from "../util/throttle";
import { ErrorBoundary } from "../util/errorBoundary";
import { ShortVerticalDivider } from "./Common";
Expand Down Expand Up @@ -45,16 +45,14 @@ interface MetricsProps {
queryId?: string;
parentUrl?: string;
selection?: string;
fullscreen?: boolean;
}

export const Metrics: React.FunctionComponent<MetricsProps> = ({
wuid,
querySet = "",
queryId = "",
parentUrl = `/workunits/${wuid}/metrics`,
selection,
fullscreen = false
selection
}) => {
if (querySet && queryId) {
wuid = "";
Expand Down Expand Up @@ -100,20 +98,11 @@ export const Metrics: React.FunctionComponent<MetricsProps> = ({
}).catch(err => logger.error(err));
}, [wuid]);

const pushUrl = React.useCallback((selection?: string, fullscreen?: boolean) => {
const pushSelectionUrl = React.useCallback((selection: string) => {
const selectionStr = selection?.length ? `/${selection}` : "";
const fullscreenStr = fullscreen ? "?fullscreen" : "";
_pushUrl(`${parentUrl}${selectionStr}${fullscreenStr}`);
pushUrl(`${parentUrl}${selectionStr}`);
}, [parentUrl]);

const pushSelectionUrl = React.useCallback((selection: string) => {
pushUrl(selection, fullscreen);
}, [fullscreen, pushUrl]);

const pushFullscreenUrl = React.useCallback((fullscreen: boolean) => {
pushUrl(selection, fullscreen);
}, [pushUrl, selection]);

const onHotspot = React.useCallback(() => {
setSelectedMetricsSource("hotspot");
pushSelectionUrl(selection);
Expand Down Expand Up @@ -535,18 +524,13 @@ export const Metrics: React.FunctionComponent<MetricsProps> = ({
}]
}
},
{ key: "divider_2", itemType: ContextualMenuItemType.Divider, onRender: () => <ShortVerticalDivider /> },
{
key: "fullscreen", title: nlsHPCC.MaximizeRestore, iconProps: { iconName: fullscreen ? "ChromeRestore" : "FullScreen" },
onClick: () => pushFullscreenUrl(!fullscreen)
}
], [dot, formatColumns, fullscreen, metrics, pushFullscreenUrl, wuid]);
], [dot, formatColumns, metrics, wuid]);

const setShowMetricOptionsHook = React.useCallback((show: boolean) => {
setShowMetricOptions(show);
}, []);

return <HolyGrail fullscreen={fullscreen}
return <HolyGrail
header={<>
<CommandBar items={buttons} farItems={rightButtons} />
<AutosizeHpccJSComponent widget={timeline} fixedHeight={`${TIMELINE_FIXEDHEIGHT + 8}px`} padding={4} hidden={!view.showTimeline} />
Expand Down
76 changes: 42 additions & 34 deletions esp/src/src-react/components/QueryDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import * as React from "react";
import { SizeMe } from "react-sizeme";
import nlsHPCC from "src/nlsHPCC";
import * as ESPQuery from "src/ESPQuery";
import { pushUrl } from "../util/history";
import { pushUrl, updateFullscreen } from "../util/history";
import { FullscreenFrame, FullscreenStack } from "../layouts/Fullscreen";
import { QueryErrors } from "./QueryErrors";
import { QueryLibrariesUsed } from "./QueryLibrariesUsed";
import { QueryLogicalFiles } from "./QueryLogicalFiles";
Expand All @@ -18,6 +19,7 @@ interface QueryDetailsProps {
querySet: string;
queryId: string;
tab?: string;
fullscreen?: boolean;
state?: { metricsTab?: string, metricsState?: string, testTab?: string };
queryParams?: { metricsSelection?: string };
}
Expand All @@ -26,6 +28,7 @@ export const QueryDetails: React.FunctionComponent<QueryDetailsProps> = ({
querySet,
queryId,
tab = "summary",
fullscreen = false,
state = {},
queryParams = {}
}) => {
Expand Down Expand Up @@ -63,7 +66,8 @@ export const QueryDetails: React.FunctionComponent<QueryDetailsProps> = ({
pushUrl(tab.__state ?? `/queries/${querySet}/${queryId}/${tab.id}`);
break;
}
}, [queryId, querySet, state.testTab]);
updateFullscreen(fullscreen);
}, [fullscreen, queryId, querySet, state.testTab]);

const tabs = React.useMemo((): TabInfo[] => {
return [{
Expand Down Expand Up @@ -100,36 +104,40 @@ export const QueryDetails: React.FunctionComponent<QueryDetailsProps> = ({
}];
}, [libsUsedCount, logicalFileCount, superFileCount, wuid]);

return <SizeMe monitorHeight>{({ size }) =>
<div style={{ height: "100%" }}>
<OverflowTabList tabs={tabs} selected={tab} onTabSelect={onTabSelect} size="medium" />
<DelayLoadedPanel visible={tab === "summary"} size={size}>
<QuerySummary queryId={queryId} querySet={querySet} isSuspended={suspended} isActivated={activated} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "errors"} size={size}>
<QueryErrors queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "logicalFiles"} size={size}>
<QueryLogicalFiles queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "superfiles"} size={size}>
<QuerySuperFiles queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "librariesUsed"} size={size}>
<QueryLibrariesUsed queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "summaryStatistics"} size={size}>
<QuerySummaryStats queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "metrics"} size={size}>
<QueryMetrics wuid={query?.Wuid} queryId={queryId} querySet={querySet} tab={state.metricsTab} selection={queryParams.metricsSelection} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "resources"} size={size}>
<Resources wuid={wuid} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "testPages"} size={size}>
<QueryTests queryId={queryId} querySet={querySet} tab={state.testTab} />
</DelayLoadedPanel>
</div>
}</SizeMe>;
return <FullscreenFrame fullscreen={fullscreen}>
<SizeMe monitorHeight>{({ size }) =>
<div style={{ height: "100%" }}>
<FullscreenStack fullscreen={fullscreen}>
<OverflowTabList tabs={tabs} selected={tab} onTabSelect={onTabSelect} size="medium" />
</FullscreenStack>
<DelayLoadedPanel visible={tab === "summary"} size={size}>
<QuerySummary queryId={queryId} querySet={querySet} isSuspended={suspended} isActivated={activated} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "errors"} size={size}>
<QueryErrors queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "logicalFiles"} size={size}>
<QueryLogicalFiles queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "superfiles"} size={size}>
<QuerySuperFiles queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "librariesUsed"} size={size}>
<QueryLibrariesUsed queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "summaryStatistics"} size={size}>
<QuerySummaryStats queryId={queryId} querySet={querySet} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "metrics"} size={size}>
<QueryMetrics wuid={query?.Wuid} queryId={queryId} querySet={querySet} tab={state.metricsTab} selection={queryParams.metricsSelection} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "resources"} size={size}>
<Resources wuid={wuid} />
</DelayLoadedPanel>
<DelayLoadedPanel visible={tab === "testPages"} size={size}>
<QueryTests queryId={queryId} querySet={querySet} tab={state.testTab} />
</DelayLoadedPanel>
</div>
}</SizeMe>
</FullscreenFrame>;
};
Loading

0 comments on commit 0732f57

Please sign in to comment.