diff --git a/openbis_ng_ui/src/store/actions/browser.js b/openbis_ng_ui/src/store/actions/browser.js index afc3bedfd4fbf125d160db04cad44a3bd07712e2..d8d9810126e7c38ae80b9d7b2c8d8606d2a3b6b1 100644 --- a/openbis_ng_ui/src/store/actions/browser.js +++ b/openbis_ng_ui/src/store/actions/browser.js @@ -7,7 +7,7 @@ export const BROWSER_NODE_COLLAPSE = 'BROWSER_NODE_COLLAPSE' export const BROWSER_SET_FILTER = 'BROWSER_SET_FILTER' export const BROWSER_SET_NODES = 'BROWSER_SET_NODES' -export const BROWSER_SET_SELECTED_NODE = 'BROWSER_SET_SELECTED_NODE' +export const BROWSER_SET_SELECTED_NODES = 'BROWSER_SET_SELECTED_NODES' export const BROWSER_SET_VISIBLE_NODES = 'BROWSER_SET_VISIBLE_NODES' export const BROWSER_SET_EXPANDED_NODES = 'BROWSER_SET_EXPANDED_NODES' export const BROWSER_ADD_EXPANDED_NODES = 'BROWSER_ADD_EXPANDED_NODES' @@ -75,11 +75,11 @@ export const browserSetNodes = (page, nodes) => ({ } }) -export const browserSetSelectedNode = (page, id) => ({ - type: BROWSER_SET_SELECTED_NODE, +export const browserSetSelectedNodes = (page, ids) => ({ + type: BROWSER_SET_SELECTED_NODES, payload: { page, - id + ids } }) diff --git a/openbis_ng_ui/src/store/reducers/ui/pages/common/browser.js b/openbis_ng_ui/src/store/reducers/ui/pages/common/browser.js index ef2410cb73dd810f598952e80d527ab242a1fec6..56dfe80e0e0a874f72a294bb924dd6d495577ac7 100644 --- a/openbis_ng_ui/src/store/reducers/ui/pages/common/browser.js +++ b/openbis_ng_ui/src/store/reducers/ui/pages/common/browser.js @@ -6,7 +6,7 @@ export const browser = combineReducers({ initialized, filter, nodes, - selectedNode, + selectedNodes, visibleNodes, expandedNodes }) @@ -46,13 +46,13 @@ function nodes(state = [], action){ } } -function selectedNode(state = null, action){ +function selectedNodes(state = [], action){ switch(action.type){ - case actions.BROWSER_SET_SELECTED_NODE: - if(_.isEqual(state, action.payload.id)){ + case actions.BROWSER_SET_SELECTED_NODES: + if(_.isEqual(state, action.payload.ids)){ return state }else{ - return action.payload.id + return action.payload.ids } default: return state diff --git a/openbis_ng_ui/src/store/sagas/browser/browser.js b/openbis_ng_ui/src/store/sagas/browser/browser.js index d9508d6ca8d7971d4eec4b754228e425c6f68807..e3c668d68b4dc30677e4d9a96075e2c4db98b257 100644 --- a/openbis_ng_ui/src/store/sagas/browser/browser.js +++ b/openbis_ng_ui/src/store/sagas/browser/browser.js @@ -67,13 +67,22 @@ function* browserNodeSelect(action){ let allNodes = yield select(selectors.getAllBrowserNodes, page) let allNodesAllLevels = common.getAllNodes(allNodes) - let nodeToSelect = _.find(allNodesAllLevels, node => { + let nodeWithId = _.find(allNodesAllLevels, node => { return node.id === id }) - yield put(actions.browserSetSelectedNode(page, nodeToSelect ? nodeToSelect.id : null)) - if(nodeToSelect && nodeToSelect.object){ - yield put(actions.objectOpen(page, nodeToSelect.object.type, nodeToSelect.object.id)) + if(nodeWithId && nodeWithId.object){ + let idsToSelect = _.reduce(allNodesAllLevels, (array, node) => { + if(_.isEqual(nodeWithId.object, node.object)){ + array.push(node.id) + } + return array + }, []) + yield put(actions.browserSetSelectedNodes(page, idsToSelect)) + yield put(actions.objectOpen(page, nodeWithId.object.type, nodeWithId.object.id)) + }else{ + let idsToSelect = nodeWithId ? [nodeWithId.id] : [] + yield put(actions.browserSetSelectedNodes(page, idsToSelect)) } } @@ -87,13 +96,18 @@ function* browserNodeCollapse(action){ function* setSelectedObject(action){ let {page, type, id} = action.payload + let selectedObject = { type, id } let allNodes = yield select(selectors.getAllBrowserNodes, page) let allNodesAllLevels = common.getAllNodes(allNodes) - let nodeToSelect = _.find(allNodesAllLevels, node => { - return node.object && node.object.type === type && node.object.id === id - }) - yield put(actions.browserSetSelectedNode(page, nodeToSelect ? nodeToSelect.id : null)) + let idsToSelect = _.reduce(allNodesAllLevels, (array, node) => { + if(_.isEqual(selectedObject, node.object)){ + array.push(node.id) + } + return array + }, []) + + yield put(actions.browserSetSelectedNodes(page, idsToSelect)) } function browserFilter(nodes, filter){ diff --git a/openbis_ng_ui/src/store/selectors/browser.js b/openbis_ng_ui/src/store/selectors/browser.js index bbba82f799520f8d03221f21b27b5d78da2283e1..ca6ec0d2bc07748495f2ef3862e2e48daf0e1009 100644 --- a/openbis_ng_ui/src/store/selectors/browser.js +++ b/openbis_ng_ui/src/store/selectors/browser.js @@ -34,14 +34,14 @@ export const getBrowserNodes = createSelector( browser => { logger.log(logger.DEBUG, 'browserSelector.getBrowserNodes') - let selectedNode = browser.selectedNode + let selectedNodes = new Set(browser.selectedNodes) let visibleNodes = new Set(browser.visibleNodes) let expandedNodes = new Set(browser.expandedNodes) let nodes = browser.nodes nodes = common.mapNodes(null, nodes, (parent, node) => { if(visibleNodes.has(node.id)){ - let selected = selectedNode === node.id + let selected = selectedNodes.has(node.id) let expanded = expandedNodes.has(node.id) return Object.assign({ selected, expanded }, node) }else{ diff --git a/openbis_ng_ui/srcTest/store/sagas/browser.test.js b/openbis_ng_ui/srcTest/store/sagas/browser.test.js index ba6910b20dca40ce3cefafd4cfcc9fdc42575612..924d97c12cd802a54151d8550b83521a12cc8793 100644 --- a/openbis_ng_ui/srcTest/store/sagas/browser.test.js +++ b/openbis_ng_ui/srcTest/store/sagas/browser.test.js @@ -22,6 +22,7 @@ beforeEach(() => { }) describe('browser', () => { + test('init', () => { openbis.getUsers.mockReturnValue({ objects: [ fixture.TEST_USER_DTO, fixture.ANOTHER_USER_DTO ] @@ -59,11 +60,8 @@ describe('browser', () => { ]) ]) - let selectedObject = selectors.getSelectedObject(state, pages.USERS) - let openObjects = selectors.getOpenObjects(state, pages.USERS) - - expect(selectedObject).toEqual(null) - expect(openObjects).toEqual([]) + expectSelectedObject(pages.USERS, null) + expectOpenObjects(pages.USERS, []) }) test('filter', () => { @@ -90,23 +88,20 @@ describe('browser', () => { ]) ]) - let selectedObject = selectors.getSelectedObject(state, pages.USERS) - let openObjects = selectors.getOpenObjects(state, pages.USERS) - - expect(selectedObject).toEqual(null) - expect(openObjects).toEqual([]) + expectSelectedObject(pages.USERS, null) + expectOpenObjects(pages.USERS, []) }) - test('selectNode', () => { + test('select node', () => { openbis.getUsers.mockReturnValue({ - objects: [ fixture.TEST_USER_DTO ] + objects: [ fixture.TEST_USER_DTO, fixture.ANOTHER_USER_DTO ] }) openbis.getGroups.mockReturnValue({ objects: [] }) - let object = fixture.object(objectType.USER, fixture.TEST_USER_DTO.userId) + let testUserObject = fixture.object(objectType.USER, fixture.TEST_USER_DTO.userId) store.dispatch(actions.browserInit(pages.USERS)) store.dispatch(actions.browserNodeSelect(pages.USERS, nodeId(['users', fixture.TEST_USER_DTO.userId]))) @@ -114,29 +109,122 @@ describe('browser', () => { let state = store.getState() expectNodes(selectors.getBrowserNodes(state, pages.USERS), [ node(['users'], false, false, [ + node(['users', fixture.ANOTHER_USER_DTO.userId], false, false), node(['users', fixture.TEST_USER_DTO.userId], false, true) ]), node(['groups']) ]) - expect(selectors.getSelectedObject(state, pages.USERS)).toEqual(object) - expect(selectors.getOpenObjects(state, pages.USERS)).toEqual([object]) + expectSelectedObject(pages.USERS, testUserObject) + expectOpenObjects(pages.USERS, [testUserObject]) + }) - store.dispatch(actions.objectClose(pages.USERS, object.type, object.id)) + test('select another node', () => { + openbis.getUsers.mockReturnValue({ + objects: [ fixture.TEST_USER_DTO, fixture.ANOTHER_USER_DTO ] + }) - state = store.getState() + openbis.getGroups.mockReturnValue({ + objects: [] + }) + + let testUserObject = fixture.object(objectType.USER, fixture.TEST_USER_DTO.userId) + let anotherUserObject = fixture.object(objectType.USER, fixture.ANOTHER_USER_DTO.userId) + + store.dispatch(actions.browserInit(pages.USERS)) + store.dispatch(actions.browserNodeSelect(pages.USERS, nodeId(['users', fixture.TEST_USER_DTO.userId]))) + store.dispatch(actions.browserNodeSelect(pages.USERS, nodeId(['users', fixture.ANOTHER_USER_DTO.userId]))) + + let state = store.getState() expectNodes(selectors.getBrowserNodes(state, pages.USERS), [ node(['users'], false, false, [ + node(['users', fixture.ANOTHER_USER_DTO.userId], false, true), node(['users', fixture.TEST_USER_DTO.userId], false, false) ]), node(['groups']) ]) - expect(selectors.getSelectedObject(state, pages.USERS)).toEqual(null) - expect(selectors.getOpenObjects(state, pages.USERS)).toEqual([]) + expectSelectedObject(pages.USERS, anotherUserObject) + expectOpenObjects(pages.USERS, [testUserObject, anotherUserObject]) + }) + + test('select virtual node', () => { + openbis.getUsers.mockReturnValue({ + objects: [ fixture.TEST_USER_DTO, fixture.ANOTHER_USER_DTO ] + }) + + openbis.getGroups.mockReturnValue({ + objects: [] + }) + + store.dispatch(actions.browserInit(pages.USERS)) + store.dispatch(actions.browserNodeSelect(pages.USERS, nodeId(['users']))) + + let state = store.getState() + expectNodes(selectors.getBrowserNodes(state, pages.USERS), [ + node(['users'], false, true, [ + node(['users', fixture.ANOTHER_USER_DTO.userId], false, false), + node(['users', fixture.TEST_USER_DTO.userId], false, false) + ]), + node(['groups']) + ]) + + expectSelectedObject(pages.USERS, null) + expectOpenObjects(pages.USERS, []) + }) + + test('select two nodes that represent the same object', () => { + openbis.getUsers.mockReturnValue({ + objects: [ fixture.TEST_USER_DTO ] + }) + + openbis.getGroups.mockReturnValue({ + objects: [ fixture.TEST_GROUP_DTO ] + }) + + let testUserObject = fixture.object(objectType.USER, fixture.TEST_USER_DTO.userId) + + store.dispatch(actions.browserInit(pages.USERS)) + store.dispatch(actions.browserNodeSelect(pages.USERS, nodeId(['users', fixture.TEST_USER_DTO.userId]))) + + let state = store.getState() + expectNodes(selectors.getBrowserNodes(state, pages.USERS), [ + node(['users'], false, false, [ + node(['users', fixture.TEST_USER_DTO.userId], false, true, [ + node(['users', fixture.TEST_USER_DTO.userId, fixture.TEST_GROUP_DTO.code], false, false) + ]) + ]), + node(['groups'], false, false, [ + node(['groups', fixture.TEST_GROUP_DTO.code], false, false, [ + node(['groups', fixture.TEST_GROUP_DTO.code, fixture.TEST_USER_DTO.userId], false, true) + ]) + ]) + ]) + + expectSelectedObject(pages.USERS, testUserObject) + expectOpenObjects(pages.USERS, [testUserObject]) + + store.dispatch(actions.browserNodeSelect(pages.USERS, nodeId(['groups', fixture.TEST_GROUP_DTO.code, fixture.TEST_USER_DTO.userId]))) + + state = store.getState() + expectNodes(selectors.getBrowserNodes(state, pages.USERS), [ + node(['users'], false, false, [ + node(['users', fixture.TEST_USER_DTO.userId], false, true, [ + node(['users', fixture.TEST_USER_DTO.userId, fixture.TEST_GROUP_DTO.code], false, false) + ]) + ]), + node(['groups'], false, false, [ + node(['groups', fixture.TEST_GROUP_DTO.code], false, false, [ + node(['groups', fixture.TEST_GROUP_DTO.code, fixture.TEST_USER_DTO.userId], false, true) + ]) + ]) + ]) + + expectSelectedObject(pages.USERS, testUserObject) + expectOpenObjects(pages.USERS, [testUserObject]) }) - test('expandNode collapseNode', () => { + test('expand and collapse node', () => { openbis.getUsers.mockReturnValue({ objects: [] }) @@ -156,6 +244,9 @@ describe('browser', () => { ]) ]) + expectSelectedObject(pages.USERS, null) + expectOpenObjects(pages.USERS, []) + store.dispatch(actions.browserNodeCollapse(pages.USERS, nodeId(['groups']))) state = store.getState() @@ -166,11 +257,8 @@ describe('browser', () => { ]) ]) - let selectedObject = selectors.getSelectedObject(state, pages.USERS) - let openObjects = selectors.getOpenObjects(state, pages.USERS) - - expect(selectedObject).toEqual(null) - expect(openObjects).toEqual([]) + expectSelectedObject(pages.USERS, null) + expectOpenObjects(pages.USERS, []) }) }) @@ -208,3 +296,11 @@ function expectNodes(actualNodes, expectedNodes){ expect(actualNodesClone).toEqual(expectedNodes) } + +function expectSelectedObject(page, object){ + expect(selectors.getSelectedObject(store.getState(), page)).toEqual(object) +} + +function expectOpenObjects(page, objects){ + expect(selectors.getOpenObjects(store.getState(), page)).toEqual(objects) +}