X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/8e7e7f4a4972c44f2f4a4692953bfbe35ebcdf84..0eea0b8a51ffec0c7e975932c029e4bd9a1d6b7e:/services/workbench2/src/components/data-table/data-table.tsx diff --git a/services/workbench2/src/components/data-table/data-table.tsx b/services/workbench2/src/components/data-table/data-table.tsx index de3e272d1e..ae05353b4c 100644 --- a/services/workbench2/src/components/data-table/data-table.tsx +++ b/services/workbench2/src/components/data-table/data-table.tsx @@ -24,11 +24,13 @@ import { DataTableFilters } from "../data-table-filters/data-table-filters-tree" import { DataTableMultiselectPopover } from "../data-table-multiselect-popover/data-table-multiselect-popover"; import { DataTableFiltersPopover } from "../data-table-filters/data-table-filters-popover"; import { countNodes, getTreeDirty } from "models/tree"; -import { IconType, PendingIcon } from "components/icon/icon"; +import { IconType } from "components/icon/icon"; import { SvgIconProps } from "@material-ui/core/SvgIcon"; import ArrowDownwardIcon from "@material-ui/icons/ArrowDownward"; import { createTree } from "models/tree"; import { DataTableMultiselectOption } from "../data-table-multiselect-popover/data-table-multiselect-popover"; +import { isExactlyOneSelected } from "store/multiselect/multiselect-actions"; +import { PendingIcon } from "components/icon/icon"; export type DataColumns = Array>; @@ -49,11 +51,14 @@ export interface DataTableDataProps { working?: boolean; defaultViewIcon?: IconType; defaultViewMessages?: string[]; - currentItemUuid?: string; - currentRoute?: string; toggleMSToolbar: (isVisible: boolean) => void; setCheckedListOnStore: (checkedList: TCheckedList) => void; + currentRoute?: string; + currentRouteUuid: string; checkedList: TCheckedList; + selectedResourceUuid: string; + setSelectedUuid: (uuid: string | null) => void; + isNotFound?: boolean; } type CssRules = @@ -63,13 +68,13 @@ type CssRules = | "noItemsInfo" | "checkBoxHead" | "checkBoxCell" + | "clickBox" | "checkBox" | "firstTableCell" | "tableCell" | "arrow" | "arrowButton" - | "tableCellWorkflows" - | "loader"; + | "tableCellWorkflows"; const styles: StyleRulesCallback = (theme: Theme) => ({ root: { @@ -82,11 +87,6 @@ const styles: StyleRulesCallback = (theme: Theme) => ({ tableBody: { background: theme.palette.background.paper, }, - loader: { - left: "50%", - marginLeft: "-84px", - position: "absolute", - }, noItemsInfo: { textAlign: "center", padding: theme.spacing.unit, @@ -94,10 +94,22 @@ const styles: StyleRulesCallback = (theme: Theme) => ({ checkBoxHead: { padding: "0", display: "flex", + width: '2rem', + height: "1.5rem", + paddingLeft: '0.9rem', + marginRight: '0.5rem' }, checkBoxCell: { padding: "0", - paddingLeft: "10px", + }, + clickBox: { + display: 'flex', + width: '1.6rem', + height: "1.5rem", + paddingLeft: '0.35rem', + paddingTop: '0.1rem', + marginLeft: '0.5rem', + cursor: "pointer", }, checkBox: { cursor: "pointer", @@ -133,6 +145,7 @@ export type TCheckedList = Record; type DataTableState = { isSelected: boolean; + isLoaded: boolean; }; type DataTableProps = DataTableDataProps & WithStyles; @@ -141,27 +154,50 @@ export const DataTable = withStyles(styles)( class Component extends React.Component> { state: DataTableState = { isSelected: false, + isLoaded: false, }; componentDidMount(): void { this.initializeCheckedList([]); + // If table is initialized loaded but empty + // isLoaded won't be set true by componentDidUpdate later + // So we set it to true here + if (!this.props.working) { + this.setState({ isLoaded: true }); + } } componentDidUpdate(prevProps: Readonly>, prevState: DataTableState) { - const { items, setCheckedListOnStore } = this.props; + const { items, currentRouteUuid, setCheckedListOnStore } = this.props; const { isSelected } = this.state; + const singleSelected = isExactlyOneSelected(this.props.checkedList); if (prevProps.items !== items) { if (isSelected === true) this.setState({ isSelected: false }); if (items.length) this.initializeCheckedList(items); else setCheckedListOnStore({}); } if (prevProps.currentRoute !== this.props.currentRoute) { - this.initializeCheckedList([]) + this.initializeCheckedList([]); + } + if (singleSelected && singleSelected !== isExactlyOneSelected(prevProps.checkedList)) { + this.props.setSelectedUuid(singleSelected); + } + if (!singleSelected && !!currentRouteUuid && !this.isAnySelected()) { + this.props.setSelectedUuid(currentRouteUuid); + } + if (!singleSelected && this.isAnySelected()) { + this.props.setSelectedUuid(null); + } + if(prevProps.working === true && this.props.working === false) { + this.setState({ isLoaded: true }); + } + if((this.props.items.length > 0) && !this.state.isLoaded) { + this.setState({ isLoaded: true }); } } componentWillUnmount(): void { - this.initializeCheckedList([]) + this.initializeCheckedList([]); } checkBoxColumn: DataColumn = { @@ -172,14 +208,24 @@ export const DataTable = withStyles(styles)( render: uuid => { const { classes, checkedList } = this.props; return ( - this.handleSelectOne(uuid)} - onDoubleClick={ev => ev.stopPropagation()}> +
{ + ev.stopPropagation() + this.handleSelectOne(uuid) + }} + onDoubleClick={(ev) => ev.stopPropagation()} + > + this.handleSelectOne(uuid)} + onDoubleClick={(ev) => ev.stopPropagation()} + > +
); }, }; @@ -193,11 +239,12 @@ export const DataTable = withStyles(styles)( initializeCheckedList = (uuids: any[]): void => { const newCheckedList = { ...this.props.checkedList }; - uuids.forEach(uuid => { - if (!newCheckedList.hasOwnProperty(uuid)) { - newCheckedList[uuid] = false; + if(Object.keys(newCheckedList).length === 0){ + for(const uuid of uuids){ + newCheckedList[uuid] = false } - }); + } + for (const key in newCheckedList) { if (!uuids.includes(key)) { delete newCheckedList[key]; @@ -268,8 +315,9 @@ export const DataTable = withStyles(styles)( }; render() { - const { items, classes, working, columns } = this.props; - if (columns[0].name === this.checkBoxColumn.name) columns.shift(); + const { items, classes, columns, isNotFound } = this.props; + const { isLoaded } = this.state; + if (columns.length && columns[0].name === this.checkBoxColumn.name) columns.shift(); columns.unshift(this.checkBoxColumn); return (
@@ -278,31 +326,43 @@ export const DataTable = withStyles(styles)( {this.mapVisibleColumns(this.renderHeadCell)} - {!working && items.map(this.renderBodyRow)} + {(isLoaded && !isNotFound) && items.map(this.renderBodyRow)} - {!!working && ( -
- -
- )} - {items.length === 0 && !working && this.renderNoItemsPlaceholder(this.props.columns)} + {(!isLoaded || isNotFound || items.length === 0) && this.renderNoItemsPlaceholder(this.props.columns)}
); } renderNoItemsPlaceholder = (columns: DataColumns) => { + const { isLoaded } = this.state; + const { working, isNotFound } = this.props; const dirty = columns.some(column => getTreeDirty("")(column.filters)); - return ( - - ); + if (isNotFound && isLoaded) { + return ( + + ); + } else + if (isLoaded === false || working === true) { + return ( + + ); + } else { + // isLoaded && !working && !isNotFound + return ( + + ); + } }; renderHeadCell = (column: DataColumn, index: number) => { @@ -314,7 +374,7 @@ export const DataTable = withStyles(styles)( key={key || index} className={classes.checkBoxCell}>
- + { - const { onRowClick, onRowDoubleClick, extractKey, classes, currentItemUuid, currentRoute } = this.props; + const { onRowClick, onRowDoubleClick, extractKey, classes, selectedResourceUuid, currentRoute } = this.props; return ( onRowClick && onRowClick(event, item)} onContextMenu={this.handleRowContextMenu(item)} onDoubleClick={event => onRowDoubleClick && onRowDoubleClick(event, item)} - selected={item === currentItemUuid}> + selected={item === selectedResourceUuid}> {this.mapVisibleColumns((column, index) => (