Skip to content

Commit

Permalink
HPCC-29934 ECL Watch v9 file explorer component
Browse files Browse the repository at this point in the history
Signed-off-by: Jeremy Clements <[email protected]>
  • Loading branch information
jeclrsg committed Jan 24, 2024
1 parent 64b6a8c commit 400b3f5
Show file tree
Hide file tree
Showing 11 changed files with 381 additions and 125 deletions.
2 changes: 1 addition & 1 deletion esp/src/src-react/components/AppPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const AppPanel: React.FunctionComponent<AppPanelProps> = ({
const retVal = [];
webLinks?.forEach(webLink => {
webLink.Annotations.NamedValue.forEach(nv => {
retVal.push(<DefaultButton text={`${webLink.ServiceName} - ${nv.Name}`} href={`/${nv.Value}`} target="_blank" />);
retVal.push(<DefaultButton key={nv.Name} text={`${webLink.ServiceName} - ${nv.Name}`} href={`/${nv.Value}`} target="_blank" />);
});
});
// Include HPCC Systems link when there are no other web links available
Expand Down
397 changes: 291 additions & 106 deletions esp/src/src-react/components/LandingZone.tsx

Large diffs are not rendered by default.

69 changes: 69 additions & 0 deletions esp/src/src-react/components/controls/TreeView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as React from "react";
import { mergeStyleSets } from "@fluentui/react";
import { FlatTree as Tree, TreeItem, TreeItemLayout, TreeItemValue, TreeOpenChangeData, TreeOpenChangeEvent, useHeadlessFlatTree_unstable, HeadlessFlatTreeItemProps, useId, tokens } from "@fluentui/react-components";
import { ConnectVirtualMachineIcon, FolderOpenIcon, FolderIcon, OfflineStorageIcon } from "@fluentui/react-icons-mdl2";

export enum BranchIcon {
None,
Directory,
Dropzone,
Network,
}

const getIcon = (iconStr: BranchIcon, open: boolean): React.ReactElement | null => {
switch (iconStr) {
case BranchIcon.Directory:
return open ? <FolderOpenIcon /> : <FolderIcon />;
case BranchIcon.Dropzone:
return <OfflineStorageIcon />;
case BranchIcon.Network:
return <ConnectVirtualMachineIcon />;
case BranchIcon.None:
default:
return null;
}
};

export type FlatItem = HeadlessFlatTreeItemProps & {
label?: string,
icon?: BranchIcon,
data?: { [id: string]: any }
};

interface TreeViewProps {
treeItems: FlatItem[];
openItems: Iterable<TreeItemValue>;
onOpenChange?: (_: TreeOpenChangeEvent, data: TreeOpenChangeData) => void;
ariaLabel: string;
}

export const TreeView: React.FunctionComponent<TreeViewProps> = ({
treeItems,
openItems,
onOpenChange,
ariaLabel
}) => {

const treeStyles = mergeStyleSets({
focused: {
background: tokens.colorBrandBackgroundInvertedPressed,
}
});

const flatTree = useHeadlessFlatTree_unstable(treeItems, { onOpenChange: onOpenChange ? onOpenChange : null, openItems });
const flatTreeProps = { ...flatTree.getTreeProps() };
const key = useId("FileExplorer");
if (!treeItems || treeItems.length < 1) return null;

return <Tree key={key} aria-label={ariaLabel} {...flatTreeProps}>
{Array.from(flatTree.items(), (item, idx) => {
const { icon, label, data, ...treeItemProps } = item.getTreeItemProps();
const open = flatTreeProps.openItems.has(item.value) ? true : false;
const selected = Array.from(flatTreeProps.openItems).pop() === item.value;
return <TreeItem key={`${label?.replace(/\s+/g, "")}_${idx}`} data-tree={JSON.stringify(data)} {...treeItemProps}>
<TreeItemLayout className={selected ? treeStyles.focused : null} iconBefore={getIcon(icon, open)}>{label}</TreeItemLayout >
</TreeItem>;
})}
</Tree>;

};
21 changes: 9 additions & 12 deletions esp/src/src-react/components/forms/landing-zone/AddFileForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ const defaultValues: AddFileFormValues = {
interface AddFileFormProps {
formMinWidth?: number;
showForm: boolean;
refreshGrid: (() => void),
store: any;
refreshGrid: (() => void);
addUserFile: ((file) => void);
dropzone: any;
setShowForm: (_: boolean) => void;
}

export const AddFileForm: React.FunctionComponent<AddFileFormProps> = ({
formMinWidth = 300,
showForm,
refreshGrid,
store,
addUserFile,
dropzone,
setShowForm
}) => {

Expand All @@ -39,32 +41,27 @@ export const AddFileForm: React.FunctionComponent<AddFileFormProps> = ({
const onSubmit = React.useCallback(() => {
handleSubmit(
(data, evt) => {
const dropZone = {
...store.get(data.NetAddress),
NetAddress: data.NetAddress
};
let fullPathParts = data.fullPath.split("/");
if (fullPathParts.length === 1) {
fullPathParts = data.fullPath.split("\\");
}
const file = {
...store.get(data.NetAddress + data.fullPath),
name: fullPathParts[fullPathParts.length - 1],
displayName: fullPathParts[fullPathParts.length - 1],
fullPath: data.fullPath,
isDir: false,
DropZone: dropZone
DropZone: dropzone,
_isUserFile: true
};
store.addUserFile(file);
refreshGrid();
addUserFile(file);
closeForm();
reset(defaultValues);
},
err => {
console.log(err);
}
)();
}, [closeForm, handleSubmit, refreshGrid, reset, store]);
}, [addUserFile, closeForm, dropzone, handleSubmit, reset]);

return <MessageBox title={nlsHPCC.AddFile} show={showForm} setShow={closeForm}
footer={<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export const BlobImportForm: React.FunctionComponent<BlobImportFormProps> = ({
newValues.selectedFiles[idx] = {
TargetName: "",
SourceFile: file["fullPath"],
SourcePlane: file?.DropZone?.Name ?? "",
SourcePlane: file["SourcePlane"] ?? "",
SourceIP: file["NetAddress"]
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export const DelimitedImportForm: React.FunctionComponent<DelimitedImportFormPro
TargetName: file["name"],
NumParts: file["NumParts"],
SourceFile: file["fullPath"],
SourcePlane: file?.DropZone?.Name ?? "",
SourcePlane: file["SourcePlane"] ?? "",
SourceIP: file["NetAddress"]
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export const JsonImportForm: React.FunctionComponent<JsonImportFormProps> = ({
TargetRowPath: "/",
NumParts: "",
SourceFile: file["fullPath"],
SourcePlane: file?.DropZone?.Name ?? "",
SourcePlane: file["SourcePlane"] ?? "",
SourceIP: file["NetAddress"]
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export const VariableImportForm: React.FunctionComponent<VariableImportFormProps
newValues.selectedFiles[idx] = {
TargetName: file["name"],
SourceFile: file["fullPath"],
SourcePlane: file?.DropZone?.Name ?? "",
SourcePlane: file["SourcePlane"] ?? "",
SourceIP: file["NetAddress"]
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export const XmlImportForm: React.FunctionComponent<XmlImportFormProps> = ({
TargetRowTag: "Row",
NumParts: "",
SourceFile: file["fullPath"],
SourcePlane: file?.DropZone?.Name ?? "",
SourcePlane: file["SourcePlane"] ?? "",
SourceIP: file["NetAddress"]
};
});
Expand Down
5 changes: 5 additions & 0 deletions esp/src/src-react/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ export const routes: RoutesEx = [
return <_.LandingZone filter={parseSearch(ctx.search) as any} />;
})
},
{
path: "/:Path", action: (ctx, params) => import("./components/LandingZone").then(_ => {
return <_.LandingZone filter={parseSearch(ctx.search) as any} path={params.Path as string} />;
})
},
{
path: "/preview/:logicalFile", action: (ctx, params) => import("./components/HexView").then(_ => {
return <_.HexView logicalFile={params.logicalFile as string} />;
Expand Down
2 changes: 1 addition & 1 deletion esp/src/src/FileSpray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as ESPRequest from "./ESPRequest";

declare const dojo;

const lfEncode = (path: string) => {
export const lfEncode = (path: string) => {
let retVal = "";
for (let i = 0; i < path.length; ++i) {
switch (path[i]) {
Expand Down

0 comments on commit 400b3f5

Please sign in to comment.