//
// SPDX-License-Identifier: AGPL-3.0
-import * as React from 'react';
-import { Grid, Paper, Toolbar, Typography } from '@material-ui/core';
-import IconButton from '@material-ui/core/IconButton';
-import MoreVertIcon from "@material-ui/icons/MoreVert";
-import { formatDate, formatFileSize } from '../../common/formatters';
-import { DataItem } from './data-item';
-import DataTable, { DataColumns } from "../../components/data-table/data-table";
-import ContextMenu from "../../components/context-menu/context-menu";
-import ColumnSelector from "../../components/column-selector/column-selector";
-import { mockAnchorFromMouseEvent } from "../../components/popover/helpers";
-import { DataColumn } from "../../components/data-table/data-column";
-import { ResourceKind } from "../../models/resource";
-
-export interface DataExplorerContextActions {
- onAddToFavourite: (dataIitem: DataItem) => void;
- onCopy: (dataIitem: DataItem) => void;
- onDownload: (dataIitem: DataItem) => void;
- onMoveTo: (dataIitem: DataItem) => void;
- onRemove: (dataIitem: DataItem) => void;
- onRename: (dataIitem: DataItem) => void;
- onShare: (dataIitem: DataItem) => void;
-}
-interface DataExplorerProps {
- items: DataItem[];
- onItemClick: (item: DataItem) => void;
- contextActions: DataExplorerContextActions;
-}
-
-interface DataExplorerState {
- columns: DataColumns<DataItem>;
- contextMenu: {
- anchorEl?: HTMLElement;
- item?: DataItem;
- };
+import { connect } from "react-redux";
+import { RootState } from "~/store/store";
+import { DataExplorer as DataExplorerComponent } from "~/components/data-explorer/data-explorer";
+import { getDataExplorer } from "~/store/data-explorer/data-explorer-reducer";
+import { Dispatch } from "redux";
+import { dataExplorerActions } from "~/store/data-explorer/data-explorer-action";
+import { DataColumn } from "~/components/data-table/data-column";
+import { DataColumns } from "~/components/data-table/data-table";
+import { DataTableFilters } from '~/components/data-table-filters/data-table-filters-tree';
+
+interface Props {
+ id: string;
+ onRowClick: (item: any) => void;
+ onContextMenu?: (event: React.MouseEvent<HTMLElement>, item: any) => void;
+ onRowDoubleClick: (item: any) => void;
+ extractKey?: (item: any) => React.Key;
}
-class DataExplorer extends React.Component<DataExplorerProps, DataExplorerState> {
- state: DataExplorerState = {
- contextMenu: {},
- columns: [{
- name: "Name",
- selected: true,
- render: item => this.renderName(item)
- }, {
- name: "Status",
- selected: true,
- render: item => renderStatus(item.status)
- }, {
- name: "Type",
- selected: true,
- render: item => renderType(item.type)
- }, {
- name: "Owner",
- selected: true,
- render: item => renderOwner(item.owner)
- }, {
- name: "File size",
- selected: true,
- render: item => renderFileSize(item.fileSize)
- }, {
- name: "Last modified",
- selected: true,
- render: item => renderDate(item.lastModified)
- }, {
- name: "Actions",
- selected: true,
- configurable: false,
- renderHeader: () => null,
- render: item => this.renderActions(item)
- }]
- };
+const mapStateToProps = (state: RootState, { id }: Props) => {
+ const progress = state.progressIndicator.find(p => p.id === id);
+ const working = progress && progress.working;
+ return { ...getDataExplorer(state.dataExplorer, id), working };
+};
- contextMenuActions = [[{
- icon: "fas fa-users fa-fw",
- name: "Share",
- onClick: this.handleContextAction("onShare")
- }, {
- icon: "fas fa-sign-out-alt fa-fw",
- name: "Move to",
- onClick: this.handleContextAction("onMoveTo")
- }, {
- icon: "fas fa-star fa-fw",
- name: "Add to favourite",
- onClick: this.handleContextAction("onAddToFavourite")
- }, {
- icon: "fas fa-edit fa-fw",
- name: "Rename",
- onClick: this.handleContextAction("onRename")
- }, {
- icon: "fas fa-copy fa-fw",
- name: "Make a copy",
- onClick: this.handleContextAction("onCopy")
- }, {
- icon: "fas fa-download fa-fw",
- name: "Download",
- onClick: this.handleContextAction("onDownload")
- }], [{
- icon: "fas fa-trash-alt fa-fw",
- name: "Remove",
- onClick: this.handleContextAction("onRemove")
- }
- ]];
+const mapDispatchToProps = () => {
+ return (dispatch: Dispatch, { id, onRowClick, onRowDoubleClick, onContextMenu }: Props) => ({
+ onSetColumns: (columns: DataColumns<any>) => {
+ dispatch(dataExplorerActions.SET_COLUMNS({ id, columns }));
+ },
- render() {
- return <Paper>
- <ContextMenu
- {...this.state.contextMenu}
- actions={this.contextMenuActions}
- onClose={this.closeContextMenu} />
- <Toolbar>
- <Grid container justify="flex-end">
- <ColumnSelector
- columns={this.state.columns}
- onColumnToggle={this.toggleColumn} />
- </Grid>
- </Toolbar>
- <DataTable
- columns={this.state.columns}
- items={this.props.items}
- onRowContextMenu={this.openItemMenuOnRowClick} />
- <Toolbar />
- </Paper>;
- }
+ onSearch: (searchValue: string) => {
+ dispatch(dataExplorerActions.SET_EXPLORER_SEARCH_VALUE({ id, searchValue }));
+ },
- toggleColumn = (column: DataColumn<DataItem>) => {
- const index = this.state.columns.indexOf(column);
- const columns = this.state.columns.slice(0);
- columns.splice(index, 1, { ...column, selected: !column.selected });
- this.setState({ columns });
- }
+ onColumnToggle: (column: DataColumn<any>) => {
+ dispatch(dataExplorerActions.TOGGLE_COLUMN({ id, columnName: column.name }));
+ },
- renderName = (item: DataItem) =>
- <Grid
- container
- alignItems="center"
- wrap="nowrap"
- spacing={16}
- onClick={() => this.props.onItemClick(item)}>
- <Grid item>
- {renderIcon(item)}
- </Grid>
- <Grid item>
- <Typography color="primary">
- {item.name}
- </Typography>
- </Grid>
- </Grid>
+ onSortToggle: (column: DataColumn<any>) => {
+ dispatch(dataExplorerActions.TOGGLE_SORT({ id, columnName: column.name }));
+ },
- renderActions = (item: DataItem) =>
- <Grid container justify="flex-end">
- <IconButton onClick={event => this.openItemMenuOnActionsClick(event, item)}>
- <MoreVertIcon />
- </IconButton>
- </Grid>
+ onFiltersChange: (filters: DataTableFilters, column: DataColumn<any>) => {
+ dispatch(dataExplorerActions.SET_FILTERS({ id, columnName: column.name, filters }));
+ },
- openItemMenuOnRowClick = (event: React.MouseEvent<HTMLElement>, item: DataItem) => {
- event.preventDefault();
- this.setState({
- contextMenu: {
- anchorEl: mockAnchorFromMouseEvent(event),
- item
- }
- });
- }
+ onChangePage: (page: number) => {
+ dispatch(dataExplorerActions.SET_PAGE({ id, page }));
+ },
- openItemMenuOnActionsClick = (event: React.MouseEvent<HTMLElement>, item: DataItem) => {
- this.setState({
- contextMenu: {
- anchorEl: event.currentTarget,
- item
- }
- });
- }
+ onChangeRowsPerPage: (rowsPerPage: number) => {
+ dispatch(dataExplorerActions.SET_ROWS_PER_PAGE({ id, rowsPerPage }));
+ },
- closeContextMenu = () => {
- this.setState({ contextMenu: {} });
- }
+ onRowClick,
- handleContextAction(action: keyof DataExplorerContextActions) {
- return (item: DataItem) => {
- this.closeContextMenu();
- this.props.contextActions[action](item);
- };
- }
+ onRowDoubleClick,
-}
-
-const renderIcon = (dataItem: DataItem) => {
- switch (dataItem.type) {
- case ResourceKind.LEVEL_UP:
- return <i className="icon-level-up" style={{fontSize: "1rem"}}/>;
- case ResourceKind.PROJECT:
- return <i className="fas fa-folder fa-lg"/>;
- case ResourceKind.COLLECTION:
- return <i className="fas fa-th fa-lg"/>;
- default:
- return <i />;
- }
+ onContextMenu,
+ });
};
-const renderDate = (date: string) =>
- <Typography noWrap>
- {formatDate(date)}
- </Typography>;
-
-const renderFileSize = (fileSize?: number) =>
- <Typography noWrap>
- {formatFileSize(fileSize)}
- </Typography>;
-
-const renderOwner = (owner: string) =>
- <Typography noWrap color="primary">
- {owner}
- </Typography>;
-
-const renderType = (type: string) =>
- <Typography noWrap>
- {type}
- </Typography>;
-
-const renderStatus = (status?: string) =>
- <Typography noWrap align="center">
- {status || "-"}
- </Typography>;
+export const DataExplorer = connect(mapStateToProps, mapDispatchToProps())(DataExplorerComponent);
-export default DataExplorer;