[ARVADOS-WORKBENCH2] updated: 1.2.0-381-gd9c91ff

Git user git at public.curoverse.com
Tue Sep 18 07:04:43 EDT 2018


Summary of changes:
 src/index.tsx                                      | 11 ++-
 src/services/api/api-actions.ts                    |  2 +-
 .../common-service/common-resource-service.ts      |  7 +-
 .../favorite-panel-middleware-service.ts           | 15 ++--
 .../progress-indicator-actions.ts                  |  8 +--
 .../progress-indicator-reducer.ts                  | 12 ++--
 .../project-panel-middleware-service.ts            | 17 +++--
 src/store/snackbar/snackbar-actions.ts             | 17 +++--
 src/store/snackbar/snackbar-reducer.ts             | 35 ++++++---
 .../trash-panel/trash-panel-middleware-service.ts  | 18 +++--
 src/store/trash/trash-actions.ts                   | 82 +++++++++++++---------
 src/views-components/snackbar/snackbar.tsx         | 40 ++++++-----
 12 files changed, 166 insertions(+), 98 deletions(-)

       via  d9c91ff458dfedd01fb2d5a86e60e054f5a87d10 (commit)
      from  aafa91ce918b23cff556f73e337ad8fe76ed578a (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 d9c91ff458dfedd01fb2d5a86e60e054f5a87d10
Author: Daniel Kos <daniel.kos at contractors.roche.com>
Date:   Tue Sep 18 13:04:34 2018 +0200

    Add queued snackbar, fix progress reducer
    
    Feature #14186
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos at contractors.roche.com>

diff --git a/src/index.tsx b/src/index.tsx
index b74329f..0d026f2 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -38,7 +38,7 @@ import { addRouteChangeHandlers } from './routes/route-change-handlers';
 import { setCurrentTokenDialogApiHost } from '~/store/current-token-dialog/current-token-dialog-actions';
 import { processResourceActionSet } from './views-components/context-menu/action-sets/process-resource-action-set';
 import { progressIndicatorActions } from '~/store/progress-indicator/progress-indicator-actions';
-import { snackbarActions } from "~/store/snackbar/snackbar-actions";
+import { snackbarActions, SnackbarKind } from "~/store/snackbar/snackbar-actions";
 
 const getBuildNumber = () => "BN-" + (process.env.REACT_APP_BUILD_NUMBER || "dev");
 const getGitCommit = () => "GIT-" + (process.env.REACT_APP_GIT_COMMIT || "latest").substr(0, 7);
@@ -65,10 +65,11 @@ fetchConfig()
         const history = createBrowserHistory();
         const services = createServices(config, {
             progressFn: (id, working) => {
-                store.dispatch(progressIndicatorActions.TOGGLE({ id, working }));
+                store.dispatch(progressIndicatorActions.TOGGLE_WORKING({ id, working }));
             },
-            errorFn: (id, message) => {
-                store.dispatch(snackbarActions.OPEN_SNACKBAR({ message }));
+            errorFn: (id, error) => {
+                console.error("Backend error:", error);
+                store.dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Backend error", kind: SnackbarKind.ERROR }));
             }
         });
         const store = configureStore(history, services);
@@ -96,8 +97,6 @@ fetchConfig()
             <App />,
             document.getElementById('root') as HTMLElement
         );
-
-
     });
 
 const initListener = (history: History, store: RootStore, services: ServiceRepository, config: Config) => {
diff --git a/src/services/api/api-actions.ts b/src/services/api/api-actions.ts
index d47eeaa..f986786 100644
--- a/src/services/api/api-actions.ts
+++ b/src/services/api/api-actions.ts
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 export type ProgressFn = (id: string, working: boolean) => void;
-export type ErrorFn = (id: string, message: string) => void;
+export type ErrorFn = (id: string, error: any) => void;
 
 export interface ApiActions {
     progressFn: ProgressFn;
diff --git a/src/services/common-service/common-resource-service.ts b/src/services/common-service/common-resource-service.ts
index cfae106..f6810c0 100644
--- a/src/services/common-service/common-resource-service.ts
+++ b/src/services/common-service/common-resource-service.ts
@@ -41,7 +41,7 @@ export enum CommonResourceServiceError {
 
 export class CommonResourceService<T extends Resource> {
 
-    static mapResponseKeys = (response: { data: any }): Promise<any> =>
+    static mapResponseKeys = (response: { data: any }) =>
         CommonResourceService.mapKeys(_.camelCase)(response.data)
 
     static mapKeys = (mapFn: (key: string) => string) =>
@@ -73,8 +73,9 @@ export class CommonResourceService<T extends Resource> {
             .then(CommonResourceService.mapResponseKeys)
             .catch(({ response }) => {
                 actions.progressFn(reqId, false);
-                actions.errorFn(reqId, response.message);
-                Promise.reject<Errors>(CommonResourceService.mapResponseKeys(response));
+                const errors = CommonResourceService.mapResponseKeys(response) as Errors;
+                actions.errorFn(reqId, errors);
+                throw errors;
             });
     }
 
diff --git a/src/store/favorite-panel/favorite-panel-middleware-service.ts b/src/store/favorite-panel/favorite-panel-middleware-service.ts
index 96f6664..acdc12b 100644
--- a/src/store/favorite-panel/favorite-panel-middleware-service.ts
+++ b/src/store/favorite-panel/favorite-panel-middleware-service.ts
@@ -16,7 +16,7 @@ import { OrderBuilder, OrderDirection } from "~/services/api/order-builder";
 import { LinkResource } from "~/models/link";
 import { GroupContentsResource, GroupContentsResourcePrefix } from "~/services/groups-service/groups-service";
 import { resourcesActions } from "~/store/resources/resources-actions";
-import { snackbarActions } from '~/store/snackbar/snackbar-actions';
+import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
 import { progressIndicatorActions } from '~/store/progress-indicator/progress-indicator-actions.ts';
 import { getDataExplorer } from "~/store/data-explorer/data-explorer-reducer";
 import { loadMissingProcessesInformation } from "~/store/project-panel/project-panel-middleware-service";
@@ -50,7 +50,7 @@ export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareServic
                     .addOrder(direction, "name", GroupContentsResourcePrefix.PROJECT);
             }
             try {
-                api.dispatch(progressIndicatorActions.START(this.getId()));
+                api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
                 const response = await this.services.favoriteService
                     .list(this.services.authService.getUuid()!, {
                         limit: dataExplorer.rowsPerPage,
@@ -62,7 +62,7 @@ export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareServic
                             .addILike("name", dataExplorer.searchValue)
                             .getFilters()
                     });
-                api.dispatch(progressIndicatorActions.PERSIST_STOP(this.getId()));
+                api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
                 api.dispatch(resourcesActions.SET_RESOURCES(response.items));
                 await api.dispatch<any>(loadMissingProcessesInformation(response.items));
                 api.dispatch(favoritePanelActions.SET_ITEMS({
@@ -73,13 +73,14 @@ export class FavoritePanelMiddlewareService extends DataExplorerMiddlewareServic
                 }));
                 api.dispatch<any>(updateFavorites(response.items.map(item => item.uuid)));
             } catch (e) {
-                api.dispatch(progressIndicatorActions.PERSIST_STOP(this.getId()));
+                api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
                 api.dispatch(favoritePanelActions.SET_ITEMS({
                     items: [],
                     itemsAvailable: 0,
                     page: 0,
                     rowsPerPage: dataExplorer.rowsPerPage
                 }));
+                api.dispatch(couldNotFetchFavoritesContents());
             }
         }
     }
@@ -89,3 +90,9 @@ const favoritesPanelDataExplorerIsNotSet = () =>
     snackbarActions.OPEN_SNACKBAR({
         message: 'Favorites panel is not ready.'
     });
+
+const couldNotFetchFavoritesContents = () =>
+    snackbarActions.OPEN_SNACKBAR({
+        message: 'Could not fetch favorites contents.',
+        kind: SnackbarKind.ERROR
+    });
diff --git a/src/store/progress-indicator/progress-indicator-actions.ts b/src/store/progress-indicator/progress-indicator-actions.ts
index 144f20b..34a43d8 100644
--- a/src/store/progress-indicator/progress-indicator-actions.ts
+++ b/src/store/progress-indicator/progress-indicator-actions.ts
@@ -5,10 +5,10 @@
 import { unionize, ofType, UnionOf } from "~/common/unionize";
 
 export const progressIndicatorActions = unionize({
-    START: ofType<string>(),
-    STOP: ofType<string>(),
-    PERSIST_STOP: ofType<string>(),
-    TOGGLE: ofType<{ id: string, working: boolean }>()
+    START_WORKING: ofType<string>(),
+    STOP_WORKING: ofType<string>(),
+    PERSIST_STOP_WORKING: ofType<string>(),
+    TOGGLE_WORKING: ofType<{ id: string, working: boolean }>()
 });
 
 export type ProgressIndicatorAction = UnionOf<typeof progressIndicatorActions>;
diff --git a/src/store/progress-indicator/progress-indicator-reducer.ts b/src/store/progress-indicator/progress-indicator-reducer.ts
index 4889bac..849906b 100644
--- a/src/store/progress-indicator/progress-indicator-reducer.ts
+++ b/src/store/progress-indicator/progress-indicator-reducer.ts
@@ -9,17 +9,17 @@ export type ProgressIndicatorState = { id: string, working: boolean }[];
 const initialState: ProgressIndicatorState = [];
 
 export const progressIndicatorReducer = (state: ProgressIndicatorState = initialState, action: ProgressIndicatorAction) => {
-    const startWorking = (id: string) => state.find(p => p.working) ? state : state.concat({ id, working: true });
+    const startWorking = (id: string) => state.find(p => p.id === id) ? state : state.concat({ id, working: true });
     const stopWorking = (id: string) => state.filter(p => p.id !== id);
 
     return progressIndicatorActions.match(action, {
-        START: id => startWorking(id),
-        STOP: id => stopWorking(id),
-        PERSIST_STOP: id => state.map(p => ({
-            id,
+        START_WORKING: id => startWorking(id),
+        STOP_WORKING: id => stopWorking(id),
+        PERSIST_STOP_WORKING: id => state.map(p => ({
+            ...p,
             working: p.id === id ? false : p.working
         })),
-        TOGGLE: ({ id, working }) => working ? startWorking(id) : stopWorking(id),
+        TOGGLE_WORKING: ({ id, working }) => working ? startWorking(id) : stopWorking(id),
         default: () => state,
     });
 };
diff --git a/src/store/project-panel/project-panel-middleware-service.ts b/src/store/project-panel/project-panel-middleware-service.ts
index 89db436..84eaa85 100644
--- a/src/store/project-panel/project-panel-middleware-service.ts
+++ b/src/store/project-panel/project-panel-middleware-service.ts
@@ -17,7 +17,7 @@ import { Dispatch, MiddlewareAPI } from "redux";
 import { ProjectResource } from "~/models/project";
 import { updateResources } from "~/store/resources/resources-actions";
 import { getProperty } from "~/store/properties/properties";
-import { snackbarActions } from '../snackbar/snackbar-actions';
+import { snackbarActions, SnackbarKind } from '../snackbar/snackbar-actions';
 import { progressIndicatorActions } from '~/store/progress-indicator/progress-indicator-actions.ts';
 import { DataExplorer, getDataExplorer } from '../data-explorer/data-explorer-reducer';
 import { ListResults } from '~/services/common-service/common-resource-service';
@@ -39,15 +39,21 @@ export class ProjectPanelMiddlewareService extends DataExplorerMiddlewareService
             api.dispatch(projectPanelDataExplorerIsNotSet());
         } else {
             try {
-                api.dispatch(progressIndicatorActions.START(this.getId()));
+                api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
                 const response = await this.services.groupsService.contents(projectUuid, getParams(dataExplorer));
-                api.dispatch(progressIndicatorActions.PERSIST_STOP(this.getId()));
+                api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
                 api.dispatch<any>(updateFavorites(response.items.map(item => item.uuid)));
                 api.dispatch(updateResources(response.items));
                 await api.dispatch<any>(loadMissingProcessesInformation(response.items));
                 api.dispatch(setItems(response));
             } catch (e) {
-                api.dispatch(progressIndicatorActions.PERSIST_STOP(this.getId()));
+                api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
+                api.dispatch(projectPanelActions.SET_ITEMS({
+                    items: [],
+                    itemsAvailable: 0,
+                    page: 0,
+                    rowsPerPage: dataExplorer.rowsPerPage
+                }));
                 api.dispatch(couldNotFetchProjectContents());
             }
         }
@@ -120,7 +126,8 @@ const projectPanelCurrentUuidIsNotSet = () =>
 
 const couldNotFetchProjectContents = () =>
     snackbarActions.OPEN_SNACKBAR({
-        message: 'Could not fetch project contents.'
+        message: 'Could not fetch project contents.',
+        kind: SnackbarKind.ERROR
     });
 
 const projectPanelDataExplorerIsNotSet = () =>
diff --git a/src/store/snackbar/snackbar-actions.ts b/src/store/snackbar/snackbar-actions.ts
index dd34895..d6d7128 100644
--- a/src/store/snackbar/snackbar-actions.ts
+++ b/src/store/snackbar/snackbar-actions.ts
@@ -4,16 +4,23 @@
 
 import { unionize, ofType, UnionOf } from "~/common/unionize";
 
+export interface SnackbarMessage {
+    message: string;
+    hideDuration: number;
+    kind: SnackbarKind;
+}
+
 export enum SnackbarKind {
-    SUCCESS,
-    ERROR,
-    INFO,
-    WARNING
+    SUCCESS = 1,
+    ERROR = 2,
+    INFO = 3,
+    WARNING = 4
 }
 
 export const snackbarActions = unionize({
     OPEN_SNACKBAR: ofType<{message: string; hideDuration?: number, kind?: SnackbarKind}>(),
-    CLOSE_SNACKBAR: ofType<{}>()
+    CLOSE_SNACKBAR: ofType<{}>(),
+    SHIFT_MESSAGES: ofType<{}>()
 });
 
 export type SnackbarAction = UnionOf<typeof snackbarActions>;
diff --git a/src/store/snackbar/snackbar-reducer.ts b/src/store/snackbar/snackbar-reducer.ts
index 0595d28..73c566f 100644
--- a/src/store/snackbar/snackbar-reducer.ts
+++ b/src/store/snackbar/snackbar-reducer.ts
@@ -2,28 +2,43 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { SnackbarAction, snackbarActions, SnackbarKind } from "./snackbar-actions";
+import { SnackbarAction, snackbarActions, SnackbarKind, SnackbarMessage } from "./snackbar-actions";
 
 export interface SnackbarState {
-    message: string;
+    messages: SnackbarMessage[];
     open: boolean;
-    hideDuration: number;
-    kind: SnackbarKind;
 }
 
 const DEFAULT_HIDE_DURATION = 3000;
 
 const initialState: SnackbarState = {
-    message: "",
-    open: false,
-    hideDuration: DEFAULT_HIDE_DURATION,
-    kind: SnackbarKind.INFO
+    messages: [],
+    open: false
 };
 
 export const snackbarReducer = (state = initialState, action: SnackbarAction) => {
     return snackbarActions.match(action, {
-        OPEN_SNACKBAR: data => ({ ...initialState, ...data, open: true }),
-        CLOSE_SNACKBAR: () => initialState,
+        OPEN_SNACKBAR: data => {
+            return {
+                open: true,
+                messages: state.messages.concat({
+                    message: data.message,
+                    hideDuration: data.hideDuration ? data.hideDuration : DEFAULT_HIDE_DURATION,
+                    kind: data.kind ? data.kind : SnackbarKind.INFO
+                })
+            };
+        },
+        CLOSE_SNACKBAR: () => ({
+            ...state,
+            open: false
+        }),
+        SHIFT_MESSAGES: () => {
+            const messages = state.messages.filter((m, idx) => idx > 0);
+            return {
+                open: messages.length > 0,
+                messages
+            };
+        },
         default: () => state,
     });
 };
diff --git a/src/store/trash-panel/trash-panel-middleware-service.ts b/src/store/trash-panel/trash-panel-middleware-service.ts
index 968656d..90838b2 100644
--- a/src/store/trash-panel/trash-panel-middleware-service.ts
+++ b/src/store/trash-panel/trash-panel-middleware-service.ts
@@ -19,7 +19,7 @@ import { TrashPanelColumnNames, TrashPanelFilter } from "~/views/trash-panel/tra
 import { ProjectResource } from "~/models/project";
 import { ProjectPanelColumnNames } from "~/views/project-panel/project-panel";
 import { updateFavorites } from "~/store/favorites/favorites-actions";
-import { snackbarActions } from "~/store/snackbar/snackbar-actions";
+import { snackbarActions, SnackbarKind } from "~/store/snackbar/snackbar-actions";
 import { updateResources } from "~/store/resources/resources-actions";
 import { progressIndicatorActions } from "~/store/progress-indicator/progress-indicator-actions";
 
@@ -48,7 +48,7 @@ export class TrashPanelMiddlewareService extends DataExplorerMiddlewareService {
         }
 
         try {
-            api.dispatch(progressIndicatorActions.START(this.getId()));
+            api.dispatch(progressIndicatorActions.START_WORKING(this.getId()));
             const userUuid = this.services.authService.getUuid()!;
             const listResults = await this.services.groupsService
                 .contents(userUuid, {
@@ -63,7 +63,7 @@ export class TrashPanelMiddlewareService extends DataExplorerMiddlewareService {
                     recursive: true,
                     includeTrash: true
                 });
-            api.dispatch(progressIndicatorActions.PERSIST_STOP(this.getId()));
+            api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
 
             const items = listResults.items.map(it => it.uuid);
 
@@ -74,7 +74,13 @@ export class TrashPanelMiddlewareService extends DataExplorerMiddlewareService {
             api.dispatch<any>(updateFavorites(items));
             api.dispatch(updateResources(listResults.items));
         } catch (e) {
-            api.dispatch(progressIndicatorActions.PERSIST_STOP(this.getId()));
+            api.dispatch(progressIndicatorActions.PERSIST_STOP_WORKING(this.getId()));
+            api.dispatch(trashPanelActions.SET_ITEMS({
+                items: [],
+                itemsAvailable: 0,
+                page: 0,
+                rowsPerPage: dataExplorer.rowsPerPage
+            }));
             api.dispatch(couldNotFetchTrashContents());
         }
     }
@@ -82,5 +88,7 @@ export class TrashPanelMiddlewareService extends DataExplorerMiddlewareService {
 
 const couldNotFetchTrashContents = () =>
     snackbarActions.OPEN_SNACKBAR({
-        message: 'Could not fetch trash contents.'
+        message: 'Could not fetch trash contents.',
+        kind: SnackbarKind.ERROR
     });
+
diff --git a/src/store/trash/trash-actions.ts b/src/store/trash/trash-actions.ts
index cd6df55..5cf952e 100644
--- a/src/store/trash/trash-actions.ts
+++ b/src/store/trash/trash-actions.ts
@@ -5,53 +5,69 @@
 import { Dispatch } from "redux";
 import { RootState } from "~/store/store";
 import { ServiceRepository } from "~/services/services";
-import { snackbarActions } from "~/store/snackbar/snackbar-actions";
+import { snackbarActions, SnackbarKind } from "~/store/snackbar/snackbar-actions";
 import { trashPanelActions } from "~/store/trash-panel/trash-panel-action";
 import { activateSidePanelTreeItem, loadSidePanelTreeProjects } from "~/store/side-panel-tree/side-panel-tree-actions";
 import { projectPanelActions } from "~/store/project-panel/project-panel-action";
-import { ResourceKind, TrashableResource } from "~/models/resource";
+import { ResourceKind } from "~/models/resource";
 
 export const toggleProjectTrashed = (uuid: string, ownerUuid: string, isTrashed: boolean) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<any> => {
-        if (isTrashed) {
-            dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Restoring from trash..." }));
-            await services.groupsService.untrash(uuid);
-            dispatch<any>(activateSidePanelTreeItem(uuid));
-            dispatch(trashPanelActions.REQUEST_ITEMS());
-            dispatch(snackbarActions.CLOSE_SNACKBAR());
+        try {
+            if (isTrashed) {
+                dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Restoring from trash..." }));
+                await services.groupsService.untrash(uuid);
+                dispatch<any>(activateSidePanelTreeItem(uuid));
+                dispatch(trashPanelActions.REQUEST_ITEMS());
+                dispatch(snackbarActions.OPEN_SNACKBAR({
+                    message: "Restored from trash",
+                    hideDuration: 2000,
+                    kind: SnackbarKind.SUCCESS
+                }));
+            } else {
+                dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Moving to trash..." }));
+                await services.groupsService.trash(uuid);
+                dispatch<any>(loadSidePanelTreeProjects(ownerUuid));
+                dispatch(snackbarActions.OPEN_SNACKBAR({
+                    message: "Added to trash",
+                    hideDuration: 2000,
+                    kind: SnackbarKind.SUCCESS
+                }));
+            }
+        } catch (e) {
             dispatch(snackbarActions.OPEN_SNACKBAR({
-                message: "Restored from trash",
-                hideDuration: 2000
-            }));
-        } else {
-            dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Moving to trash..." }));
-            await services.groupsService.trash(uuid);
-            dispatch<any>(loadSidePanelTreeProjects(ownerUuid));
-            dispatch(snackbarActions.CLOSE_SNACKBAR());
-            dispatch(snackbarActions.OPEN_SNACKBAR({
-                message: "Added to trash",
-                hideDuration: 2000
+                message: "Could not move project to trash",
+                kind: SnackbarKind.ERROR
             }));
         }
     };
 
 export const toggleCollectionTrashed = (uuid: string, isTrashed: boolean) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<any> => {
-        if (isTrashed) {
-            dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Restoring from trash..." }));
-            await services.collectionService.untrash(uuid);
-            dispatch(trashPanelActions.REQUEST_ITEMS());
-            dispatch(snackbarActions.OPEN_SNACKBAR({
-                message: "Restored from trash",
-                hideDuration: 2000
-            }));
-        } else {
-            dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Moving to trash..." }));
-            await services.collectionService.trash(uuid);
-            dispatch(projectPanelActions.REQUEST_ITEMS());
+        try {
+            if (isTrashed) {
+                dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Restoring from trash..." }));
+                await services.collectionService.untrash(uuid);
+                dispatch(trashPanelActions.REQUEST_ITEMS());
+                dispatch(snackbarActions.OPEN_SNACKBAR({
+                    message: "Restored from trash",
+                    hideDuration: 2000,
+                    kind: SnackbarKind.SUCCESS
+                }));
+            } else {
+                dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Moving to trash..." }));
+                await services.collectionService.trash(uuid);
+                dispatch(projectPanelActions.REQUEST_ITEMS());
+                dispatch(snackbarActions.OPEN_SNACKBAR({
+                    message: "Added to trash",
+                    hideDuration: 2000,
+                    kind: SnackbarKind.SUCCESS
+                }));
+            }
+        } catch (e) {
             dispatch(snackbarActions.OPEN_SNACKBAR({
-                message: "Added to trash",
-                hideDuration: 2000
+                message: "Could not move collection to trash",
+                kind: SnackbarKind.ERROR
             }));
         }
     };
diff --git a/src/views-components/snackbar/snackbar.tsx b/src/views-components/snackbar/snackbar.tsx
index 341e803..7449e1e 100644
--- a/src/views-components/snackbar/snackbar.tsx
+++ b/src/views-components/snackbar/snackbar.tsx
@@ -20,18 +20,25 @@ import { ArvadosTheme } from "~/common/custom-theme";
 import { amber, green } from "@material-ui/core/colors";
 import * as classNames from 'classnames';
 
-const mapStateToProps = (state: RootState): SnackbarProps => ({
-    anchorOrigin: { vertical: "bottom", horizontal: "right" },
-    open: state.snackbar.open,
-    message: <span>{state.snackbar.message}</span>,
-    autoHideDuration: state.snackbar.hideDuration,
-});
+const mapStateToProps = (state: RootState): SnackbarProps & ArvadosSnackbarProps => {
+    const messages = state.snackbar.messages;
+    return {
+        anchorOrigin: { vertical: "bottom", horizontal: "right" },
+        open: state.snackbar.open,
+        message: <span>{messages.length > 0 ? messages[0].message : ""}</span>,
+        autoHideDuration: messages.length > 0 ? messages[0].hideDuration : 0,
+        kind: messages.length > 0 ? messages[0].kind : SnackbarKind.INFO
+    };
+};
 
-const mapDispatchToProps = (dispatch: Dispatch): Pick<SnackbarProps, "onClose"> => ({
+const mapDispatchToProps = (dispatch: Dispatch) => ({
     onClose: (event: any, reason: string) => {
         if (reason !== "clickaway") {
             dispatch(snackbarActions.CLOSE_SNACKBAR());
         }
+    },
+    onExited: () => {
+        dispatch(snackbarActions.SHIFT_MESSAGES());
     }
 });
 
@@ -43,27 +50,27 @@ type CssRules = "success" | "error" | "info" | "warning" | "icon" | "iconVariant
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     success: {
-        backgroundColor: green[600],
+        backgroundColor: green[600]
     },
     error: {
-        backgroundColor: theme.palette.error.dark,
+        backgroundColor: theme.palette.error.dark
     },
     info: {
-        backgroundColor: theme.palette.primary.dark,
+        backgroundColor: theme.palette.primary.dark
     },
     warning: {
-        backgroundColor: amber[700],
+        backgroundColor: amber[700]
     },
     icon: {
-        fontSize: 20,
+        fontSize: 20
     },
     iconVariant: {
         opacity: 0.9,
-        marginRight: theme.spacing.unit,
+        marginRight: theme.spacing.unit
     },
     message: {
         display: 'flex',
-        alignItems: 'center',
+        alignItems: 'center'
     },
 });
 
@@ -72,10 +79,11 @@ interface ArvadosSnackbarProps {
 }
 
 const ArvadosSnackbarContent = (props: SnackbarProps & ArvadosSnackbarProps & WithStyles<CssRules>) => {
-    const { classes, className, message, onClose, kind, ...other } = props;
+    const { classes, className, message, onClose, kind } = props;
 
     let Icon = InfoIcon;
-    let cssClass;
+    let cssClass = classes.info;
+
     switch (kind) {
         case SnackbarKind.INFO:
             Icon = InfoIcon;

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list