--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { unionize, ofType, UnionOf } from "unionize";
+
+export const snackbarActions = unionize({
+ OPEN_SNACKBAR: ofType<{message: string; hideDuration?: number}>(),
+ CLOSE_SNACKBAR: ofType<{}>()
+}, { tag: 'type', value: 'payload' });
+
+export type SnackbarAction = UnionOf<typeof snackbarActions>;
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { SnackbarAction, snackbarActions } from "./snackbar-actions";
+
+export interface SnackbarState {
+ message: string;
+ open: boolean;
+ hideDuration: number;
+}
+
+const DEFAULT_HIDE_DURATION = 3000;
+
+const initialState: SnackbarState = {
+ message: "",
+ open: false,
+ hideDuration: DEFAULT_HIDE_DURATION
+};
+
+export const snackbarReducer = (state = initialState, action: SnackbarAction) => {
+ return snackbarActions.match(action, {
+ OPEN_SNACKBAR: data => ({ ...data, open: true }),
+ CLOSE_SNACKBAR: () => initialState,
+ default: () => state,
+ });
+};
import { favoritePanelMiddleware } from "./favorite-panel/favorite-panel-middleware";
import { reducer as formReducer } from 'redux-form';
import { FavoritesState, favoritesReducer } from './favorites/favorites-reducer';
+import { snackbarReducer, SnackbarState } from './snackbar/snackbar-reducer';
const composeEnhancers =
(process.env.NODE_ENV === 'development' &&
detailsPanel: DetailsPanelState;
contextMenu: ContextMenuState;
favorites: FavoritesState;
+ snackbar: SnackbarState;
}
const rootReducer = combineReducers({
contextMenu: contextMenuReducer,
form: formReducer,
favorites: favoritesReducer,
+ snackbar: snackbarReducer,
});
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from "react";
+import { connect } from "react-redux";
+import { RootState } from "../../store/store";
+import MaterialSnackbar, { SnackbarProps } from "@material-ui/core/Snackbar";
+import { Dispatch } from "redux";
+import { snackbarActions } from "../../store/snackbar/snackbar-actions";
+
+const mapStateToProps = (state: RootState): SnackbarProps => ({
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
+ open: state.snackbar.open,
+ message: <span>{state.snackbar.message}</span>,
+ autoHideDuration: state.snackbar.hideDuration
+});
+
+const mapDispatchToProps = (dispatch: Dispatch): Pick<SnackbarProps, "onClose"> => ({
+ onClose: () => {
+ dispatch(snackbarActions.CLOSE_SNACKBAR());
+ }
+});
+
+export const Snackbar = connect(mapStateToProps, mapDispatchToProps)(MaterialSnackbar);
import { FavoritePanel, FAVORITE_PANEL_ID } from "../favorite-panel/favorite-panel";
import { CurrentTokenDialog } from '../../views-components/current-token-dialog/current-token-dialog';
import { dataExplorerActions } from '../../store/data-explorer/data-explorer-action';
+import { Snackbar } from '../../views-components/snackbar/snackbar';
const drawerWidth = 240;
const appBarHeight = 100;
{user && <DetailsPanel />}
</main>
<ContextMenu />
+ <Snackbar />
<CreateProjectDialog />
<CurrentTokenDialog
currentToken={this.props.currentToken}