diff --git a/esp/src/src-react/components/FileDetails.tsx b/esp/src/src-react/components/FileDetails.tsx index cad9f801cc4..4111fe870f6 100644 --- a/esp/src/src-react/components/FileDetails.tsx +++ b/esp/src/src-react/components/FileDetails.tsx @@ -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"; @@ -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 = ({ cluster, logicalFile, tab = "summary", - sort, + sort = {}, queryParams = {} }) => { const [file] = useFile(cluster, logicalFile); @@ -47,59 +47,112 @@ export const FileDetails: React.FunctionComponent = ({ }, [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 {({ size }) => - pushUrl(`/files/${cluster}/${logicalFile}/${evt.props.itemKey}`)}> - +
+ + {file?.ContentType === "key" ? : file?.isSuperfile ? : } - - - - - + + + + + - - + + - - + + - - + + - - {file?.isSuperfile - ? - - - : - - - } - - - - + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + +
}
; }; diff --git a/esp/src/src-react/components/QueryDetails.tsx b/esp/src/src-react/components/QueryDetails.tsx index 35ecd7b259a..92a58a014c6 100644 --- a/esp/src/src-react/components/QueryDetails.tsx +++ b/esp/src/src-react/components/QueryDetails.tsx @@ -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"; @@ -14,14 +12,15 @@ 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 = ({ @@ -29,8 +28,8 @@ export const QueryDetails: React.FunctionComponent = ({ queryId, tab = "summary", metricsTab, - testTab = "form", - state + metricsState, + testTab = "form" }) => { const [query, setQuery] = React.useState(); @@ -38,7 +37,6 @@ export const QueryDetails: React.FunctionComponent = ({ const [logicalFileCount, setLogicalFileCount] = React.useState(0); const [superFileCount, setSuperFileCount] = React.useState(0); const [libsUsedCount, setLibsUsedCount] = React.useState(0); - const wuidDisable = usePivotItemDisable(wuid === ""); React.useEffect(() => { setQuery(ESPQuery.Get(querySet, queryId)); @@ -53,47 +51,82 @@ export const QueryDetails: React.FunctionComponent = ({ }); }, [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 {({ size }) => - { - switch (evt.props.itemKey) { - case "testPages": - pushUrl(`/queries/${querySet}/${queryId}/testPages/${testTab}`); - break; - default: - pushUrl(`/queries/${querySet}/${queryId}/${evt.props.itemKey}`); - break; - } - }} - > - +
+ + - - + + - - + + - - + + - - + + - - + + - - - - - - {wuid && } - - + + + + + + + + - - + +
}
; }; diff --git a/esp/src/src-react/components/WorkunitDetails.tsx b/esp/src/src-react/components/WorkunitDetails.tsx index 3ae985ed24c..66d016c479b 100644 --- a/esp/src/src-react/components/WorkunitDetails.tsx +++ b/esp/src/src-react/components/WorkunitDetails.tsx @@ -1,14 +1,12 @@ import * as React from "react"; -import { IPivotItemProps, Pivot, PivotItem } from "@fluentui/react"; +import { Icon } from "@fluentui/react"; import { scopedLogger } from "@hpcc-js/util"; import { SizeMe } from "react-sizeme"; import nlsHPCC from "src/nlsHPCC"; import { hasLogAccess } from "src/ESPLog"; import { useWorkunit } from "../hooks/workunit"; -import { useUserTheme } from "../hooks/theme"; import { useDeepEffect } from "../hooks/deepHooks"; import { DojoAdapter } from "../layouts/DojoAdapter"; -import { pivotItemStyle } from "../layouts/pivot"; import { pushUrl } from "../util/history"; import { WorkunitPersona } from "./controls/StateIcon"; import { Helpers } from "./Helpers"; @@ -24,14 +22,16 @@ import { SourceFiles } from "./SourceFiles"; import { Variables } from "./Variables"; import { Workflows } from "./Workflows"; import { WorkunitSummary } from "./WorkunitSummary"; +import { TabInfo, DelayLoadedPanel, OverflowTabList } from "./controls/TabbedPanes/index"; const logger = scopedLogger("src-react/components/WorkunitDetails.tsx"); +type StringStringMap = { [key: string]: string }; interface WorkunitDetailsProps { wuid: string; tab?: string; - state?: string; - queryParams?: { [key: string]: string }; + state?: { outputs?: string, metrics?: string, resources?: string, helpers?: string }; + queryParams?: { outputs?: StringStringMap, inputs?: StringStringMap, resources?: StringStringMap, helpers?: StringStringMap, logs?: StringStringMap }; } export const WorkunitDetails: React.FunctionComponent = ({ @@ -41,22 +41,7 @@ export const WorkunitDetails: React.FunctionComponent = ({ queryParams = {} }) => { - const { themeV9 } = useUserTheme(); const [workunit] = useWorkunit(wuid, true); - - const wuidPivotRenderer = React.useMemo(() => { - return function (link?: IPivotItemProps, - defaultRenderer?: (link?: IPivotItemProps) => JSX.Element | null) { - if (!link || !defaultRenderer) return null; - return - - {defaultRenderer({ ...link, itemIcon: undefined })} - ; - }; - }, [wuid]); - - const resourceCount = workunit?.ResourceURLCount > 1 ? workunit?.ResourceURLCount - 1 : undefined; - const [logCount, setLogCount] = React.useState("*"); const [logsDisabled, setLogsDisabled] = React.useState(true); @@ -70,55 +55,111 @@ export const WorkunitDetails: React.FunctionComponent = ({ }); }, [wuid], [queryParams]); + const onTabSelect = React.useCallback((tab: TabInfo) => { + pushUrl(tab.__state ?? `/workunits/${wuid}/${tab.id}`); + }, [wuid]); + + const tabs = React.useMemo((): TabInfo[] => { + return [{ + id: "summary", + icon: , + label: wuid + }, { + id: "variables", + label: nlsHPCC.Variables, + count: (workunit?.VariableCount || 0) + (workunit?.ApplicationValueCount || 0) + (workunit?.DebugValueCount || 0) + }, { + id: "outputs", + label: nlsHPCC.Outputs, + count: workunit?.ResultCount + }, { + id: "inputs", + label: nlsHPCC.Inputs, + count: workunit?.SourceFileCount + }, { + id: "metrics", + label: nlsHPCC.Metrics, + count: workunit?.GraphCount + }, { + id: "workflows", + label: nlsHPCC.Workflows, + count: workunit?.WorkflowCount + }, { + id: "queries", + icon: , + label: nlsHPCC.Queries + }, { + id: "resources", + label: nlsHPCC.Resources, + count: workunit?.ResourceURLCount + }, { + id: "helpers", + label: nlsHPCC.Helpers, + count: workunit?.HelpersCount + }, { + id: "logs", + label: nlsHPCC.Logs, + count: logCount, + disabled: logsDisabled + }, { + id: "eclsummary", + label: nlsHPCC.ECL + }, { + id: "xml", + label: nlsHPCC.XML + }]; + }, [logCount, logsDisabled, workunit?.ApplicationValueCount, workunit?.DebugValueCount, workunit?.GraphCount, workunit?.HelpersCount, workunit?.ResourceURLCount, workunit?.ResultCount, workunit?.SourceFileCount, workunit?.VariableCount, workunit?.WorkflowCount, wuid]); + return {({ size }) => - pushUrl(`/workunits/${wuid}/${evt.props.itemKey}`)}> - +
+ + - - + + - - - {state ? - queryParams.hasOwnProperty("__legacy") ?