diff --git a/esp/src/src-react/components/FileDetails.tsx b/esp/src/src-react/components/FileDetails.tsx index 599339bc7da..c936e617142 100644 --- a/esp/src/src-react/components/FileDetails.tsx +++ b/esp/src/src-react/components/FileDetails.tsx @@ -41,10 +41,10 @@ export const FileDetails: React.FunctionComponent = ({ }) => { const [file] = useFile(cluster, logicalFile); React.useEffect(() => { - if (file?.NodeGroup && cluster === undefined) { + if (file?.NodeGroup && cluster === undefined && !file?.isSuperfile) { replaceUrl(`/files/${file.NodeGroup}/${logicalFile}`); } - }, [cluster, file?.NodeGroup, logicalFile]); + }, [cluster, file?.NodeGroup, file?.isSuperfile, logicalFile]); const [defFile] = useDefFile(cluster, logicalFile, WsDfu.DFUDefFileFormat.def); const [xmlFile] = useDefFile(cluster, logicalFile, WsDfu.DFUDefFileFormat.xml); diff --git a/esp/src/src-react/components/LogicalFileSummary.tsx b/esp/src/src-react/components/LogicalFileSummary.tsx index 469f2c57b83..a2551783357 100644 --- a/esp/src/src-react/components/LogicalFileSummary.tsx +++ b/esp/src/src-react/components/LogicalFileSummary.tsx @@ -181,7 +181,7 @@ export const LogicalFileSummary: React.FunctionComponent ({ label: "", type: "link", value: row.Name, href: `#/files/${row.Name}` })) }, + "SuperOwner": { label: nlsHPCC.SuperFile, type: "links", links: file?.Superfiles?.DFULogicalFile?.map(row => ({ label: "", type: "link", value: row.Name, href: `#/files/${row.NodeGroup !== null ? row.NodeGroup : undefined}/${row.Name}` })) }, "NodeGroup": { label: nlsHPCC.ClusterName, type: "string", value: file?.NodeGroup, readonly: true }, "Description": { label: nlsHPCC.Description, type: "string", value: description }, "JobName": { label: nlsHPCC.JobName, type: "string", value: file?.JobName, readonly: true }, diff --git a/esp/src/src-react/components/SubFiles.tsx b/esp/src/src-react/components/SubFiles.tsx index 7337454931f..b7e52a25965 100644 --- a/esp/src/src-react/components/SubFiles.tsx +++ b/esp/src/src-react/components/SubFiles.tsx @@ -5,10 +5,10 @@ import nlsHPCC from "src/nlsHPCC"; import { QuerySortItem } from "src/store/Store"; import * as WsDfu from "src/WsDfu"; import { useConfirm } from "../hooks/confirm"; -import { useFile } from "../hooks/file"; +import { useFile, useSubfiles } from "../hooks/file"; import { FluentGrid, useCopyButtons, useFluentStoreState, FluentColumns } from "./controls/Grid"; import { ShortVerticalDivider } from "./Common"; -import { pushUrl } from "../util/history"; +import { pushUrl, replaceUrl } from "../util/history"; const defaultUIState = { hasSelection: false, @@ -28,7 +28,8 @@ export const SubFiles: React.FunctionComponent = ({ sort = defaultSort }) => { - const [file, , , refresh] = useFile(cluster, logicalFile); + const [file] = useFile(cluster, logicalFile); + const [subfiles, refreshSubfiles] = useSubfiles(cluster, logicalFile); const [uiState, setUIState] = React.useState({ ...defaultUIState }); const [data, setData] = React.useState([]); const { @@ -101,26 +102,35 @@ export const SubFiles: React.FunctionComponent = ({ message: nlsHPCC.RemoveSubfiles2, items: selection.map(item => item.Name), onSubmit: React.useCallback(() => { - WsDfu.SuperfileAction("remove", file.Name, selection, false).then(() => refresh()); - }, [file, refresh, selection]) + WsDfu.SuperfileAction("remove", file.Name, selection, false).then(() => { + refreshSubfiles(); + if (file.subfiles.Item.length - 1 === 0) { + replaceUrl(`/files/${file.Name}`); + } + }); + }, [file, refreshSubfiles, selection]) }); React.useEffect(() => { - const subfiles = []; + const files = []; const promises = []; - file?.subfiles?.Item.forEach(item => { + subfiles?.Item.forEach(item => { const logicalFile = ESPLogicalFile.Get("", item); promises.push(logicalFile.getInfo2({ onAfterSend: function (response) { } })); - subfiles.push(logicalFile); - }); - Promise.all(promises).then(logicalFiles => { - setData(subfiles); + files.push(logicalFile); }); - }, [file?.subfiles]); + if (promises.length) { + Promise.all(promises).then(logicalFiles => { + setData(files); + }); + } else { + setData(files); + } + }, [file, subfiles]); const buttons = React.useMemo((): ICommandBarItemProps[] => [ { diff --git a/esp/src/src-react/components/SuperFiles.tsx b/esp/src/src-react/components/SuperFiles.tsx index b1cbe3bdd0b..392ea9d369d 100644 --- a/esp/src/src-react/components/SuperFiles.tsx +++ b/esp/src/src-react/components/SuperFiles.tsx @@ -43,7 +43,7 @@ export const SuperFiles: React.FunctionComponent = ({ label: nlsHPCC.Name, sortable: true, formatter: (name, row) => { - return {name}; + return {name}; } } }; diff --git a/esp/src/src-react/hooks/file.ts b/esp/src/src-react/hooks/file.ts index 7210998f5cf..7ea78a2cc70 100644 --- a/esp/src/src-react/hooks/file.ts +++ b/esp/src/src-react/hooks/file.ts @@ -14,7 +14,7 @@ export function useFile(cluster: string, name: string): [LogicalFile, boolean, n const [count, increment] = useCounter(); React.useEffect(() => { - const file = LogicalFile.attach({ baseUrl: "" }, cluster, name); + const file = LogicalFile.attach({ baseUrl: "" }, cluster === "undefined" ? undefined : cluster, name); let active = true; let handle; const fetchInfo = singletonDebounce(file, "fetchInfo"); @@ -87,3 +87,23 @@ export function useFileHistory(cluster: string, name: string): [WsDfu.Origin[], return [history, eraseHistory, increment]; } + +export function useSubfiles(cluster: string, name: string): [WsDfu.subfiles, () => void] { + + const [file] = useFile(cluster, name); + const [subfiles, setSubfiles] = React.useState({ Item: [] }); + const [count, increment] = useCounter(); + + React.useEffect(() => { + if (file) { + file.fetchInfo() + .then(response => { + setSubfiles(response.subfiles ?? { Item: [] }); + }) + .catch(err => logger.error(err)) + ; + } + }, [file, count]); + + return [subfiles, increment]; +}