diff --git a/__tests__/src/actions/config.test.js b/__tests__/src/actions/config.test.js index f75d604d7a2ba9a0a3b832eb3c0948ffc205c857..0fbfca936b9aeff269c377700fa54ed7d2dff0f4 100644 --- a/__tests__/src/actions/config.test.js +++ b/__tests__/src/actions/config.test.js @@ -1,5 +1,6 @@ import * as actions from '../../../src/state/actions'; import ActionTypes from '../../../src/state/actions/action-types'; +import configFixture from '../../fixtures/config/export.example.json'; describe('config actions', () => { describe('setConfig', () => { @@ -22,4 +23,15 @@ describe('config actions', () => { expect(actions.updateConfig(config)).toEqual(expectedAction); }); }); + + describe('importConfig', () => { + it('imports the config', () => { + const config = configFixture; + const expectedAction = { + type: ActionTypes.IMPORT_CONFIG, + config, + }; + expect(actions.importConfig(config)).toEqual(expectedAction); + }); + }); }); diff --git a/src/components/ErrorDialog.js b/src/components/ErrorDialog.js index 40032c0bb6a8cfd98d599868085c02cbdbafdff5..d302ac9af6357da85c59f077626a74afe6298190 100644 --- a/src/components/ErrorDialog.js +++ b/src/components/ErrorDialog.js @@ -27,6 +27,7 @@ export class ErrorDialog extends Component { /* extract 'items' value and get first key-value-pair (an error) */ const error = first(values(omit(errors, 'items'))); const hasError = !isUndefined(error); + return ( <div> { hasError && ( diff --git a/src/state/actions/workspace.js b/src/state/actions/workspace.js index 1ff7a5ae814736024713a8239645b05fb98c7396..224d499c805953f255fc181d33442d16d3a7d077 100644 --- a/src/state/actions/workspace.js +++ b/src/state/actions/workspace.js @@ -1,4 +1,9 @@ -import { difference, values } from 'lodash'; +import { + difference, + keys, + slice, + values, +} from 'lodash'; import ActionTypes from './action-types'; import { importConfig } from './config'; import { removeWindow, addWindow, updateWindow } from './window'; @@ -99,9 +104,16 @@ export function importWorkspace(stateExport) { dispatch(importConfig(stateExport.config)); const { viewers } = stateExport || {}; const imWins = values(stateExport.windows); + const exWins = values(getState().windows); + const exWinCnt = exWins.length > imWins.length ? imWins.length : exWins.length; - /* re-use existing windows */ - const exIds = values(getState().windows).map((exWin) => { + /* + If the existing workspace already contains windows (exWins), + we can re-use them in order to optimize the performance. + As we only can only re-use the amount of windows to be imported maximally, + slice all additional windows before + */ + const exIds = slice(exWins, 0, exWinCnt).map((exWin) => { const imWin = imWins.shift(); const viewer = viewers[imWin.id]; delete imWin.id; @@ -123,7 +135,7 @@ export function importWorkspace(stateExport) { }); /* close surplus windows */ - difference(getState().windows, exIds.concat(imIds)) + difference(keys(getState().windows), exIds.concat(imIds)) .map(winId => dispatch(removeWindow(winId))); }; } diff --git a/src/state/reducers/windows.js b/src/state/reducers/windows.js index 76bd83ee1787274525782cae3a7d242643097298..0edbb07ceee4bd555300e7df50eb24a60b246fb7 100644 --- a/src/state/reducers/windows.js +++ b/src/state/reducers/windows.js @@ -82,6 +82,10 @@ export const windowsReducer = (state = {}, action) => { y: action.payload.size.y, }, }; + case ActionTypes.NEXT_CANVAS: + return setCanvasIndex(state, action.windowId, currentIndex => currentIndex + 1); + case ActionTypes.PREVIOUS_CANVAS: + return setCanvasIndex(state, action.windowId, currentIndex => currentIndex - 1); case ActionTypes.SET_CANVAS: return setCanvasIndex(state, action.windowId, currentIndex => action.canvasIndex); case ActionTypes.ADD_COMPANION_WINDOW: