Create generic dialog state
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Thu, 2 Aug 2018 13:04:55 +0000 (15:04 +0200)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Thu, 2 Aug 2018 13:04:55 +0000 (15:04 +0200)
Feature #13855

Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski@contractors.roche.com>

src/store/dialog/dialog-actions.ts [new file with mode: 0644]
src/store/dialog/dialog-reducer.test.ts [new file with mode: 0644]
src/store/dialog/dialog-reducer.ts [new file with mode: 0644]
src/store/dialog/with-dialog.ts [new file with mode: 0644]
src/store/store.ts

diff --git a/src/store/dialog/dialog-actions.ts b/src/store/dialog/dialog-actions.ts
new file mode 100644 (file)
index 0000000..df4418f
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { default as unionize, ofType, UnionOf } from "unionize";
+
+export const dialogActions = unionize({
+    OPEN_DIALOG: ofType<{ id: string, data: any }>(),
+    CLOSE_DIALOG: ofType<{ id: string }>()
+}, {
+        tag: 'type',
+        value: 'payload'
+    });
+
+export type DialogAction = UnionOf<typeof dialogActions>;
diff --git a/src/store/dialog/dialog-reducer.test.ts b/src/store/dialog/dialog-reducer.test.ts
new file mode 100644 (file)
index 0000000..1beb6ee
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { dialogReducer } from "./dialog-reducer";
+import { dialogActions } from "./dialog-actions";
+
+describe('DialogReducer', () => {
+    it('OPEN_DIALOG', () => {
+        const id = 'test id';
+        const data = 'test data';
+        const state = dialogReducer({}, dialogActions.OPEN_DIALOG({ id, data }));
+        expect(state[id]).toEqual({ open: true, data });
+    });
+
+    it('CLOSE_DIALOG', () => {
+        const id = 'test id';
+        const state = dialogReducer({}, dialogActions.CLOSE_DIALOG({ id }));
+        expect(state[id]).toEqual({ open: false });
+    });
+});
diff --git a/src/store/dialog/dialog-reducer.ts b/src/store/dialog/dialog-reducer.ts
new file mode 100644 (file)
index 0000000..6013ab6
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { DialogAction, dialogActions } from "./dialog-actions";
+
+export type DialogState = Record<string, Dialog>;
+
+export interface Dialog {
+    open: boolean;
+    data?: any;
+}
+
+export const dialogReducer = (state: DialogState = {}, action: DialogAction) =>
+    dialogActions.match(action, {
+        OPEN_DIALOG: ({ id, data }) => ({ ...state, [id]: { open: true, data } }),
+        CLOSE_DIALOG: ({ id }) => ({ ...state, [id]: { open: false } }),
+        default: () => state,
+    });
+
diff --git a/src/store/dialog/with-dialog.ts b/src/store/dialog/with-dialog.ts
new file mode 100644 (file)
index 0000000..60cb5d1
--- /dev/null
@@ -0,0 +1,21 @@
+// 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 { DialogState } from './dialog-reducer';
+
+export type WithDialog<T> = {
+    open: boolean;
+    data?: T;
+};
+
+export const withDialog = (id: string) =>
+    <T>(component: React.ComponentType<WithDialog<T>>) =>
+        connect(mapStateToProps(id))(component);
+
+export const mapStateToProps = (id: string) => <T>(state: { dialog: DialogState }): WithDialog<T> => {
+    const dialog = state.dialog[id];
+    return dialog ? dialog : { open: false };
+};
index 9d888efb6163b914057b10a0f7f84559943e3ddc..0ce461602bbe73c2b41d3b9934fae9b29117fc23 100644 (file)
@@ -22,6 +22,7 @@ import { CollectionPanelFilesState } from './collection-panel/collection-panel-f
 import { collectionPanelFilesReducer } from './collection-panel/collection-panel-files/collections-panel-files-reducer';
 import { CollectionCreatorState, collectionCreationReducer } from './collections/creator/collection-creator-reducer';
 import { CollectionPanelState, collectionPanelReducer } from './collection-panel/collection-panel-reducer';
+import { DialogState, dialogReducer } from './dialog/dialog-reducer';
 
 const composeEnhancers =
     (process.env.NODE_ENV === 'development' &&
@@ -41,6 +42,7 @@ export interface RootState {
     favorites: FavoritesState;
     snackbar: SnackbarState;
     collectionPanelFiles: CollectionPanelFilesState;
+    dialog: DialogState;
 }
 
 const rootReducer = combineReducers({
@@ -57,6 +59,7 @@ const rootReducer = combineReducers({
     favorites: favoritesReducer,
     snackbar: snackbarReducer,
     collectionPanelFiles: collectionPanelFilesReducer,
+    dialog: dialogReducer
 });