Create FileTree component
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Fri, 27 Jul 2018 11:25:46 +0000 (13:25 +0200)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Fri, 27 Jul 2018 11:25:46 +0000 (13:25 +0200)
Feature #13855

Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski@contractors.roche.com>

src/components/file-tree/file-tree-data.ts [new file with mode: 0644]
src/components/file-tree/file-tree-item.tsx [new file with mode: 0644]
src/components/file-tree/file-tree.tsx [new file with mode: 0644]

diff --git a/src/components/file-tree/file-tree-data.ts b/src/components/file-tree/file-tree-data.ts
new file mode 100644 (file)
index 0000000..4be4ace
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export interface FileTreeData {
+    name: string;
+    type: string;
+    size?: number;
+}
diff --git a/src/components/file-tree/file-tree-item.tsx b/src/components/file-tree/file-tree-item.tsx
new file mode 100644 (file)
index 0000000..e65c6cd
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from "react";
+import { TreeItem } from "../tree/tree";
+import { ProjectIcon, MoreOptionsIcon } from "../icon/icon";
+import { Typography, IconButton, StyleRulesCallback, withStyles, WithStyles } from "@material-ui/core";
+import { formatFileSize } from "../../common/formatters";
+import { ListItemTextIcon } from "../list-item-text-icon/list-item-text-icon";
+import { FileTreeData } from "./file-tree-data";
+
+type CssRules = "root" | "spacer" | "sizeInfo" | "button";
+
+const fileTreeItemStyle: StyleRulesCallback<CssRules> = theme => ({
+    root: {
+        display: "flex",
+        alignItems: "center",
+        paddingRight: `${theme.spacing.unit}px`
+    },
+    spacer: {
+        flex: "1"
+    },
+    sizeInfo: {
+        marginRight: `${theme.spacing.unit * 3}px`
+    },
+    button: {
+        width: theme.spacing.unit * 3,
+        height: theme.spacing.unit * 3
+    }
+});
+
+export interface FileTreeItemProps {
+    item: TreeItem<FileTreeData>;
+    onMoreClick: (event: React.MouseEvent<any>, item: TreeItem<FileTreeData>) => void;
+}
+export const FileTreeItem = withStyles(fileTreeItemStyle)(
+    class extends React.Component<FileTreeItemProps & WithStyles<CssRules>> {
+        render() {
+            const { classes, item } = this.props;
+            return <div className={classes.root}>
+                <ListItemTextIcon
+                    icon={ProjectIcon}
+                    name={item.data.name} />
+                <div className={classes.spacer} />
+                <Typography
+                    className={classes.sizeInfo}
+                    variant="caption">{formatFileSize(item.data.size)}</Typography>
+                <IconButton
+                    className={classes.button}
+                    onClick={this.handleClick}>
+                    <MoreOptionsIcon />
+                </IconButton>
+            </div >;
+        }
+
+        handleClick = (event: React.MouseEvent<any>) => {
+            this.props.onMoreClick(event, this.props.item);
+        }
+    });
+
diff --git a/src/components/file-tree/file-tree.tsx b/src/components/file-tree/file-tree.tsx
new file mode 100644 (file)
index 0000000..bb70f25
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from "react";
+import { Tree, TreeItem, TreeItemStatus } from "../tree/tree";
+import { FileTreeData } from "./file-tree-data";
+import { FileTreeItem } from "./file-tree-item";
+
+export interface FileTreeProps {
+    items: Array<TreeItem<FileTreeData>>;
+    onContextMenu: (event: React.MouseEvent<HTMLElement>, item: TreeItem<FileTreeData>) => void;
+    onSelectionToggle: (event: React.MouseEvent<HTMLElement>, item: TreeItem<FileTreeData>) => void;
+    onCollapseToggle: (id: string, status: TreeItemStatus) => void;
+}
+
+export class FileTree extends React.Component<FileTreeProps> {
+    render() {
+        return <Tree
+            showSelection={true}
+            items={this.props.items}
+            disableRipple={true}
+            render={this.renderItem}
+            onContextMenu={this.handleContextMenu}
+            toggleItemActive={this.handleToggleActive}
+            toggleItemOpen={this.handleToggle}
+            onSelectionChange={this.handleSelectionChange} />;
+    }
+
+    handleContextMenu = (event: React.MouseEvent<any>, item: TreeItem<FileTreeData>) => {
+        event.stopPropagation();
+        this.props.onContextMenu(event, item);
+    }
+
+    handleToggle = (id: string, status: TreeItemStatus) => {
+        this.props.onCollapseToggle(id, status);
+    }
+
+    handleToggleActive = () => { return; };
+
+    handleSelectionChange = (event: React.MouseEvent<HTMLElement>, item: TreeItem<FileTreeData>) => {
+        event.stopPropagation();
+        this.props.onSelectionToggle(event, item);
+    }
+
+    renderItem = (item: TreeItem<FileTreeData>) =>
+        <FileTreeItem
+            item={item}
+            onMoreClick={this.handleContextMenu} />
+
+}