21386: project 404 vs empty working Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa...
authorLisa Knox <lisaknox83@gmail.com>
Tue, 20 Feb 2024 17:13:04 +0000 (12:13 -0500)
committerLisa Knox <lisaknox83@gmail.com>
Tue, 20 Feb 2024 17:13:04 +0000 (12:13 -0500)
services/workbench2/src/components/data-explorer/data-explorer.tsx
services/workbench2/src/components/data-table/data-table.tsx
services/workbench2/src/store/data-explorer/data-explorer-action.ts
services/workbench2/src/store/data-explorer/data-explorer-reducer.ts
services/workbench2/src/store/project-panel/project-panel-middleware-service.ts
services/workbench2/src/store/search-results-panel/search-results-middleware-service.ts
services/workbench2/src/views-components/data-explorer/data-explorer.tsx
services/workbench2/src/views/project-panel/project-panel.tsx

index 1f9fb42d6baddd443d026f5d5b9c9b5c7e3064e1..5d3fba3a6104b6aff428b96702e82e3782019584 100644 (file)
@@ -97,6 +97,7 @@ interface DataExplorerDataProps<T> {
     elementPath?: string;
     isMSToolbarVisible: boolean;
     checkedList: TCheckedList;
+    is404?: boolean;
 }
 
 interface DataExplorerActionProps<T> {
@@ -121,7 +122,6 @@ type DataExplorerProps<T> = DataExplorerDataProps<T> & DataExplorerActionProps<T
 type DataExplorerState = {
     prevRefresh: string;
     prevRoute: string;
-    notFound: boolean;
 };
 
 export const DataExplorer = withStyles(styles)(
@@ -129,7 +129,6 @@ export const DataExplorer = withStyles(styles)(
         state: DataExplorerState = {
             prevRefresh: "",
             prevRoute: "",
-            notFound: false,
         };
 
         multiSelectToolbarInTitle = !this.props.title && !this.props.progressBar;
@@ -153,18 +152,6 @@ export const DataExplorer = withStyles(styles)(
                     prevRefresh: currentRefresh,
                 });
             }
-
-            if(this.state.notFound === true && this.props.itemsAvailable > 0) {
-                this.setState({
-                    notFound: false,
-                });
-            }
-
-            if (prevProps.working === true && this.props.working === false) {
-                this.setState({
-                    notFound: this.props.itemsAvailable === 0,
-                });
-            }
         }
 
         componentDidMount() {
@@ -333,7 +320,7 @@ export const DataExplorer = withStyles(styles)(
                                 setCheckedListOnStore={setCheckedListOnStore}
                                 checkedList={checkedList}
                                 working={working}
-                                notFound={this.state.notFound}
+                                is404={this.props.is404}
                             />
                         </Grid>
                         <Grid
index f9ab7f0a25c9927ab905af0dd20a3ee221bfd26d..d1c7e1fc9d55758099fb96e18b678d3665b7f321 100644 (file)
@@ -54,7 +54,7 @@ export interface DataTableDataProps<I> {
     toggleMSToolbar: (isVisible: boolean) => void;
     setCheckedListOnStore: (checkedList: TCheckedList) => void;
     checkedList: TCheckedList;
-    notFound?: boolean;
+    is404?: boolean;
 }
 
 type CssRules =
@@ -141,6 +141,7 @@ export type TCheckedList = Record<string, boolean>;
 
 type DataTableState = {
     isSelected: boolean;
+    isLoaded: boolean;
 };
 
 type DataTableProps<T> = DataTableDataProps<T> & WithStyles<CssRules>;
@@ -149,6 +150,7 @@ export const DataTable = withStyles(styles)(
     class Component<T> extends React.Component<DataTableProps<T>> {
         state: DataTableState = {
             isSelected: false,
+            isLoaded: false,
         };
 
         componentDidMount(): void {
@@ -166,6 +168,9 @@ export const DataTable = withStyles(styles)(
             if (prevProps.currentRoute !== this.props.currentRoute) {
                 this.initializeCheckedList([])
             }
+            if(prevProps.working === true && this.props.working === false) {
+                this.setState({ isLoaded: true });
+            }
         }
 
         componentWillUnmount(): void {
@@ -286,7 +291,8 @@ export const DataTable = withStyles(styles)(
         };
 
         render() {
-            const { items, classes, working, columns, notFound } = this.props;
+            const { items, classes, working, columns, is404 } = this.props;
+            const { isLoaded } = this.state;
             if (columns[0].name === this.checkBoxColumn.name) columns.shift();
             columns.unshift(this.checkBoxColumn);
             return (
@@ -296,25 +302,24 @@ export const DataTable = withStyles(styles)(
                             <TableHead>
                                 <TableRow>{this.mapVisibleColumns(this.renderHeadCell)}</TableRow>
                             </TableHead>
-                            <TableBody className={classes.tableBody}>{(!working && !notFound) && items.map(this.renderBodyRow)}</TableBody>
+                            <TableBody className={classes.tableBody}>{(isLoaded && !is404) && items.map(this.renderBodyRow)}</TableBody>
                         </Table>
-                        {(working || notFound) && this.renderNoItemsPlaceholder(this.props.columns)}
+                        {(!isLoaded || is404 || items.length === 0) && this.renderNoItemsPlaceholder(this.props.columns)}
                     </div>
                 </div>
             );
         }
 
         renderNoItemsPlaceholder = (columns: DataColumns<T, any>) => {
-            const { working, notFound } = this.props;
             const dirty = columns.some(column => getTreeDirty("")(column.filters));
-            if (working) {
+            if (this.state.isLoaded === false) {
                 return (
                     <DataTableDefaultView 
                         icon={this.props.defaultViewIcon} 
                         messages={["Loading data, please wait"]} 
                     />
                 );
-            } else if (notFound) {
+            } else if (this.props.is404) {
                 return (
                     <DataTableDefaultView 
                         icon={this.props.defaultViewIcon} 
index ea050e609f558a91decb73ac7badd65fe18f7d3f..5a7ad22b8fe24b373b4ea50b80eb899974a5fc02 100644 (file)
@@ -29,6 +29,7 @@ export const dataExplorerActions = unionize({
     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_IS_RESPONSE_404: ofType<{ id: string; isResponse404: boolean }>(),
 });
 
 export type DataExplorerAction = UnionOf<typeof dataExplorerActions>;
@@ -51,4 +52,5 @@ export const bindDataExplorerActions = (id: string) => ({
     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 }),
+    SET_IS_RESPONSE_404: (payload: { isResponse404: boolean }) => dataExplorerActions.SET_IS_RESPONSE_404({ ...payload, id }),
 });
index a0a7eb6400b1160f0702d2e4243b94912c85bfa1..b50eabd69ac11d7da6b670bef0e614d95630a20d 100644 (file)
@@ -30,6 +30,7 @@ export interface DataExplorer {
     searchValue: string;
     working?: boolean;
     requestState: DataTableRequestState;
+    isResponse404: boolean;
 }
 
 export const initialDataExplorer: DataExplorer = {
@@ -42,6 +43,7 @@ export const initialDataExplorer: DataExplorer = {
     rowsPerPageOptions: [10, 20, 50, 100, 200, 500],
     searchValue: '',
     requestState: DataTableRequestState.IDLE,
+    isResponse404: false,
 };
 
 export type DataExplorerState = Record<string, DataExplorer>;
@@ -119,6 +121,9 @@ export const dataExplorerReducer = (
         TOGGLE_COLUMN: ({ id, columnName }) =>
             update(state, id, mapColumns(toggleColumn(columnName))),
 
+        SET_IS_RESPONSE_404: ({ id, isResponse404 }) =>
+            update(state, id, (explorer) => ({ ...explorer, isResponse404 })),
+
         default: () => state,
     });
 };
index 366e15ae04759e2a774563d8307fa8c4449eb8fe..7ff0a58a3fdbb2ac678c95b4ff8d7a0e00b03334 100644 (file)
@@ -37,6 +37,7 @@ import { defaultCollectionSelectedFields } from "models/collection";
 import { containerRequestFieldsNoMounts } from "models/container-request";
 import { MultiSelectMenuActionNames } from "views-components/multiselect-toolbar/ms-menu-actions";
 import { removeDisabledButton } from "store/multiselect/multiselect-actions";
+import { dataExplorerActions } from "store/data-explorer/data-explorer-action";
 
 export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService {
     constructor(private services: ServiceRepository, id: string) {
@@ -54,6 +55,7 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService
             api.dispatch(projectPanelDataExplorerIsNotSet());
         } else {
             try {
+                api.dispatch<any>(dataExplorerActions.SET_IS_RESPONSE_404({ id: this.id, isResponse404: false }));
                 if (!background) { api.dispatch(progressIndicatorActions.START_WORKING(this.getId())); }
                 const response = await this.services.groupsService.contents(projectUuid, getParams(dataExplorer, !!isProjectTrashed));
                 const resourceUuids = response.items.map(item => item.uuid);
@@ -72,7 +74,7 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService
                     })
                 );
                 if (e.status === 404) {
-                    // It'll just show up as not found
+                    api.dispatch<any>(dataExplorerActions.SET_IS_RESPONSE_404({ id: this.id, isResponse404: true}));
                 }
                 else {
                     api.dispatch(couldNotFetchProjectContents());
index defacf21ded782ef15ecd3783628b68386f5995c..e70cb29ae653c0a79b624172e919b754c334cd8c 100644 (file)
@@ -84,7 +84,7 @@ export class SearchResultsMiddlewareService extends DataExplorerMiddlewareServic
                         });
                     }).catch(() => {
                         api.dispatch(couldNotFetchSearchResults(session.clusterId));
-                        api.dispatch(progressIndicatorActions.STOP_WORKING(this.id))
+                        api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.id))
                     });
             }
         );
index 05e923f1bbeecfb90583e1314b68e9e8e9afd3f0..a56c839242678d756ced6b0ab44f5d4dec1ba878 100644 (file)
@@ -21,6 +21,7 @@ interface Props {
     onRowDoubleClick: (item: any) => void;
     extractKey?: (item: any) => React.Key;
     working?: boolean;
+    is404?: boolean;
 }
 
 const mapStateToProps = ({ progressIndicator, dataExplorer, router, multiselect, detailsPanel, properties}: RootState, { id }: Props) => {
index ad1234927bbe41faa085b38933d6e09265c76a15..5e09bfa8345f4e9f24c34f5efc0871c27814a6e6 100644 (file)
@@ -256,6 +256,7 @@ interface ProjectPanelDataProps {
     userUuid: string;
     dataExplorerItems: any;
     working: boolean;
+    is404: boolean;
 }
 
 type ProjectPanelProps = ProjectPanelDataProps & DispatchProp & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
@@ -264,10 +265,12 @@ const mapStateToProps = (state: RootState) => {
     const currentItemId = getProperty<string>(PROJECT_PANEL_CURRENT_UUID)(state.properties);
     const project = getResource<GroupResource>(currentItemId || "")(state.resources);
     const working = !!state.progressIndicator.some(p => p.id === PROJECT_PANEL_ID && p.working);
+    const is404 = state.dataExplorer[PROJECT_PANEL_ID].isResponse404;
     return {
         working,
         currentItemId,
         project,
+        is404,
         resources: state.resources,
         userUuid: state.auth.user!.uuid,
     };
@@ -289,6 +292,7 @@ export const ProjectPanel = withStyles(styles)(
                         defaultViewIcon={ProjectIcon}
                         defaultViewMessages={DEFAULT_VIEW_MESSAGES}
                         working={this.props.working}
+                        is404={this.props.is404}
                     />
                 </div>
             }