[arvados-workbench2] updated: 2.6.0-22-gef8fb604

git repository hosting git at public.arvados.org
Tue May 9 15:25:41 UTC 2023


Summary of changes:
 src/components/data-explorer/data-explorer.tsx     |  12 +-
 .../data-table-multiselect-popover.tsx             |  18 +--
 src/components/data-table/data-table.tsx           |  12 +-
 .../multiselectToolbar/MultiselectToolbar.tsx      |  51 ++++++
 src/store/data-explorer/data-explorer-action.ts    |  77 ++++-----
 src/store/multiselect/multiselect-actions.tsx      |  13 ++
 src/store/multiselect/multiselect-reducer.tsx      |  18 +++
 src/store/store.ts                                 | 173 +++++++++------------
 .../data-explorer/data-explorer.tsx                |  29 ++--
 9 files changed, 225 insertions(+), 178 deletions(-)
 create mode 100644 src/components/multiselectToolbar/MultiselectToolbar.tsx
 create mode 100644 src/store/multiselect/multiselect-actions.tsx
 create mode 100644 src/store/multiselect/multiselect-reducer.tsx

       via  ef8fb604ad4a868cae8ed6ad31c1fd1520dd73e0 (commit)
       via  78a6653e701b8835ae9b4c674100ec12f6082167 (commit)
      from  5e0a0433e3ed3da21765735e0e83454bcc10b439 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit ef8fb604ad4a868cae8ed6ad31c1fd1520dd73e0
Author: Lisa Knox <lisaknox83 at gmail.com>
Date:   Tue May 9 11:25:34 2023 -0400

    15768: multiselect toolbar visibilty toggle Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa.knox at curii.com>

diff --git a/src/components/data-explorer/data-explorer.tsx b/src/components/data-explorer/data-explorer.tsx
index 16a014bc..82ce5603 100644
--- a/src/components/data-explorer/data-explorer.tsx
+++ b/src/components/data-explorer/data-explorer.tsx
@@ -52,6 +52,7 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
         width: '100%',
         float: 'right',
         display: 'flex',
+        flexDirection: 'row-reverse',
         justifyContent: 'space-between',
     },
 });
