Преглед изворни кода

Merge pull request #15706 from GordonSmith/HPCC-26447-useTopology

HPCC-26447 Common up fetchLogicalClusters calls

Reviewed-By: Jeremy Clements <jeremy.clements@lexisnexisrisk.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman пре 3 година
родитељ
комит
982c03fb40

+ 12 - 15
esp/src/src-react/components/HexView.tsx

@@ -1,9 +1,10 @@
 import * as React from "react";
 import { Checkbox, ICheckboxStyles, ISpinButtonStyles, Label, SpinButton } from "@fluentui/react";
-import { Topology, Workunit } from "@hpcc-js/comms";
-import { TextSourceEditor } from "./SourceEditor";
-import nlsHPCC from "src/nlsHPCC";
 import { scopedLogger } from "@hpcc-js/util";
+import { Workunit } from "@hpcc-js/comms";
+import nlsHPCC from "src/nlsHPCC";
+import { useLogicalClusters } from "../hooks/platform";
+import { TextSourceEditor } from "./SourceEditor";
 
 const logger = scopedLogger("src-react/components/HexView.tsx");
 
@@ -34,7 +35,6 @@ export const HexView: React.FunctionComponent<HexViewProps> = ({
     const [cachedResponse, setCachedResponse] = React.useState<any[]>([]);
     const [lineLength, setLineLength] = React.useState("16");
     const [showEbcdic, setShowEbcdic] = React.useState(false);
-    const [queryTarget, setQueryTarget] = React.useState("");
 
     const onLineLengthChange = React.useCallback((event: React.FormEvent<HTMLInputElement>, newValue?: string) => {
         if (newValue !== undefined) {
@@ -61,16 +61,11 @@ analysis_dataset := project(data_dataset, calcAnalysis(left));
 choosen(analysis_dataset, ${bufferLength});`;
     }, [logicalFile]);
 
-    React.useEffect(() => {
-        const topology = Topology.attach({ baseUrl: "" });
-        topology.fetchLogicalClusters().then(response => {
-            setQueryTarget(response.filter(row => row.Type === "hthor")[0]?.Name || "");
-        }).catch(err => logger.error(err));
-    }, []);
+    const [, defaultCluster] = useLogicalClusters();
 
     React.useEffect(() => {
-        if (queryTarget == "") return;
-        Workunit.submit({ baseUrl: "" }, queryTarget, query).then(wu => {
+        if (!defaultCluster?.Name) return;
+        Workunit.submit({ baseUrl: "" }, defaultCluster?.Name, query).then(wu => {
             wu.on("changed", function () {
                 if (!wu.isComplete()) {
                     setText("..." + wu.State + "...");
@@ -78,7 +73,9 @@ choosen(analysis_dataset, ${bufferLength});`;
             });
             return wu.watchUntilComplete();
         }).then(function (wu) {
-            return wu.fetchECLExceptions().then(function () { return wu; });
+            return wu.fetchECLExceptions()
+                .then(() => wu)
+                .catch(err => wu);
         }).then(function (wu) {
             const exceptions = wu.Exceptions && wu.Exceptions.ECLException ? wu.Exceptions.ECLException : [];
             if (exceptions.length) {
@@ -108,7 +105,7 @@ choosen(analysis_dataset, ${bufferLength});`;
         }).then(function (wu) {
             return wu.delete();
         });
-    }, [query, queryTarget]);
+    }, [defaultCluster?.Name, query]);
 
     React.useEffect(() => {
         const formatRow = (row, strRow, hexRow, length) => {
@@ -167,7 +164,7 @@ choosen(analysis_dataset, ${bufferLength});`;
             <Label>{nlsHPCC.Width}</Label>
             <SpinButton value={lineLength.toString()} min={1} onChange={onLineLengthChange} styles={spinStyles} />
             <Label>{nlsHPCC.EBCDIC}</Label>
-            <Checkbox onChange={() => setShowEbcdic(!showEbcdic)} styles={checkboxStyles} />
+            <Checkbox onChange={(ev, checked) => setShowEbcdic(checked)} styles={checkboxStyles} />
         </div>
         <TextSourceEditor text={text} readonly={true} />
     </>;

+ 8 - 8
esp/src/src-react/components/QueryTests.tsx

@@ -48,40 +48,40 @@ export const QueryTests: React.FunctionComponent<QueryTestsProps> = ({
         fetch(`/WsEcl/definitions/query/${querySet}/${queryId}/main/${queryId}.wsdl`)
             .then(response => response.text())
             .then(content => setWsdl(content))
-            .catch(err => logger.error);
+            .catch(err => logger.error(err));
 
         fetch(`/WsEcl/definitions/query/${querySet}/${queryId}/main/${queryId}.xsd`)
             .then(response => response.text())
             .then(content => setRequestSchema(content))
-            .catch(err => logger.error);
+            .catch(err => logger.error(err));
 
         const requests = resultNames.map(name => {
             const url = `/WsEcl/definitions/query/${querySet}/${queryId}/result/${name}.xsd`;
             return fetch(url)
                 .then(response => response.text())
-                .catch(err => logger.error);
+                .catch(err => logger.error(err));
         });
         Promise.all(requests)
             .then(schemas => {
                 logger.debug(schemas);
                 setResponseSchemas(schemas);
             })
-            .catch(err => logger.error);
+            .catch(err => logger.error(err));
 
         fetch(`/WsEcl/example/request/query/${querySet}/${queryId}`)
             .then(response => response.text())
             .then(content => setExampleRequest(content))
-            .catch(err => logger.error);
+            .catch(err => logger.error(err));
 
         fetch(`/WsEcl/example/response/query/${querySet}/${queryId}`)
             .then(response => response.text())
             .then(content => setExampleResponse(content))
-            .catch(err => logger.error);
+            .catch(err => logger.error(err));
 
         fetch(`/WsEcl/definitions/query/${querySet}/${queryId}/resource/soap/${queryId}.xml`)
             .then(response => response.text())
             .then(content => setParameterXml(content))
-            .catch(err => logger.error);
+            .catch(err => logger.error(err));
 
         setFormUrl(`/WsEcl/forms/ecl/query/${querySet}/${queryId}`);
         setLinksUrl(`/WsEcl/links/query/${querySet}/${queryId}`);
@@ -92,7 +92,7 @@ export const QueryTests: React.FunctionComponent<QueryTestsProps> = ({
             .then(({ WUQueryDetailsResponse }) => {
                 setWuid(WUQueryDetailsResponse.Wuid);
             })
-            .catch(err => logger.error);
+            .catch(err => logger.error(err));
     }, [query]);
 
     React.useEffect(() => {

+ 22 - 43
esp/src/src-react/components/forms/Fields.tsx

@@ -1,6 +1,5 @@
 import * as React from "react";
 import { Checkbox, ChoiceGroup, IChoiceGroupOption, Dropdown as DropdownBase, IDropdownOption, TextField, Link, ProgressIndicator } from "@fluentui/react";
-import { Topology, TpLogicalClusterQuery } from "@hpcc-js/comms";
 import { scopedLogger } from "@hpcc-js/util";
 import { TpDropZoneQuery, TpGroupQuery, TpServiceQuery } from "src/WsTopology";
 import * as WsAccess from "src/ws_access";
@@ -8,6 +7,7 @@ import * as WsESDLConfig from "src/WsESDLConfig";
 import { States } from "src/WsWorkunits";
 import { FileList, States as DFUStates } from "src/FileSpray";
 import nlsHPCC from "src/nlsHPCC";
+import { useLogicalClusters } from "../../hooks/platform";
 
 const logger = scopedLogger("src-react/components/forms/Fields.tsx");
 
@@ -304,47 +304,26 @@ export interface TargetClusterTextFieldProps extends AsyncDropdownProps {
 
 export const TargetClusterTextField: React.FunctionComponent<TargetClusterTextFieldProps> = (props) => {
 
-    const [targetClusters, setTargetClusters] = React.useState<IDropdownOption[]>();
+    const [targetClusters, defaultCluster] = useLogicalClusters();
+    const [options, setOptions] = React.useState<IDropdownOption[]>();
     const [defaultRow, setDefaultRow] = React.useState<IDropdownOption>();
 
     React.useEffect(() => {
-        const topology = Topology.attach({ baseUrl: "" });
-        let active = true;
-        topology.fetchLogicalClusters().then((response: TpLogicalClusterQuery.TpLogicalCluster[]) => {
-            if (active) {
-                const options = response.map(row => {
-                    return {
-                        key: row.Name || "unknown",
-                        text: row.Name + (row.Name !== row.Type ? ` (${row.Type})` : ""),
-                        type: row.Type
-                    };
-                }) || [];
-                setTargetClusters(options);
-                let firstRow: IDropdownOption;
-                let firstHThor: IDropdownOption;
-                let firstThor: IDropdownOption;
-                options.forEach(row => {
-                    if (firstRow === undefined) {
-                        firstRow = row;
-                    }
-                    if (firstHThor === undefined && (row as any).type === "hthor") {
-                        firstHThor = row;
-                    }
-                    if (firstThor === undefined && (row as any).type === "thor") {
-                        firstThor = row;
-                    }
-                    return row;
-                });
-                if (autoSelectDropdown(props.selectedKey, props.required, props.optional)) {
-                    const selRow = firstThor || firstHThor || firstRow;
-                    setDefaultRow(selRow);
-                }
-            }
-        }).catch(e => logger.error);
-        return () => { active = false; };
-    }, [props.selectedKey, props.required, props.optional]);
+        const options = targetClusters?.map(row => {
+            return {
+                key: row.Name || "unknown",
+                text: row.Name + (row.Name !== row.Type ? ` (${row.Type})` : ""),
+                type: row.Type
+            };
+        }) || [];
+        setOptions(options);
+
+        if (autoSelectDropdown(props.selectedKey, props.required, props.optional)) {
+            setDefaultRow(options.filter(row => row.key === defaultCluster?.Name)[0]);
+        }
+    }, [targetClusters, defaultCluster, props.selectedKey, props.required, props.optional]);
 
-    return <AsyncDropdown {...props} selectedKey={props.selectedKey || defaultRow?.key as string} options={targetClusters} />;
+    return <AsyncDropdown {...props} selectedKey={props.selectedKey || defaultRow?.key as string} options={options} />;
 };
 
 export interface TargetDropzoneTextFieldProps extends AsyncDropdownProps {
@@ -363,7 +342,7 @@ export const TargetDropzoneTextField: React.FunctionComponent<TargetDropzoneText
                     path: row.Path
                 };
             }) || []);
-        }).catch(e => logger.error);
+        }).catch(err => logger.error(err));
     }, []);
 
     return <AsyncDropdown {...props} options={targetDropzones} />;
