+
diff --git a/esp/src/src-react/components/InfoGrid.tsx b/esp/src/src-react/components/InfoGrid.tsx
index 160a0dc0271..da3a212ba8b 100644
--- a/esp/src/src-react/components/InfoGrid.tsx
+++ b/esp/src/src-react/components/InfoGrid.tsx
@@ -5,7 +5,6 @@ import { formatCost, formatTwoDigits } from "src/Session";
import nlsHPCC from "src/nlsHPCC";
import { useWorkunitExceptions } from "../hooks/workunit";
import { FluentGrid, useCopyButtons, useFluentStoreState, FluentColumns } from "./controls/Grid";
-import { pivotItemStyle } from "../layouts/pivot";
function extractGraphInfo(msg) {
const regex = /^([a-zA-Z0-9 :]+: )(graph graph(\d+)\[(\d+)\], )(([a-zA-Z]+)\[(\d+)\]: )?(.*)$/gmi;
@@ -237,23 +236,19 @@ export const InfoGrid: React.FunctionComponent
= ({
}
}, [data.length]);
- return
+ return
{({ size }) =>
-
-
- { }}
- setTotal={setTotal}
- refresh={refreshTable}
- height={`${size.height - (44 + 8 + 45 + 12)}px`}
- selectionMode={SelectionMode.none}
- >
-
-
+ { }}
+ setTotal={setTotal}
+ refresh={refreshTable}
+ height={`${size.height - (44 + 8 + 45 + 12)}px`}
+ selectionMode={SelectionMode.none}
+ >
}
;
};
diff --git a/esp/src/src-react/components/LogViewer.tsx b/esp/src/src-react/components/LogViewer.tsx
index 82e027a55b4..2e44c369051 100644
--- a/esp/src/src-react/components/LogViewer.tsx
+++ b/esp/src/src-react/components/LogViewer.tsx
@@ -102,13 +102,16 @@ export const LogViewer: React.FunctionComponent
= ({
return }
main={
- }
+
+
+
+ }
/>;
};
diff --git a/esp/src/src-react/components/Menu.tsx b/esp/src/src-react/components/Menu.tsx
index 7f291c40944..ea6b9601d00 100644
--- a/esp/src/src-react/components/Menu.tsx
+++ b/esp/src/src-react/components/Menu.tsx
@@ -4,6 +4,7 @@ import { useConst } from "@fluentui/react-hooks";
import nlsHPCC from "src/nlsHPCC";
import { hasLogAccess } from "src/ESPLog";
import { containerized, bare_metal } from "src/BuildInfo";
+import { navCategory } from "../util/history";
import { MainNav, routes } from "../routes";
import { useFavorite, useFavorites, useHistory } from "../hooks/favorite";
import { useSessionStore } from "../hooks/store";
@@ -98,7 +99,7 @@ routes.forEach((route: any) => {
});
function navSelectedKey(hashPath) {
- const rootPath = navIdx(`/${hashPath?.split("/")[1]}`);
+ const rootPath = navIdx(`/${navCategory(hashPath)?.split("/")[1]}`);
if (rootPath?.length) {
return rootPath[0];
}
@@ -164,7 +165,7 @@ const subMenuItems: SubMenuItems = {
"files": [
{ headerText: nlsHPCC.LogicalFiles, itemKey: "/files" },
{ headerText: nlsHPCC.LandingZones, itemKey: "/landingzone" },
- { headerText: nlsHPCC.Workunits, itemKey: "/dfuworkunits" },
+ { headerText: nlsHPCC.title_GetDFUWorkunits, itemKey: "/dfuworkunits" },
{ headerText: nlsHPCC.XRef + " (L)", itemKey: "/xref" },
],
"queries": [
@@ -215,8 +216,8 @@ for (const key in subMenuItems) {
}
function subNavSelectedKey(hashPath) {
- const hashCategory = hashPath.split("/").slice(0, 3).join("/");
- return subNavIdx(hashCategory).length ? hashCategory : null;
+ const category = navCategory(hashPath);
+ return subNavIdx(category).length ? category : null;
}
interface SubNavigationProps {
diff --git a/esp/src/src-react/components/SourceFiles.tsx b/esp/src/src-react/components/SourceFiles.tsx
index ed1e083edfb..cda748e8845 100644
--- a/esp/src/src-react/components/SourceFiles.tsx
+++ b/esp/src/src-react/components/SourceFiles.tsx
@@ -25,7 +25,7 @@ interface SourceFilesProps {
}
const emptyFilter: { [id: string]: any } = {};
-const defaultSort = { attribute: "Name", descending: false };
+const defaultSort = { attribute: undefined, descending: false };
export const SourceFiles: React.FunctionComponent = ({
wuid,
@@ -52,7 +52,7 @@ export const SourceFiles: React.FunctionComponent = ({
selectorType: "checkbox"
},
Name: {
- label: "Name", sortable: true,
+ label: "Name", width: 400, sortable: true,
formatter: (Name, row) => {
let fileUrl = `#/files/${Name}`;
if (row?.FileCluster) {
@@ -65,11 +65,8 @@ export const SourceFiles: React.FunctionComponent = ({
>;
}
},
- FileCluster: { label: nlsHPCC.FileCluster, width: 300, sortable: false },
- Count: {
- label: nlsHPCC.Usage, width: 72, sortable: true,
- justify: "right"
- }
+ FileCluster: { label: nlsHPCC.FileCluster, width: 200, sortable: false },
+ Count: { label: nlsHPCC.Usage, width: 72, sortable: true, justify: "right" }
};
}, []);
diff --git a/esp/src/src-react/components/controls/Grid.tsx b/esp/src/src-react/components/controls/Grid.tsx
index 770b5b759ba..129271d47b3 100644
--- a/esp/src/src-react/components/controls/Grid.tsx
+++ b/esp/src/src-react/components/controls/Grid.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DetailsList, DetailsListLayoutMode, Dropdown, IColumn as _IColumn, ICommandBarItemProps, IDetailsHeaderProps, IDetailsListStyles, mergeStyleSets, Selection, Stack, TooltipHost, TooltipOverflowMode, IRenderFunction, IDetailsRowProps, SelectionMode, ConstrainMode, ISelection } from "@fluentui/react";
+import { DetailsList, DetailsListLayoutMode, Dropdown, IColumn as _IColumn, ICommandBarItemProps, IDetailsHeaderProps, IDetailsListStyles, mergeStyleSets, Selection, Stack, TooltipHost, TooltipOverflowMode, IRenderFunction, IDetailsRowProps, SelectionMode, ConstrainMode, ISelection, ScrollablePane, Sticky } from "@fluentui/react";
import { Pagination } from "@fluentui/react-experiments/lib/Pagination";
import { useConst } from "@fluentui/react-hooks";
import { BaseStore, Memory, QueryRequest, QuerySortItem } from "src/store/Memory";
@@ -293,45 +293,22 @@ const FluentStoreGrid: React.FunctionComponent = ({
}, [memoizedColumns]);
const renderDetailsHeader = React.useCallback((props: IDetailsHeaderProps, defaultRender?: any) => {
- return defaultRender({
- ...props,
- onRenderColumnHeaderTooltip: (tooltipHostProps) => {
- return ;
- },
- styles: { root: { paddingTop: 1 } }
- });
+ return
+ {defaultRender({
+ ...props,
+ onRenderColumnHeaderTooltip: (tooltipHostProps) => {
+ return ;
+ },
+ styles: { root: { paddingTop: 1 } }
+ })}
+ ;
}, []);
const columnResize = React.useCallback((column: IColumn, newWidth: number, columnIndex?: number) => {
columnWidths.set(column.key, newWidth);
}, [columnWidths]);
- /* Monitor Scroll Events (hack)
-
- Essentially we are setting the scrollElement of the DetailsList to the div that contains the DetailsList (rather than a scrollable pane host).
- See: https://github.com/microsoft/fluentui/blob/55d3a31042e8972ea373841bef616c68e6ab69f9/packages/react/src/components/List/List.tsx#L355-L369
-
- Note: Not sure if `_onScroll` call is needed, but excluding for now as it seems to work without it and is more performant.
- */
- // const id = useId("fluent-store-grid-");
- // const detailListScrollComponent = React.useRef(null);
- // const detailListComponent = React.useRef(null);
- // const [detailListElement, setDetailListElement] = React.useState(null);
- // useMount(() => {
- // const detailListElement = document.querySelector(`#${id} .ms-DetailsList`);
- // setDetailListElement(detailListElement);
- // if (detailListComponent.current?._list?.current) {
- // detailListComponent.current._list.current._scrollElement = detailListElement;
- // }
- // });
- // useOnEvent(detailListScrollComponent, "scroll", () => {
- // detailListComponent.current?._list?.current?._onScroll();
- // });
- // useOnEvent(detailListScrollComponent, "scroll", () => {
- // detailListComponent.current?._list?.current?._onAsyncScrollDebounced();
- // });
-
- return
+ return
= ({
styles={gridStyles(height)}
selectionMode={selectionMode}
/>
-
;
+ ;
};
interface FluentGridProps {
diff --git a/esp/src/src-react/components/forms/AddBinding.tsx b/esp/src/src-react/components/forms/AddBinding.tsx
index 33df4fa0127..abc26d8d4c9 100644
--- a/esp/src/src-react/components/forms/AddBinding.tsx
+++ b/esp/src/src-react/components/forms/AddBinding.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DefaultButton, IDropdownOption, PrimaryButton, TextField, } from "@fluentui/react";
+import { DefaultButton, IDropdownOption, PrimaryButton, Spinner, TextField, } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import { EsdlDefinitionsTextField, EsdlEspProcessesTextField } from "./Fields";
@@ -39,6 +39,8 @@ export const AddBindingForm: React.FunctionComponent = ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -47,11 +49,16 @@ export const AddBindingForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
+
const request: any = data;
request.Overwrite = true;
WsESDLConfig.PublishESDLBinding({ request: request })
.then(() => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
if (refreshGrid) refreshGrid();
@@ -66,7 +73,8 @@ export const AddBindingForm: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
= ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -41,10 +43,14 @@ export const AddGroupForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request: any = data;
WsAccess.GroupAdd({ request: request })
.then(() => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
if (refreshGrid) refreshGrid();
@@ -58,7 +64,8 @@ export const AddGroupForm: React.FunctionComponent = ({
return
-
+
+
{ reset(defaultValues); closeForm(); }} />
>}>
{
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -51,6 +53,8 @@ export const AddGroupResourceForm: React.FunctionComponent {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request: any = data;
request["action"] = "update";
@@ -60,6 +64,8 @@ export const AddGroupResourceForm: React.FunctionComponent {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
if (refreshGrid) refreshGrid();
@@ -73,7 +79,8 @@ export const AddGroupResourceForm: React.FunctionComponent
-
+
+
{ reset(defaultValues); closeForm(); }} />
>}>
= ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const [remoteTargets, setRemoteTargets] = React.useState([]);
@@ -67,15 +69,21 @@ export const AddPackageMap: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
WsPackageMaps.AddPackage({
request: data
})
.then(({ AddPackageResponse, Exceptions }) => {
if (AddPackageResponse?.status?.Code === 0) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
refreshData(true);
reset(defaultValues);
} else if (Exceptions) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
logger.error(Exceptions.Exception[0].Message);
}
@@ -99,7 +107,8 @@ export const AddPackageMap: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/AddPackageMapPart.tsx b/esp/src/src-react/components/forms/AddPackageMapPart.tsx
index cae4d80a7c1..23193c02259 100644
--- a/esp/src/src-react/components/forms/AddPackageMapPart.tsx
+++ b/esp/src/src-react/components/forms/AddPackageMapPart.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, DefaultButton, PrimaryButton, Stack, TextField, } from "@fluentui/react";
+import { Checkbox, DefaultButton, PrimaryButton, Spinner, Stack, TextField, } from "@fluentui/react";
import { useForm, Controller } from "react-hook-form";
import { scopedLogger } from "@hpcc-js/util";
import * as WsPackageMaps from "src/WsPackageMaps";
@@ -50,6 +50,8 @@ export const AddPackageMapPart: React.FunctionComponent
refreshData,
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -58,15 +60,21 @@ export const AddPackageMapPart: React.FunctionComponent
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
WsPackageMaps.AddPartToPackageMap({
request: { ...data, Target: target, PackageMap: packageMap }
})
.then(({ AddPartToPackageMapResponse, Exceptions }) => {
if (AddPartToPackageMapResponse?.status?.Code === 0) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
if (refreshData) refreshData();
reset(defaultValues);
} else if (Exceptions) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
logger.error(Exceptions.Exception[0].Message);
}
@@ -82,7 +90,8 @@ export const AddPackageMapPart: React.FunctionComponent
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/AddPermission.tsx b/esp/src/src-react/components/forms/AddPermission.tsx
index 5b44b6eb7e2..40a31d8a604 100644
--- a/esp/src/src-react/components/forms/AddPermission.tsx
+++ b/esp/src/src-react/components/forms/AddPermission.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DefaultButton, IDropdownOption, MessageBar, MessageBarType, PrimaryButton, TextField, } from "@fluentui/react";
+import { DefaultButton, IDropdownOption, MessageBar, MessageBarType, PrimaryButton, Spinner, TextField, } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import nlsHPCC from "src/nlsHPCC";
@@ -34,6 +34,8 @@ export const AddPermissionForm: React.FunctionComponent
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const [showError, setShowError] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState("");
@@ -45,6 +47,8 @@ export const AddPermissionForm: React.FunctionComponent
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request: any = data;
WsAccess.ResourceAdd({ request: request })
@@ -52,9 +56,13 @@ export const AddPermissionForm: React.FunctionComponent
if (ResourceAddResponse?.retcode < 0) {
//log exception from API
setShowError(true);
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
setErrorMessage(ResourceAddResponse?.retmsg);
logger.error(ResourceAddResponse?.retmsg);
} else {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
if (refreshGrid) refreshGrid();
@@ -69,7 +77,8 @@ export const AddPermissionForm: React.FunctionComponent
return
-
+
+
{ reset(defaultValues); closeForm(); }} />
>}>
= ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -56,8 +58,12 @@ export const AddToSuperfile: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
WsDfu.AddtoSuperfile(data.names, data.superFile, data.existingFile)
.then(response => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
if (refreshGrid) refreshGrid(true);
})
@@ -83,7 +89,8 @@ export const AddToSuperfile: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/AddUser.tsx b/esp/src/src-react/components/forms/AddUser.tsx
index b74977e1403..377025fdabd 100644
--- a/esp/src/src-react/components/forms/AddUser.tsx
+++ b/esp/src/src-react/components/forms/AddUser.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DefaultButton, MessageBar, MessageBarType, PrimaryButton, TextField, } from "@fluentui/react";
+import { DefaultButton, MessageBar, MessageBarType, PrimaryButton, Spinner, TextField, } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import nlsHPCC from "src/nlsHPCC";
@@ -41,6 +41,8 @@ export const AddUserForm: React.FunctionComponent = ({
}) => {
const { handleSubmit, control, reset, watch } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const pwd1 = watch("password1");
@@ -54,6 +56,8 @@ export const AddUserForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request: any = data;
WsAccess.AddUser({ request: request })
@@ -61,9 +65,13 @@ export const AddUserForm: React.FunctionComponent = ({
if (AddUserResponse?.retcode < 0) {
//log exception from API
setShowError(true);
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
setErrorMessage(AddUserResponse?.retmsg);
logger.error(AddUserResponse?.retmsg);
} else {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
if (refreshGrid) refreshGrid();
@@ -78,7 +86,8 @@ export const AddUserForm: React.FunctionComponent = ({
return
-
+
+
{ reset(defaultValues); closeForm(); }} />
>}>
= ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -64,10 +66,14 @@ export const CopyFile: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
if (logicalFiles.length > 0) {
if (logicalFiles.length === 1) {
const request = { ...data, sourceLogicalName: logicalFiles[0] };
FileSpray.Copy({ request: request }).then(response => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
pushUrl(`/dfuworkunits/${response.CopyResponse.result}`);
});
@@ -77,6 +83,8 @@ export const CopyFile: React.FunctionComponent = ({
const requests = [];
requests.push(FileSpray.Copy({ request: request }));
Promise.all(requests).then(_ => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
if (refreshGrid) refreshGrid();
});
@@ -115,7 +123,8 @@ export const CopyFile: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/DesprayFile.tsx b/esp/src/src-react/components/forms/DesprayFile.tsx
index b57a171d0d1..ee70122c138 100644
--- a/esp/src/src-react/components/forms/DesprayFile.tsx
+++ b/esp/src/src-react/components/forms/DesprayFile.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, DefaultButton, IDropdownOption, mergeStyleSets, PrimaryButton, Stack, TextField, } from "@fluentui/react";
+import { Checkbox, DefaultButton, IDropdownOption, mergeStyleSets, PrimaryButton, Spinner, Stack, TextField, } from "@fluentui/react";
import { useForm, Controller } from "react-hook-form";
import { FileSpray, FileSprayService } from "@hpcc-js/comms";
import { scopedLogger } from "@hpcc-js/util";
@@ -67,6 +67,8 @@ export const DesprayFile: React.FunctionComponent = ({
const [os, setOs] = React.useState();
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -75,6 +77,8 @@ export const DesprayFile: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
if (logicalFiles.length > 0) {
if (logicalFiles.length === 1) {
const request = {
@@ -84,6 +88,8 @@ export const DesprayFile: React.FunctionComponent = ({
sourceLogicalName: logicalFiles[0]
} as FileSpray.Despray;
myFileSprayService.Despray(request).then(response => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
if (refreshGrid) refreshGrid(true);
@@ -99,6 +105,8 @@ export const DesprayFile: React.FunctionComponent = ({
requests.push(myFileSprayService.Despray(request));
});
Promise.all(requests).then(_ => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
if (refreshGrid) refreshGrid(true);
}).catch(err => logger.error(err));
@@ -136,7 +144,8 @@ export const DesprayFile: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/GroupAddUser.tsx b/esp/src/src-react/components/forms/GroupAddUser.tsx
index c8f1cef78b9..518231f1d17 100644
--- a/esp/src/src-react/components/forms/GroupAddUser.tsx
+++ b/esp/src/src-react/components/forms/GroupAddUser.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DefaultButton, IDropdownOption, MessageBar, MessageBarType, PrimaryButton, } from "@fluentui/react";
+import { DefaultButton, IDropdownOption, MessageBar, MessageBarType, PrimaryButton, Spinner, } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import nlsHPCC from "src/nlsHPCC";
@@ -32,6 +32,8 @@ export const GroupAddUserForm: React.FunctionComponent = ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const [showError, setShowError] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState("");
@@ -43,6 +45,8 @@ export const GroupAddUserForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request: any = data;
request.groupname = groupname;
request.action = "add";
@@ -52,9 +56,13 @@ export const GroupAddUserForm: React.FunctionComponent = ({
if (GroupMemberEditResponse?.retcode < 0) {
//log exception from API
setShowError(true);
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
setErrorMessage(GroupMemberEditResponse?.retmsg);
logger.error(GroupMemberEditResponse?.retmsg);
} else {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
if (refreshGrid) refreshGrid();
@@ -69,7 +77,8 @@ export const GroupAddUserForm: React.FunctionComponent = ({
return
-
+
+
{ reset(defaultValues); closeForm(); }} />
>}>
= ({
const [workunit] = useWorkunit(wuid);
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -54,6 +56,8 @@ export const PublishQueryForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request = {
Wuid: workunit?.Wuid,
Cluster: workunit?.Cluster,
@@ -70,6 +74,8 @@ export const PublishQueryForm: React.FunctionComponent = ({
workunit.publishEx(request).then(() => {
return workunit.update({ Jobname: data.jobName });
}).then(() => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
}).catch(err => logger.error(err));
@@ -86,7 +92,8 @@ export const PublishQueryForm: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
= ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const [showError, setShowError] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState("");
@@ -40,6 +42,8 @@ export const PushEventForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request: any = data;
WsWorkunits.WUPushEvent({ request: request })
@@ -47,9 +51,13 @@ export const PushEventForm: React.FunctionComponent = ({
if (WUPushEventResponse?.retcode < 0) {
//log exception from API
setShowError(true);
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
setErrorMessage(WUPushEventResponse?.retmsg);
logger.error(WUPushEventResponse?.retmsg);
} else {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
}
@@ -62,7 +70,8 @@ export const PushEventForm: React.FunctionComponent = ({
return
-
+
+
{ reset(defaultValues); closeForm(); }} />
>}>
= ({
const [showError, setShowError] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState("");
-
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const [selectedDestGroup, setSelectedDestGroup] = React.useState("");
const [replicateDisabled, setReplicateDisabled] = React.useState(true);
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
+
FileSpray.Copy({
request: data
}).then(({ CopyResponse, Exceptions }) => {
if (Exceptions?.Exception) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
setShowError(true);
setErrorMessage(Exceptions?.Exception[0]?.Message);
} else {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
setShowForm(false);
reset(defaultValues);
if (refreshGrid) refreshGrid(true);
@@ -113,7 +121,8 @@ export const RemoteCopy: React.FunctionComponent = ({
return
-
+
+
setShowForm(false)} />
>}>
{showError &&
diff --git a/esp/src/src-react/components/forms/RenameFile.tsx b/esp/src/src-react/components/forms/RenameFile.tsx
index eeedfba61a3..b003f1cc280 100644
--- a/esp/src/src-react/components/forms/RenameFile.tsx
+++ b/esp/src/src-react/components/forms/RenameFile.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, DefaultButton, mergeStyleSets, PrimaryButton, Stack, TextField, } from "@fluentui/react";
+import { Checkbox, DefaultButton, mergeStyleSets, PrimaryButton, Spinner, Stack, TextField, } from "@fluentui/react";
import { useConst } from "@fluentui/react-hooks";
import { useForm, Controller } from "react-hook-form";
import { FileSprayService, FileSprayStates } from "@hpcc-js/comms";
@@ -39,6 +39,8 @@ export const RenameFile: React.FunctionComponent = ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const service = useConst(() => new FileSprayService({ baseUrl: "" }));
@@ -49,6 +51,8 @@ export const RenameFile: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
async (data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const renameRequests = [];
const getDfuWuRequests = [];
@@ -87,6 +91,8 @@ export const RenameFile: React.FunctionComponent = ({
}
}
});
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
if (refreshGrid) refreshGrid(true);
},
@@ -116,7 +122,8 @@ export const RenameFile: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/ReplicateFile.tsx b/esp/src/src-react/components/forms/ReplicateFile.tsx
index 4a8b61034f9..ed504ec3b23 100644
--- a/esp/src/src-react/components/forms/ReplicateFile.tsx
+++ b/esp/src/src-react/components/forms/ReplicateFile.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DefaultButton, IDropdownOption, PrimaryButton, Stack, TextField, } from "@fluentui/react";
+import { DefaultButton, IDropdownOption, PrimaryButton, Spinner, Stack, TextField, } from "@fluentui/react";
import { useForm, Controller } from "react-hook-form";
import nlsHPCC from "src/nlsHPCC";
import * as FileSpray from "src/FileSpray";
@@ -37,6 +37,8 @@ export const ReplicateFile: React.FunctionComponent = ({
const [file] = useFile(cluster, logicalFile);
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -45,8 +47,12 @@ export const ReplicateFile: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request = { ...data, srcname: logicalFile };
FileSpray.Replicate({ request: request }).then(response => {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
pushUrl(`/dfuworkunits/${response?.ReplicateResponse?.wuid}`);
});
@@ -64,7 +70,8 @@ export const ReplicateFile: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/TitlebarConfig.tsx b/esp/src/src-react/components/forms/TitlebarConfig.tsx
index b0682975468..59d49193871 100644
--- a/esp/src/src-react/components/forms/TitlebarConfig.tsx
+++ b/esp/src/src-react/components/forms/TitlebarConfig.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, ColorPicker, DefaultButton, getColorFromString, IColor, Label, PrimaryButton, TextField, TooltipHost } from "@fluentui/react";
+import { Checkbox, ColorPicker, DefaultButton, getColorFromString, IColor, Label, PrimaryButton, Spinner, TextField, TooltipHost } from "@fluentui/react";
import { useForm, Controller } from "react-hook-form";
import { MessageBox } from "../../layouts/MessageBox";
import { useGlobalStore } from "../../hooks/store";
@@ -32,6 +32,8 @@ export const TitlebarConfig: React.FunctionComponent = ({
setShowForm
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const [color, setColor] = React.useState(white);
const updateColor = React.useCallback((evt: any, colorObj: IColor) => setColor(colorObj), []);
const [showEnvironmentTitle, setShowEnvironmentTitle] = useGlobalStore("HPCCPlatformWidget_Toolbar_Active", toolbarThemeDefaults.active, true);
@@ -45,6 +47,8 @@ export const TitlebarConfig: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request: any = data;
request.titlebarColor = color.str;
@@ -52,6 +56,8 @@ export const TitlebarConfig: React.FunctionComponent = ({
setEnvironmentTitle(request?.environmentTitle);
setTitlebarColor(request.titlebarColor);
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
},
)();
@@ -78,7 +84,8 @@ export const TitlebarConfig: React.FunctionComponent = ({
return
-
+
+
{ reset(defaultValues); closeForm(); }} />
{ onReset(); }} />
>}>
diff --git a/esp/src/src-react/components/forms/UserAddGroup.tsx b/esp/src/src-react/components/forms/UserAddGroup.tsx
index b09393c30f1..467271fdeb9 100644
--- a/esp/src/src-react/components/forms/UserAddGroup.tsx
+++ b/esp/src/src-react/components/forms/UserAddGroup.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { DefaultButton, IDropdownOption, MessageBar, MessageBarType, PrimaryButton, } from "@fluentui/react";
+import { DefaultButton, IDropdownOption, MessageBar, MessageBarType, PrimaryButton, Spinner, } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import nlsHPCC from "src/nlsHPCC";
@@ -32,6 +32,8 @@ export const UserAddGroupForm: React.FunctionComponent = ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const [showError, setShowError] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState("");
@@ -43,6 +45,8 @@ export const UserAddGroupForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const request: any = data;
request.username = username;
request.action = "add";
@@ -52,9 +56,13 @@ export const UserAddGroupForm: React.FunctionComponent = ({
if (UserGroupEditResponse?.retcode < 0) {
//log exception from API
setShowError(true);
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
setErrorMessage(UserGroupEditResponse?.retmsg);
logger.error(UserGroupEditResponse?.retmsg);
} else {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
if (refreshGrid) refreshGrid();
@@ -69,7 +77,8 @@ export const UserAddGroupForm: React.FunctionComponent = ({
return
-
+
+
{ reset(defaultValues); closeForm(); }} />
>}>
= ({
}) => {
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -39,6 +41,8 @@ export const AddFileForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
const dropZone = {
...store.get(data.NetAddress),
NetAddress: data.NetAddress
@@ -57,6 +61,8 @@ export const AddFileForm: React.FunctionComponent = ({
};
store.addUserFile(file);
refreshGrid();
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
reset(defaultValues);
},
@@ -68,7 +74,8 @@ export const AddFileForm: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
= ({
const [, { isContainer }] = useBuildInfo();
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -74,6 +76,8 @@ export const BlobImportForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
let request = {};
const files = data.selectedFiles;
@@ -115,6 +119,8 @@ export const BlobImportForm: React.FunctionComponent = ({
}
});
if (errors.length === 0) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
}
}
@@ -153,7 +159,8 @@ export const BlobImportForm: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/landing-zone/DelimitedImportForm.tsx b/esp/src/src-react/components/forms/landing-zone/DelimitedImportForm.tsx
index 93510cf8191..ceb386cf2a4 100644
--- a/esp/src/src-react/components/forms/landing-zone/DelimitedImportForm.tsx
+++ b/esp/src/src-react/components/forms/landing-zone/DelimitedImportForm.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, DefaultButton, Dropdown, IDropdownOption, mergeStyleSets, PrimaryButton, Stack, TextField } from "@fluentui/react";
+import { Checkbox, DefaultButton, Dropdown, IDropdownOption, mergeStyleSets, PrimaryButton, Spinner, Stack, TextField } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import * as FileSpray from "src/FileSpray";
@@ -82,6 +82,8 @@ export const DelimitedImportForm: React.FunctionComponent({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -91,6 +93,8 @@ export const DelimitedImportForm: React.FunctionComponent {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
let request = {};
const files = data.selectedFiles;
@@ -136,6 +140,8 @@ export const DelimitedImportForm: React.FunctionComponent
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/landing-zone/FixedImportForm.tsx b/esp/src/src-react/components/forms/landing-zone/FixedImportForm.tsx
index 6b8a5cbaa02..34846ef4bef 100644
--- a/esp/src/src-react/components/forms/landing-zone/FixedImportForm.tsx
+++ b/esp/src/src-react/components/forms/landing-zone/FixedImportForm.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, DefaultButton, IDropdownOption, mergeStyleSets, PrimaryButton, Stack, TextField } from "@fluentui/react";
+import { Checkbox, DefaultButton, IDropdownOption, mergeStyleSets, PrimaryButton, Spinner, Stack, TextField } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import * as FileSpray from "src/FileSpray";
@@ -65,6 +65,8 @@ export const FixedImportForm: React.FunctionComponent = ({
const [, { isContainer }] = useBuildInfo();
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -74,6 +76,8 @@ export const FixedImportForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
let request = {};
const files = data.selectedFiles;
@@ -120,6 +124,8 @@ export const FixedImportForm: React.FunctionComponent = ({
}
});
if (errors.length === 0) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
}
}
@@ -160,7 +166,8 @@ export const FixedImportForm: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/landing-zone/JsonImportForm.tsx b/esp/src/src-react/components/forms/landing-zone/JsonImportForm.tsx
index 7132df1e0fa..590f26e9aba 100644
--- a/esp/src/src-react/components/forms/landing-zone/JsonImportForm.tsx
+++ b/esp/src/src-react/components/forms/landing-zone/JsonImportForm.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, DefaultButton, Dropdown, IDropdownOption, mergeStyleSets, PrimaryButton, Stack, TextField } from "@fluentui/react";
+import { Checkbox, DefaultButton, Dropdown, IDropdownOption, mergeStyleSets, PrimaryButton, Spinner, Stack, TextField } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import * as FileSpray from "src/FileSpray";
@@ -69,6 +69,8 @@ export const JsonImportForm: React.FunctionComponent = ({
const [, { isContainer }] = useBuildInfo();
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -77,6 +79,8 @@ export const JsonImportForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
let request = {};
const files = data.selectedFiles;
@@ -125,6 +129,8 @@ export const JsonImportForm: React.FunctionComponent = ({
}
});
if (errors.length === 0) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
}
}
@@ -165,7 +171,8 @@ export const JsonImportForm: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/landing-zone/VariableImportForm.tsx b/esp/src/src-react/components/forms/landing-zone/VariableImportForm.tsx
index 64fadc72493..6ae0bbf3c1c 100644
--- a/esp/src/src-react/components/forms/landing-zone/VariableImportForm.tsx
+++ b/esp/src/src-react/components/forms/landing-zone/VariableImportForm.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, DefaultButton, Dropdown, IDropdownOption, mergeStyleSets, PrimaryButton, Stack, TextField } from "@fluentui/react";
+import { Checkbox, DefaultButton, Dropdown, IDropdownOption, mergeStyleSets, PrimaryButton, Spinner, Stack, TextField } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import * as FileSpray from "src/FileSpray";
@@ -65,6 +65,8 @@ export const VariableImportForm: React.FunctionComponent({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -73,6 +75,8 @@ export const VariableImportForm: React.FunctionComponent {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
let request = {};
const files = data.selectedFiles;
@@ -117,6 +121,8 @@ export const VariableImportForm: React.FunctionComponent
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/components/forms/landing-zone/XmlImportForm.tsx b/esp/src/src-react/components/forms/landing-zone/XmlImportForm.tsx
index e5f01992294..f40fd9aca23 100644
--- a/esp/src/src-react/components/forms/landing-zone/XmlImportForm.tsx
+++ b/esp/src/src-react/components/forms/landing-zone/XmlImportForm.tsx
@@ -1,5 +1,5 @@
import * as React from "react";
-import { Checkbox, DefaultButton, Dropdown, IDropdownOption, mergeStyleSets, PrimaryButton, Stack, TextField } from "@fluentui/react";
+import { Checkbox, DefaultButton, Dropdown, IDropdownOption, mergeStyleSets, PrimaryButton, Spinner, Stack, TextField } from "@fluentui/react";
import { scopedLogger } from "@hpcc-js/util";
import { useForm, Controller } from "react-hook-form";
import * as FileSpray from "src/FileSpray";
@@ -69,6 +69,8 @@ export const XmlImportForm: React.FunctionComponent = ({
const [, { isContainer }] = useBuildInfo();
const { handleSubmit, control, reset } = useForm({ defaultValues });
+ const [submitDisabled, setSubmitDisabled] = React.useState(false);
+ const [spinnerHidden, setSpinnerHidden] = React.useState(true);
const closeForm = React.useCallback(() => {
setShowForm(false);
@@ -77,6 +79,8 @@ export const XmlImportForm: React.FunctionComponent = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
+ setSubmitDisabled(true);
+ setSpinnerHidden(false);
let request = {};
const files = data.selectedFiles;
@@ -123,6 +127,8 @@ export const XmlImportForm: React.FunctionComponent = ({
}
});
if (errors.length === 0) {
+ setSubmitDisabled(false);
+ setSpinnerHidden(true);
closeForm();
}
}
@@ -163,7 +169,8 @@ export const XmlImportForm: React.FunctionComponent = ({
return
-
+
+
closeForm()} />
>}>
diff --git a/esp/src/src-react/hooks/platform.ts b/esp/src/src-react/hooks/platform.ts
index 8e90b4ab363..66dac5d9487 100644
--- a/esp/src/src-react/hooks/platform.ts
+++ b/esp/src/src-react/hooks/platform.ts
@@ -137,8 +137,14 @@ export function useCheckFeatures(): Features {
timestamp
};
}
-
-const fetchReleases = () => {
+interface OctokitRelease {
+ id: number;
+ draft: boolean;
+ prerelease: boolean;
+ tag_name: string;
+ html_url: string;
+}
+const fetchReleases = (): Promise<{ data: OctokitRelease[] }> => {
const octokit = new Octokit({});
return octokit.request("GET /repos/{owner}/{repo}/releases", {
owner: "hpcc-systems",
@@ -149,16 +155,12 @@ const fetchReleases = () => {
}
});
};
-type ReleasesPromise = ReturnType;
-type ReleasesResponse = Awaited;
-type Releases = ReleasesResponse["data"];
-type Release = Releases[number];
-const _fetchLatestReleases = (): Promise => {
+const _fetchLatestReleases = (): Promise => {
return fetchReleases().then(response => {
- const latest: { [id: string]: Release } = response.data
+ const latest: { [releaseID: string]: OctokitRelease } = response.data
.filter(release => !release.draft || !release.prerelease)
- .reduce((prev, curr: Release) => {
+ .reduce((prev, curr: OctokitRelease) => {
const versionParts = curr.tag_name.split(".");
versionParts.length = 2;
const partialVersion = versionParts.join(".");
@@ -167,14 +169,14 @@ const _fetchLatestReleases = (): Promise => {
}
return prev;
}, {});
- return Object.values(latest) as Releases;
+ return Object.values(latest);
}).catch(err => {
logger.error(err);
- return [] as Releases;
+ return [];
});
};
-let releasesPromise: Promise | undefined;
-export const fetchLatestReleases = (): Promise => {
+let releasesPromise: Promise | undefined;
+export const fetchLatestReleases = (): Promise => {
if (!releasesPromise) {
releasesPromise = _fetchLatestReleases();
}
diff --git a/esp/src/src-react/hooks/workunit.ts b/esp/src/src-react/hooks/workunit.ts
index 662b44dccdb..3bc1c22314a 100644
--- a/esp/src/src-react/hooks/workunit.ts
+++ b/esp/src/src-react/hooks/workunit.ts
@@ -132,6 +132,21 @@ export function useWorkunitSourceFiles(wuid: string): [SourceFile[], Workunit, W
const [sourceFiles, setSourceFiles] = React.useState([]);
const [count, inc] = useCounter();
+ // sorts the WU source files alphabetically by parent name, then name
+ // with children immediately following parents
+ const sortFiles = React.useCallback(files => {
+ const sortedFiles = [];
+ const temp = files.sort((a, b) => a.Name.localeCompare(b.Name));
+
+ temp.filter(item => item.__hpcc_parentName === "").forEach(parent => {
+ sortedFiles.push(parent);
+ const relatedChildren = temp.filter(child => child.__hpcc_parentName === parent.Name);
+ sortedFiles.push(...relatedChildren);
+ });
+
+ return sortedFiles;
+ }, []);
+
React.useEffect(() => {
if (workunit) {
const fetchInfo = singletonDebounce(workunit, "fetchInfo");
@@ -151,10 +166,10 @@ export function useWorkunitSourceFiles(wuid: string): [SourceFile[], Workunit, W
});
});
});
- setSourceFiles(sourceFiles);
+ setSourceFiles(sortFiles(sourceFiles));
}).catch(err => logger.error(err));
}
- }, [workunit, state, count]);
+ }, [count, sortFiles, state, workunit]);
return [sourceFiles, workunit, state, inc];
}
diff --git a/esp/src/src-react/util/history.ts b/esp/src/src-react/util/history.ts
index d4420fc4d7e..6f54845db45 100644
--- a/esp/src/src-react/util/history.ts
+++ b/esp/src/src-react/util/history.ts
@@ -278,3 +278,11 @@ export function updateState(key: string, val?: string | string[] | number | bool
}
globalHistory.replaceState(state, "");
}
+
+export function navCategory(hash: string): string {
+ let category = hash.split("/").slice(0, 2).join("/");
+ if (category.indexOf("?") > -1) {
+ category = category.substring(0, category.indexOf("?"));
+ }
+ return category;
+}
\ No newline at end of file
diff --git a/system/jlib/jlzw.cpp b/system/jlib/jlzw.cpp
index 827223950b1..f289c185717 100644
--- a/system/jlib/jlzw.cpp
+++ b/system/jlib/jlzw.cpp
@@ -2529,7 +2529,7 @@ static bool isCompressedType(__int64 compressedType)
return 0 != getCompressedMethod(compressedType);
}
-bool isCompressedFile(IFileIO *iFileIO, CompressedFileTrailer *trailer=nullptr)
+static bool isCompressedFile(IFileIO *iFileIO, CompressedFileTrailer *trailer=nullptr)
{
if (iFileIO)
{
@@ -2547,6 +2547,16 @@ bool isCompressedFile(IFileIO *iFileIO, CompressedFileTrailer *trailer=nullptr)
return true;
}
}
+ else if ((fsize == 0) && trailer)
+ {
+ //If the file is empty, but we are expecting a compressed file, fill in the trailer with default information
+ memset(trailer,0,sizeof(*trailer));
+ trailer->crc = ~0U;
+ trailer->compressedType = LZ4COMPRESSEDFILEFLAG;
+ trailer->blockSize = LZ4COMPRESSEDFILEBLOCKSIZE;
+ trailer->recordSize = 0;
+ return true;
+ }
}
return false;
}