@@ -80,6 +81,7 @@ interface DataExplorerDataProps<T> {
     paperKey?: string;
     currentItemUuid: string;
     elementPath?: string;
+    isMSToolbarVisible: boolean;
 }
 
 interface DataExplorerActionProps<T> {
@@ -95,6 +97,7 @@ interface DataExplorerActionProps<T> {
     onChangeRowsPerPage: (rowsPerPage: number) => void;
     onLoadMore: (page: number) => void;
     extractKey?: (item: T) => React.Key;
+    toggleMSToolbar: (isVisible: boolean) => void;
 }
 
 type DataExplorerProps<T> = DataExplorerDataProps<T> & DataExplorerActionProps<T> & WithStyles<CssRules> & MPVPanelProps;
@@ -181,6 +184,8 @@ export const DataExplorer = withStyles(styles)(
                 panelName,
                 panelMaximized,
                 elementPath,
+                isMSToolbarVisible,
+                toggleMSToolbar,
             } = this.props;
             return (
                 <Paper className={classes.root} {...paperProps} key={paperKey} data-cy={this.props['data-cy']}>
@@ -193,7 +198,6 @@ export const DataExplorer = withStyles(styles)(
                             )}
                             {(!hideColumnSelector || !hideSearchInput || !!actions) && (
                                 <Grid className={classes.headerMenu} item xs>
-                                    <MultiselectToolbar />
                                     <Toolbar className={classes.toolbar}>
                                         {!hideSearchInput && (
                                             <div className={classes.searchBox}>
@@ -224,6 +228,7 @@ export const DataExplorer = withStyles(styles)(
                                             </Tooltip>
                                         )}
                                     </Toolbar>
+                                    {isMSToolbarVisible && <MultiselectToolbar />}
                                 </Grid>
                             )}
                         </div>
@@ -242,6 +247,7 @@ export const DataExplorer = withStyles(styles)(
                                 defaultViewMessages={defaultViewMessages}
                                 currentItemUuid={currentItemUuid}
                                 currentRoute={paperKey}
+                                toggleMSToolbar={toggleMSToolbar}
                             />
                         </Grid>
                         <Grid item xs>
diff --git a/src/components/data-table-multiselect-popover/data-table-multiselect-popover.tsx b/src/components/data-table-multiselect-popover/data-table-multiselect-popover.tsx
index 5c593251..ae2eda41 100644
--- a/src/components/data-table-multiselect-popover/data-table-multiselect-popover.tsx
+++ b/src/components/data-table-multiselect-popover/data-table-multiselect-popover.tsx
@@ -3,21 +3,7 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import React, { useEffect } from 'react';
-import {
-    WithStyles,
-    withStyles,
-    ButtonBase,
-    StyleRulesCallback,
-    Theme,
-    Popover,
-    Button,
-    Card,
-    CardActions,
-    Typography,
-    CardContent,
-    Tooltip,
-    IconButton,
-} from '@material-ui/core';
+import { WithStyles, withStyles, ButtonBase, StyleRulesCallback, Theme, Popover, Button, Card, CardActions, Tooltip, IconButton } from '@material-ui/core';
 import classnames from 'classnames';
 import { DefaultTransformOrigin } from 'components/popover/helpers';
 import debounce from 'lodash/debounce';
@@ -89,7 +75,7 @@ export const DataTableMultiselectPopover = withStyles(styles)(
         icon = React.createRef<HTMLElement>();
 
         render() {
-            const { name, classes, children, options, checkedList } = this.props;
+            const { classes, children, options, checkedList } = this.props;
             return (
                 <>
                     <Tooltip disableFocusListener title='Select Options'>
diff --git a/src/components/data-table/data-table.tsx b/src/components/data-table/data-table.tsx
index 4954bb6b..7f0e93ca 100644
--- a/src/components/data-table/data-table.tsx
+++ b/src/components/data-table/data-table.tsx
@@ -52,6 +52,7 @@ export interface DataTableDataProps<I> {
     defaultViewMessages?: string[];
     currentItemUuid?: string;
     currentRoute?: string;
+    toggleMSToolbar: (isVisible: boolean) => void;
 }
 
 type CssRules =
@@ -142,13 +143,14 @@ export const DataTable = withStyles(styles)(
         }
 
         componentDidUpdate(prevProps: Readonly<DataTableProps<T>>, prevState: DataTableState) {
-            const { items } = this.props;
+            const { items, toggleMSToolbar } = this.props;
             const { checkedList } = this.state;
             if (!arraysAreCongruent(prevProps.items, items)) {
                 this.state.isSelected = false;
                 this.initializeCheckedList(items);
             }
             if (prevState.checkedList !== checkedList) {
+                toggleMSToolbar(this.isAnySelected() ? true : false);
                 window.localStorage.setItem('selectedRows', JSON.stringify(checkedList));
             }
         }
@@ -198,6 +200,14 @@ export const DataTable = withStyles(styles)(
             return true;
         };
 
+        isAnySelected = (): boolean => {
+            const { checkedList } = this.state;
+            for (const key in checkedList) {
+                if (checkedList[key] === true) return true;
+            }
+            return false;
+        };
+
         handleCheck = (uuid: string): void => {
             const { checkedList } = this.state;
             const newCheckedList = { ...checkedList };
diff --git a/src/components/multiselectToolbar/MultiselectToolbar.tsx b/src/components/multiselectToolbar/MultiselectToolbar.tsx
index c71994af..46c33ee3 100644
--- a/src/components/multiselectToolbar/MultiselectToolbar.tsx
+++ b/src/components/multiselectToolbar/MultiselectToolbar.tsx
@@ -3,34 +3,49 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import React from 'react';
+import { connect } from 'react-redux';
 import { StyleRulesCallback, withStyles, WithStyles, Toolbar } from '@material-ui/core';
 import { ArvadosTheme } from 'common/custom-theme';
+import { RootState } from 'store/store';
 
 type CssRules = 'root' | 'item';
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     root: {
-        // border: '2px dotted green',
         display: 'flex',
         flexDirection: 'row',
     },
     item: {
-        // border: '2px dotted blue',
         color: theme.palette.text.primary,
         margin: '0.5rem',
     },
 });
 
+type MultiselectToolbarAction = {
+    name: string;
+    fn: () => void;
+};
+
+export type MultiselectToolbarActions = MultiselectToolbarAction[];
+
+// type MultiselectToolbarProps = MultiselectToolbarActions & WithStyles<CssRules>;
 type MultiselectToolbarProps = WithStyles<CssRules>;
 
-export default withStyles(styles)((props: MultiselectToolbarProps) => {
-    console.log(props);
-    const { classes } = props;
-    return (
-        <Toolbar className={classes.root}>
-            <div className={classes.item}>test1</div>
-            <div className={classes.item}>test2</div>
-            <div className={classes.item}>test3</div>
-        </Toolbar>
-    );
-});
+export default connect(mapStateToProps)(
+    withStyles(styles)((props: MultiselectToolbarProps) => {
+        const { classes } = props;
+        return (
+            <Toolbar className={classes.root}>
+                <div className={classes.item}>test1</div>
+                <div className={classes.item}>test2</div>
+                <div className={classes.item}>test3</div>
+            </Toolbar>
+        );
+    })
+);
+
+function mapStateToProps(state: RootState) {
+    return {
+        state: state,
+    };
+}
diff --git a/src/store/data-explorer/data-explorer-action.ts b/src/store/data-explorer/data-explorer-action.ts
index 22b786fd..387decf7 100644
--- a/src/store/data-explorer/data-explorer-action.ts
+++ b/src/store/data-explorer/data-explorer-action.ts
@@ -2,66 +2,51 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { unionize, ofType, UnionOf } from "common/unionize";
-import { DataColumns, DataTableFetchMode } from "components/data-table/data-table";
+import { unionize, ofType, UnionOf } from 'common/unionize';
+import { DataColumns, DataTableFetchMode } from 'components/data-table/data-table';
 import { DataTableFilters } from 'components/data-table-filters/data-table-filters-tree';
 
 export enum DataTableRequestState {
     IDLE,
     PENDING,
-    NEED_REFRESH
+    NEED_REFRESH,
 }
 
 export const dataExplorerActions = unionize({
     CLEAR: ofType<{ id: string }>(),
     RESET_PAGINATION: ofType<{ id: string }>(),
-    REQUEST_ITEMS: ofType<{ id: string, criteriaChanged?: boolean }>(),
-    REQUEST_STATE: ofType<{ id: string, criteriaChanged?: boolean }>(),
-    SET_FETCH_MODE: ofType<({ id: string, fetchMode: DataTableFetchMode })>(),
-    SET_COLUMNS: ofType<{ id: string, columns: DataColumns<any, any> }>(),
-    SET_FILTERS: ofType<{ id: string, columnName: string, filters: DataTableFilters }>(),
-    SET_ITEMS: ofType<{ id: string, items: any[], page: number, rowsPerPage: number, itemsAvailable: number }>(),
-    APPEND_ITEMS: ofType<{ id: string, items: any[], page: number, rowsPerPage: number, itemsAvailable: number }>(),
-    SET_PAGE: ofType<{ id: string, page: number }>(),
-    SET_ROWS_PER_PAGE: ofType<{ id: string, rowsPerPage: number }>(),
-    TOGGLE_COLUMN: ofType<{ id: string, columnName: string }>(),
-    TOGGLE_SORT: ofType<{ id: string, columnName: string }>(),
-    SET_EXPLORER_SEARCH_VALUE: ofType<{ id: string, searchValue: string }>(),
+    REQUEST_ITEMS: ofType<{ id: string; criteriaChanged?: boolean }>(),
+    REQUEST_STATE: ofType<{ id: string; criteriaChanged?: boolean }>(),
+    SET_FETCH_MODE: ofType<{ id: string; fetchMode: DataTableFetchMode }>(),
+    SET_COLUMNS: ofType<{ id: string; columns: DataColumns<any, any> }>(),
+    SET_FILTERS: ofType<{ id: string; columnName: string; filters: DataTableFilters }>(),
+    SET_ITEMS: ofType<{ id: string; items: any[]; page: number; rowsPerPage: number; itemsAvailable: number }>(),
+    APPEND_ITEMS: ofType<{ id: string; items: any[]; page: number; rowsPerPage: number; itemsAvailable: number }>(),
+    SET_PAGE: ofType<{ id: string; page: number }>(),
+    SET_ROWS_PER_PAGE: ofType<{ id: string; rowsPerPage: number }>(),
+    TOGGLE_COLUMN: ofType<{ id: string; columnName: string }>(),
+    TOGGLE_SORT: ofType<{ id: string; columnName: string }>(),
+    SET_EXPLORER_SEARCH_VALUE: ofType<{ id: string; searchValue: string }>(),
     RESET_EXPLORER_SEARCH_VALUE: ofType<{ id: string }>(),
-    SET_REQUEST_STATE: ofType<{ id: string, requestState: DataTableRequestState }>(),
+    SET_REQUEST_STATE: ofType<{ id: string; requestState: DataTableRequestState }>(),
 });
 
 export type DataExplorerAction = UnionOf<typeof dataExplorerActions>;
 
 export const bindDataExplorerActions = (id: string) => ({
-    CLEAR: () =>
-        dataExplorerActions.CLEAR({ id }),
-    RESET_PAGINATION: () =>
-        dataExplorerActions.RESET_PAGINATION({ id }),
-    REQUEST_ITEMS: (criteriaChanged?: boolean) =>
-        dataExplorerActions.REQUEST_ITEMS({ id, criteriaChanged }),
-    SET_FETCH_MODE: (payload: { fetchMode: DataTableFetchMode }) =>
-        dataExplorerActions.SET_FETCH_MODE({ ...payload, id }),
-    SET_COLUMNS: (payload: { columns: DataColumns<any, any> }) =>
-        dataExplorerActions.SET_COLUMNS({ ...payload, id }),
-    SET_FILTERS: (payload: { columnName: string, filters: DataTableFilters }) =>
-        dataExplorerActions.SET_FILTERS({ ...payload, id }),
-    SET_ITEMS: (payload: { items: any[], page: number, rowsPerPage: number, itemsAvailable: number }) =>
-        dataExplorerActions.SET_ITEMS({ ...payload, id }),
-    APPEND_ITEMS: (payload: { items: any[], page: number, rowsPerPage: number, itemsAvailable: number }) =>
-        dataExplorerActions.APPEND_ITEMS({ ...payload, id }),
-    SET_PAGE: (payload: { page: number }) =>
-        dataExplorerActions.SET_PAGE({ ...payload, id }),
-    SET_ROWS_PER_PAGE: (payload: { rowsPerPage: number }) =>
-        dataExplorerActions.SET_ROWS_PER_PAGE({ ...payload, id }),
-    TOGGLE_COLUMN: (payload: { columnName: string }) =>
-        dataExplorerActions.TOGGLE_COLUMN({ ...payload, id }),
-    TOGGLE_SORT: (payload: { columnName: string }) =>
-        dataExplorerActions.TOGGLE_SORT({ ...payload, id }),
-    SET_EXPLORER_SEARCH_VALUE: (payload: { searchValue: string }) =>
-        dataExplorerActions.SET_EXPLORER_SEARCH_VALUE({ ...payload, id }),
-    RESET_EXPLORER_SEARCH_VALUE: () =>
-        dataExplorerActions.RESET_EXPLORER_SEARCH_VALUE({ id }),
-    SET_REQUEST_STATE: (payload: { requestState: DataTableRequestState }) =>
-        dataExplorerActions.SET_REQUEST_STATE({ ...payload, id })
+    CLEAR: () => dataExplorerActions.CLEAR({ id }),
+    RESET_PAGINATION: () => dataExplorerActions.RESET_PAGINATION({ id }),
+    REQUEST_ITEMS: (criteriaChanged?: boolean) => dataExplorerActions.REQUEST_ITEMS({ id, criteriaChanged }),
+    SET_FETCH_MODE: (payload: { fetchMode: DataTableFetchMode }) => dataExplorerActions.SET_FETCH_MODE({ ...payload, id }),
+    SET_COLUMNS: (payload: { columns: DataColumns<any, any> }) => dataExplorerActions.SET_COLUMNS({ ...payload, id }),
+    SET_FILTERS: (payload: { columnName: string; filters: DataTableFilters }) => dataExplorerActions.SET_FILTERS({ ...payload, id }),
+    SET_ITEMS: (payload: { items: any[]; page: number; rowsPerPage: number; itemsAvailable: number }) => dataExplorerActions.SET_ITEMS({ ...payload, id }),
+    APPEND_ITEMS: (payload: { items: any[]; page: number; rowsPerPage: number; itemsAvailable: number }) => dataExplorerActions.APPEND_ITEMS({ ...payload, id }),
+    SET_PAGE: (payload: { page: number }) => dataExplorerActions.SET_PAGE({ ...payload, id }),
+    SET_ROWS_PER_PAGE: (payload: { rowsPerPage: number }) => dataExplorerActions.SET_ROWS_PER_PAGE({ ...payload, id }),
+    TOGGLE_COLUMN: (payload: { columnName: string }) => dataExplorerActions.TOGGLE_COLUMN({ ...payload, id }),
+    TOGGLE_SORT: (payload: { columnName: string }) => dataExplorerActions.TOGGLE_SORT({ ...payload, id }),
+    SET_EXPLORER_SEARCH_VALUE: (payload: { searchValue: string }) => dataExplorerActions.SET_EXPLORER_SEARCH_VALUE({ ...payload, id }),
+    RESET_EXPLORER_SEARCH_VALUE: () => dataExplorerActions.RESET_EXPLORER_SEARCH_VALUE({ id }),
+    SET_REQUEST_STATE: (payload: { requestState: DataTableRequestState }) => dataExplorerActions.SET_REQUEST_STATE({ ...payload, id }),
 });
diff --git a/src/store/multiselect/multiselect-actions.tsx b/src/store/multiselect/multiselect-actions.tsx
new file mode 100644
index 00000000..307423b5
--- /dev/null
+++ b/src/store/multiselect/multiselect-actions.tsx
@@ -0,0 +1,13 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export const multiselectActions = {
+    TOGGLE_VISIBLITY: 'TOGGLE_VISIBLITY',
+};
+
+export const toggleMSToolbar = (isVisible: boolean) => {
+    return (dispatch) => {
+        dispatch({ type: multiselectActions.TOGGLE_VISIBLITY, payload: isVisible });
+    };
+};
diff --git a/src/store/multiselect/multiselect-reducer.tsx b/src/store/multiselect/multiselect-reducer.tsx
new file mode 100644
index 00000000..212f416b
--- /dev/null
+++ b/src/store/multiselect/multiselect-reducer.tsx
@@ -0,0 +1,18 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { multiselectActions } from './multiselect-actions';
+
+type MultiselectToolbarState = {
+    isVisible: boolean;
+};
+
+const multiselectToolbarInitialState = {
+    isVisible: false,
+};
+
+export const multiselectReducer = (state: MultiselectToolbarState = multiselectToolbarInitialState, action) => {
+    if (action.type === multiselectActions.TOGGLE_VISIBLITY) return { ...state, isVisible: action.payload };
+    return state;
+};
diff --git a/src/store/store.ts b/src/store/store.ts
index 1501fd4f..b6edaaef 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -3,13 +3,13 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { createStore, applyMiddleware, compose, Middleware, combineReducers, Store, Action, Dispatch } from 'redux';
-import { routerMiddleware, routerReducer } from "react-router-redux";
+import { routerMiddleware, routerReducer } from 'react-router-redux';
 import thunkMiddleware from 'redux-thunk';
-import { History } from "history";
+import { History } from 'history';
 import { handleRedirects } from '../common/redirect-to';
 
-import { authReducer } from "./auth/auth-reducer";
-import { authMiddleware } from "./auth/auth-middleware";
+import { authReducer } from './auth/auth-reducer';
+import { authMiddleware } from './auth/auth-middleware';
 import { dataExplorerReducer } from './data-explorer/data-explorer-reducer';
 import { detailsPanelReducer } from './details-panel/details-panel-reducer';
 import { contextMenuReducer } from './context-menu/context-menu-reducer';
@@ -17,22 +17,22 @@ import { reducer as formReducer } from 'redux-form';
 import { favoritesReducer } from './favorites/favorites-reducer';
 import { snackbarReducer } from './snackbar/snackbar-reducer';
 import { collectionPanelFilesReducer } from './collection-panel/collection-panel-files/collection-panel-files-reducer';
-import { dataExplorerMiddleware } from "./data-explorer/data-explorer-middleware";
-import { FAVORITE_PANEL_ID } from "./favorite-panel/favorite-panel-action";
-import { PROJECT_PANEL_ID } from "./project-panel/project-panel-action";
-import { ProjectPanelMiddlewareService } from "./project-panel/project-panel-middleware-service";
-import { FavoritePanelMiddlewareService } from "./favorite-panel/favorite-panel-middleware-service";
-import { AllProcessesPanelMiddlewareService } from "./all-processes-panel/all-processes-panel-middleware-service";
+import { dataExplorerMiddleware } from './data-explorer/data-explorer-middleware';
+import { FAVORITE_PANEL_ID } from './favorite-panel/favorite-panel-action';
+import { PROJECT_PANEL_ID } from './project-panel/project-panel-action';
+import { ProjectPanelMiddlewareService } from './project-panel/project-panel-middleware-service';
+import { FavoritePanelMiddlewareService } from './favorite-panel/favorite-panel-middleware-service';
+import { AllProcessesPanelMiddlewareService } from './all-processes-panel/all-processes-panel-middleware-service';
 import { collectionPanelReducer } from './collection-panel/collection-panel-reducer';
 import { dialogReducer } from './dialog/dialog-reducer';
-import { ServiceRepository } from "services/services";
+import { ServiceRepository } from 'services/services';
 import { treePickerReducer, treePickerSearchReducer } from './tree-picker/tree-picker-reducer';
 import { treePickerSearchMiddleware } from './tree-picker/tree-picker-middleware';
 import { resourcesReducer } from 'store/resources/resources-reducer';
 import { propertiesReducer } from './properties/properties-reducer';
 import { fileUploaderReducer } from './file-uploader/file-uploader-reducer';
-import { TrashPanelMiddlewareService } from "store/trash-panel/trash-panel-middleware-service";
-import { TRASH_PANEL_ID } from "store/trash-panel/trash-panel-action";
+import { TrashPanelMiddlewareService } from 'store/trash-panel/trash-panel-middleware-service';
+import { TRASH_PANEL_ID } from 'store/trash-panel/trash-panel-action';
 import { processLogsPanelReducer } from './process-logs-panel/process-logs-panel-reducer';
 import { processPanelReducer } from 'store/process-panel/process-panel-reducer';
 import { SHARED_WITH_ME_PANEL_ID } from 'store/shared-with-me-panel/shared-with-me-panel-actions';
@@ -45,13 +45,13 @@ import { appInfoReducer } from 'store/app-info/app-info-reducer';
 import { searchBarReducer } from './search-bar/search-bar-reducer';
 import { SEARCH_RESULTS_PANEL_ID } from 'store/search-results-panel/search-results-panel-actions';
 import { SearchResultsMiddlewareService } from './search-results-panel/search-results-middleware-service';
-import { virtualMachinesReducer } from "store/virtual-machines/virtual-machines-reducer";
+import { virtualMachinesReducer } from 'store/virtual-machines/virtual-machines-reducer';
 import { repositoriesReducer } from 'store/repositories/repositories-reducer';
 import { keepServicesReducer } from 'store/keep-services/keep-services-reducer';
 import { UserMiddlewareService } from 'store/users/user-panel-middleware-service';
 import { USERS_PANEL_ID } from 'store/users/users-actions';
 import { UserProfileGroupsMiddlewareService } from 'store/user-profile/user-profile-groups-middleware-service';
-import { USER_PROFILE_PANEL_ID } from 'store/user-profile/user-profile-actions'
+import { USER_PROFILE_PANEL_ID } from 'store/user-profile/user-profile-actions';
 import { GroupsPanelMiddlewareService } from 'store/groups-panel/groups-panel-middleware-service';
 import { GROUPS_PANEL_ID } from 'store/groups-panel/groups-panel-actions';
 import { GroupDetailsPanelMembersMiddlewareService } from 'store/group-details-panel/group-details-panel-members-middleware-service';
@@ -75,8 +75,9 @@ import { Config } from 'common/config';
 import { pluginConfig } from 'plugins';
 import { MiddlewareListReducer } from 'common/plugintypes';
 import { tooltipsMiddleware } from './tooltips/tooltips-middleware';
-import { sidePanelReducer } from './side-panel/side-panel-reducer'
+import { sidePanelReducer } from './side-panel/side-panel-reducer';
 import { bannerReducer } from './banner/banner-reducer';
+import { multiselectReducer } from './multiselect/multiselect-reducer';
 
 declare global {
     interface Window {
@@ -84,10 +85,7 @@ declare global {
     }
 }
 
-const composeEnhancers =
-    (process.env.NODE_ENV === 'development' &&
-        window && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
-    compose;
+const composeEnhancers = (process.env.NODE_ENV === 'development' && window && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
 
 export type RootState = ReturnType<ReturnType<typeof createRootReducer>>;
 
@@ -96,57 +94,25 @@ export type RootStore = Store<RootState, Action> & { dispatch: Dispatch<any> };
 export function configureStore(history: History, services: ServiceRepository, config: Config): RootStore {
     const rootReducer = createRootReducer(services);
 
-    const projectPanelMiddleware = dataExplorerMiddleware(
-        new ProjectPanelMiddlewareService(services, PROJECT_PANEL_ID)
-    );
-    const favoritePanelMiddleware = dataExplorerMiddleware(
-        new FavoritePanelMiddlewareService(services, FAVORITE_PANEL_ID)
-    );
-    const allProcessessPanelMiddleware = dataExplorerMiddleware(
-        new AllProcessesPanelMiddlewareService(services, ALL_PROCESSES_PANEL_ID)
-    );
-    const trashPanelMiddleware = dataExplorerMiddleware(
-        new TrashPanelMiddlewareService(services, TRASH_PANEL_ID)
-    );
-    const searchResultsPanelMiddleware = dataExplorerMiddleware(
-        new SearchResultsMiddlewareService(services, SEARCH_RESULTS_PANEL_ID)
-    );
-    const sharedWithMePanelMiddleware = dataExplorerMiddleware(
-        new SharedWithMeMiddlewareService(services, SHARED_WITH_ME_PANEL_ID)
-    );
-    const workflowPanelMiddleware = dataExplorerMiddleware(
-        new WorkflowMiddlewareService(services, WORKFLOW_PANEL_ID)
-    );
-    const userPanelMiddleware = dataExplorerMiddleware(
-        new UserMiddlewareService(services, USERS_PANEL_ID)
-    );
-    const userProfileGroupsMiddleware = dataExplorerMiddleware(
-        new UserProfileGroupsMiddlewareService(services, USER_PROFILE_PANEL_ID)
-    );
-    const groupsPanelMiddleware = dataExplorerMiddleware(
-        new GroupsPanelMiddlewareService(services, GROUPS_PANEL_ID)
-    );
-    const groupDetailsPanelMembersMiddleware = dataExplorerMiddleware(
-        new GroupDetailsPanelMembersMiddlewareService(services, GROUP_DETAILS_MEMBERS_PANEL_ID)
-    );
+    const projectPanelMiddleware = dataExplorerMiddleware(new ProjectPanelMiddlewareService(services, PROJECT_PANEL_ID));
+    const favoritePanelMiddleware = dataExplorerMiddleware(new FavoritePanelMiddlewareService(services, FAVORITE_PANEL_ID));
+    const allProcessessPanelMiddleware = dataExplorerMiddleware(new AllProcessesPanelMiddlewareService(services, ALL_PROCESSES_PANEL_ID));
+    const trashPanelMiddleware = dataExplorerMiddleware(new TrashPanelMiddlewareService(services, TRASH_PANEL_ID));
+    const searchResultsPanelMiddleware = dataExplorerMiddleware(new SearchResultsMiddlewareService(services, SEARCH_RESULTS_PANEL_ID));
+    const sharedWithMePanelMiddleware = dataExplorerMiddleware(new SharedWithMeMiddlewareService(services, SHARED_WITH_ME_PANEL_ID));
+    const workflowPanelMiddleware = dataExplorerMiddleware(new WorkflowMiddlewareService(services, WORKFLOW_PANEL_ID));
+    const userPanelMiddleware = dataExplorerMiddleware(new UserMiddlewareService(services, USERS_PANEL_ID));
+    const userProfileGroupsMiddleware = dataExplorerMiddleware(new UserProfileGroupsMiddlewareService(services, USER_PROFILE_PANEL_ID));
+    const groupsPanelMiddleware = dataExplorerMiddleware(new GroupsPanelMiddlewareService(services, GROUPS_PANEL_ID));
+    const groupDetailsPanelMembersMiddleware = dataExplorerMiddleware(new GroupDetailsPanelMembersMiddlewareService(services, GROUP_DETAILS_MEMBERS_PANEL_ID));
     const groupDetailsPanelPermissionsMiddleware = dataExplorerMiddleware(
         new GroupDetailsPanelPermissionsMiddlewareService(services, GROUP_DETAILS_PERMISSIONS_PANEL_ID)
     );
-    const linkPanelMiddleware = dataExplorerMiddleware(
-        new LinkMiddlewareService(services, LINK_PANEL_ID)
-    );
-    const apiClientAuthorizationMiddlewareService = dataExplorerMiddleware(
-        new ApiClientAuthorizationMiddlewareService(services, API_CLIENT_AUTHORIZATION_PANEL_ID)
-    );
-    const publicFavoritesMiddleware = dataExplorerMiddleware(
-        new PublicFavoritesMiddlewareService(services, PUBLIC_FAVORITE_PANEL_ID)
-    );
-    const collectionsContentAddress = dataExplorerMiddleware(
-        new CollectionsWithSameContentAddressMiddlewareService(services, COLLECTIONS_CONTENT_ADDRESS_PANEL_ID)
-    );
-    const subprocessMiddleware = dataExplorerMiddleware(
-        new SubprocessMiddlewareService(services, SUBPROCESS_PANEL_ID)
-    );
+    const linkPanelMiddleware = dataExplorerMiddleware(new LinkMiddlewareService(services, LINK_PANEL_ID));
+    const apiClientAuthorizationMiddlewareService = dataExplorerMiddleware(new ApiClientAuthorizationMiddlewareService(services, API_CLIENT_AUTHORIZATION_PANEL_ID));
+    const publicFavoritesMiddleware = dataExplorerMiddleware(new PublicFavoritesMiddlewareService(services, PUBLIC_FAVORITE_PANEL_ID));
+    const collectionsContentAddress = dataExplorerMiddleware(new CollectionsWithSameContentAddressMiddlewareService(services, COLLECTIONS_CONTENT_ADDRESS_PANEL_ID));
+    const subprocessMiddleware = dataExplorerMiddleware(new SubprocessMiddlewareService(services, SUBPROCESS_PANEL_ID));
     const redirectToMiddleware = (store: any) => (next: any) => (action: any) => {
         const state = store.getState();
 
@@ -179,11 +145,10 @@ export function configureStore(history: History, services: ServiceRepository, co
         publicFavoritesMiddleware,
         collectionsContentAddress,
         subprocessMiddleware,
-        treePickerSearchMiddleware
+        treePickerSearchMiddleware,
     ];
 
-    const reduceMiddlewaresFn: (a: Middleware[],
-        b: MiddlewareListReducer) => Middleware[] = (a, b) => b(a, services);
+    const reduceMiddlewaresFn: (a: Middleware[], b: MiddlewareListReducer) => Middleware[] = (a, b) => b(a, services);
 
     middlewares = pluginConfig.middlewares.reduce(reduceMiddlewaresFn, middlewares);
 
@@ -191,35 +156,37 @@ export function configureStore(history: History, services: ServiceRepository, co
     return createStore(rootReducer, enhancer);
 }
 
-const createRootReducer = (services: ServiceRepository) => combineReducers({
-    auth: authReducer(services),
-    banner: bannerReducer,
-    collectionPanel: collectionPanelReducer,
-    collectionPanelFiles: collectionPanelFilesReducer,
-    contextMenu: contextMenuReducer,
-    dataExplorer: dataExplorerReducer,
-    detailsPanel: detailsPanelReducer,
-    dialog: dialogReducer,
-    favorites: favoritesReducer,
-    ownerName: ownerNameReducer,
-    publicFavorites: publicFavoritesReducer,
-    form: formReducer,
-    processLogsPanel: processLogsPanelReducer,
-    properties: propertiesReducer,
-    resources: resourcesReducer,
-    router: routerReducer,
-    snackbar: snackbarReducer,
-    treePicker: treePickerReducer,
-    treePickerSearch: treePickerSearchReducer,
-    fileUploader: fileUploaderReducer,
-    processPanel: processPanelReducer,
-    progressIndicator: progressIndicatorReducer,
-    runProcessPanel: runProcessPanelReducer,
-    appInfo: appInfoReducer,
-    searchBar: searchBarReducer,
-    virtualMachines: virtualMachinesReducer,
-    repositories: repositoriesReducer,
-    keepServices: keepServicesReducer,
-    linkAccountPanel: linkAccountPanelReducer,
-    sidePanel: sidePanelReducer
-});
+const createRootReducer = (services: ServiceRepository) =>
+    combineReducers({
+        auth: authReducer(services),
+        banner: bannerReducer,
+        collectionPanel: collectionPanelReducer,
+        collectionPanelFiles: collectionPanelFilesReducer,
+        contextMenu: contextMenuReducer,
+        dataExplorer: dataExplorerReducer,
+        detailsPanel: detailsPanelReducer,
+        dialog: dialogReducer,
+        favorites: favoritesReducer,
+        ownerName: ownerNameReducer,
+        publicFavorites: publicFavoritesReducer,
+        form: formReducer,
+        processLogsPanel: processLogsPanelReducer,
+        properties: propertiesReducer,
+        resources: resourcesReducer,
+        router: routerReducer,
+        snackbar: snackbarReducer,
+        treePicker: treePickerReducer,
+        treePickerSearch: treePickerSearchReducer,
+        fileUploader: fileUploaderReducer,
+        processPanel: processPanelReducer,
+        progressIndicator: progressIndicatorReducer,
+        runProcessPanel: runProcessPanelReducer,
+        appInfo: appInfoReducer,
+        searchBar: searchBarReducer,
+        virtualMachines: virtualMachinesReducer,
+        repositories: repositoriesReducer,
+        keepServices: keepServicesReducer,
+        linkAccountPanel: linkAccountPanelReducer,
+        sidePanel: sidePanelReducer,
+        multiselect: multiselectReducer,
+    });
diff --git a/src/views-components/data-explorer/data-explorer.tsx b/src/views-components/data-explorer/data-explorer.tsx
index 59c389ac..be19319b 100644
--- a/src/views-components/data-explorer/data-explorer.tsx
+++ b/src/views-components/data-explorer/data-explorer.tsx
@@ -2,16 +2,17 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-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 { 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';
-import { LAST_REFRESH_TIMESTAMP } from "components/refresh-button/refresh-button";
+import { LAST_REFRESH_TIMESTAMP } from 'components/refresh-button/refresh-button';
+import { toggleMSToolbar } from 'store/multiselect/multiselect-actions';
 
 interface Props {
     id: string;
@@ -22,11 +23,12 @@ interface Props {
 }
 
 const mapStateToProps = (state: RootState, { id }: Props) => {
-    const progress = state.progressIndicator.find(p => p.id === id);
+    const progress = state.progressIndicator.find((p) => p.id === id);
     const dataExplorerState = getDataExplorer(state.dataExplorer, id);
     const currentRoute = state.router.location ? state.router.location.pathname : '';
     const currentRefresh = localStorage.getItem(LAST_REFRESH_TIMESTAMP) || '';
     const currentItemUuid = currentRoute === '/workflows' ? state.properties.workflowPanelDetailsUuid : state.detailsPanel.resourceUuid;
+    const isMSToolbarVisible = state.multiselect.isVisible;
     return {
         ...dataExplorerState,
         working: !!progress?.working,
@@ -34,10 +36,11 @@ const mapStateToProps = (state: RootState, { id }: Props) => {
         currentRoute: currentRoute,
         paperKey: currentRoute,
         currentItemUuid,
+        isMSToolbarVisible,
     };
 };
 
-const mapDispatchToProps = () => {
+const mapDispatchToProps = (dispatchFn) => {
     return (dispatch: Dispatch, { id, onRowClick, onRowDoubleClick, onContextMenu }: Props) => ({
         onSetColumns: (columns: DataColumns<any, any>) => {
             dispatch(dataExplorerActions.SET_COLUMNS({ id, columns }));
@@ -71,6 +74,10 @@ const mapDispatchToProps = () => {
             dispatch(dataExplorerActions.SET_PAGE({ id, page }));
         },
 
+        toggleMSToolbar: (isVisible: boolean) => {
+            dispatchFn(toggleMSToolbar(isVisible));
+        },
+
         onRowClick,
 
         onRowDoubleClick,

commit 78a6653e701b8835ae9b4c674100ec12f6082167
Author: Lisa Knox <lisaknox83 at gmail.com>
Date:   Mon May 8 12:55:03 2023 -0400

    15768: created multiselect toolbar Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa.knox at curii.com>

diff --git a/src/components/data-explorer/data-explorer.tsx b/src/components/data-explorer/data-explorer.tsx
index ea95648e..16a014bc 100644
--- a/src/components/data-explorer/data-explorer.tsx
+++ b/src/components/data-explorer/data-explorer.tsx
@@ -14,6 +14,7 @@ import { DataTableFilters } from 'components/data-table-filters/data-table-filte
 import { CloseIcon, IconType, MaximizeIcon, UnMaximizeIcon, MoreOptionsIcon } from 'components/icon/icon';
 import { PaperProps } from '@material-ui/core/Paper';
 import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
+import MultiselectToolbar from 'components/multiselectToolbar/MultiselectToolbar';
 
 type CssRules = 'searchBox' | 'headerMenu' | 'toolbar' | 'footer' | 'root' | 'moreOptionsButton' | 'title' | 'dataTable' | 'container';
 
@@ -48,8 +49,10 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
         height: '100%',
     },
     headerMenu: {
+        width: '100%',
         float: 'right',
-        display: 'inline-block',
+        display: 'flex',
+        justifyContent: 'space-between',
     },
 });
 
@@ -190,6 +193,7 @@ export const DataExplorer = withStyles(styles)(
                             )}
                             {(!hideColumnSelector || !hideSearchInput || !!actions) && (
                                 <Grid className={classes.headerMenu} item xs>
+                                    <MultiselectToolbar />
                                     <Toolbar className={classes.toolbar}>
                                         {!hideSearchInput && (
                                             <div className={classes.searchBox}>
diff --git a/src/components/multiselectToolbar/MultiselectToolbar.tsx b/src/components/multiselectToolbar/MultiselectToolbar.tsx
new file mode 100644
index 00000000..c71994af
--- /dev/null
+++ b/src/components/multiselectToolbar/MultiselectToolbar.tsx
@@ -0,0 +1,36 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { StyleRulesCallback, withStyles, WithStyles, Toolbar } from '@material-ui/core';
+import { ArvadosTheme } from 'common/custom-theme';
+
+type CssRules = 'root' | 'item';
+
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+    root: {
+        // border: '2px dotted green',
+        display: 'flex',
+        flexDirection: 'row',
+    },
+    item: {
+        // border: '2px dotted blue',
+        color: theme.palette.text.primary,
+        margin: '0.5rem',
+    },
+});
+
+type MultiselectToolbarProps = WithStyles<CssRules>;
+
+export default withStyles(styles)((props: MultiselectToolbarProps) => {
+    console.log(props);
+    const { classes } = props;
+    return (
+        <Toolbar className={classes.root}>
+            <div className={classes.item}>test1</div>
+            <div className={classes.item}>test2</div>
+            <div className={classes.item}>test3</div>
+        </Toolbar>
+    );
+});

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list