@@ -387,7 +366,7 @@ export const TargetServerTextField: React.FunctionComponent<TargetServerTextFiel
                     OS: n.OS
                 };
             }) || []);
-        }).catch(e => logger.error);
+        }).catch(err => logger.error(err));
     }, [props.selectedKey, props.dropzone]);
 
     return <AsyncDropdown {...props} options={targetServers} />;
@@ -425,7 +404,7 @@ export const TargetGroupTextField: React.FunctionComponent<TargetGroupTextFieldP
                     text: n.Name + (n.Name !== n.Kind ? ` (${n.Kind})` : "")
                 };
             }));
-        }).catch(e => logger.error);
+        }).catch(err => logger.error(err));
     }, []);
 
     return <AsyncDropdown {...props} options={targetGroups} />;
@@ -448,7 +427,7 @@ export const TargetDfuSprayQueueTextField: React.FunctionComponent<TargetDfuSpra
                     };
                 })
             );
-        }).catch(e => logger.error);
+        }).catch(err => logger.error(err));
     }, []);
 
     return <AsyncDropdown {...props} options={dfuSprayQueues} />;
@@ -547,7 +526,7 @@ export const TargetFolderTextField: React.FunctionComponent<TargetFolderTextFiel
                             retVal = retVal.concat(response);
                         });
                         resolve(retVal);
-                    }).catch(e => logger.error);
+                    }).catch(err => logger.error(err));
                 });
             }
         });

+ 38 - 0
esp/src/src-react/hooks/platform.ts

@@ -1,6 +1,10 @@
 import * as React from "react";
+import { scopedLogger } from "@hpcc-js/util";
+import { Topology, TpLogicalClusterQuery } from "@hpcc-js/comms";
 import { getBuildInfo, BuildInfo } from "src/Session";
 
+const logger = scopedLogger("src-react/hooks/platform.ts");
+
 declare const dojoConfig;
 
 export function useBuildInfo(): [BuildInfo, { isContainer: boolean, currencyCode: string }] {
@@ -19,3 +23,37 @@ export function useBuildInfo(): [BuildInfo, { isContainer: boolean, currencyCode
 
     return [buildInfo, { isContainer, currencyCode }];
 }
+
+export function useLogicalClusters(): [TpLogicalClusterQuery.TpLogicalCluster[] | undefined, TpLogicalClusterQuery.TpLogicalCluster | undefined] {
+    const [targetClusters, setTargetClusters] = React.useState<TpLogicalClusterQuery.TpLogicalCluster[]>();
+    const [defaultCluster, setDefaultCluster] = React.useState<TpLogicalClusterQuery.TpLogicalCluster>();
+
+    React.useEffect(() => {
+        const topology = Topology.attach({ baseUrl: "" });
+        let active = true;
+        topology.fetchLogicalClusters().then(response => {
+            if (active) {
+                setTargetClusters(response);
+                let firstRow: TpLogicalClusterQuery.TpLogicalCluster;
+                let firstHThor: TpLogicalClusterQuery.TpLogicalCluster;
+                let firstThor: TpLogicalClusterQuery.TpLogicalCluster;
+                response.forEach(row => {
+                    if (firstRow === undefined) {
+                        firstRow = row;
+                    }
+                    if (firstHThor === undefined && (row as any).type === "hthor") {
+                        firstHThor = row;
+                    }
+                    if (firstThor === undefined && (row as any).type === "thor") {
+                        firstThor = row;
+                    }
+                    return row;
+                });
+                setDefaultCluster(firstThor ?? firstHThor ?? firstRow);
+            }
+        }).catch(err => logger.error(err));
+        return () => { active = false; };
+    }, []);
+
+    return [targetClusters, defaultCluster];
+}