diff --git a/packages/xod-client-electron/src/index.jsx b/packages/xod-client-electron/src/index.jsx index b98e9291..961905c6 100644 --- a/packages/xod-client-electron/src/index.jsx +++ b/packages/xod-client-electron/src/index.jsx @@ -4,7 +4,11 @@ import ReactDOM from 'react-dom'; import { Root, initialState } from 'xod-client'; import App from './view/containers/App'; -const extraReducers = {}; +import popupsReducer from './popups/reducer'; + +const extraReducers = { + popups: popupsReducer, +}; ReactDOM.render( { + switch (action.type) { + case UPLOAD: + case UPLOAD_TO_ARDUINO: { + if (action.meta.status === 'started') { + return showOnlyPopup(POPUP_ID.UPLOADING, {}, state); + } + if (action.meta.status === 'deleted') { + return hideOnePopup(POPUP_ID.UPLOADING, state); + } + + return state; + } + + case CREATE_WORKSPACE_REQUESTED: + return showOnlyPopup(POPUP_ID.CREATING_WORKSPACE, action.payload, state); + case SWITCH_WORKSPACE_REQUESTED: + return showOnlyPopup(POPUP_ID.SWITCHING_WORKSPACE, action.payload, state); + + case CREATE_WORKSPACE: + return hideOnePopup(POPUP_ID.CREATING_WORKSPACE, state); + case SWITCH_WORKSPACE: + return hideOnePopup(POPUP_ID.SWITCHING_WORKSPACE, state); + + default: + return popupsReducer(state, action); + } +}; diff --git a/packages/xod-client-electron/src/settings/actionTypes.js b/packages/xod-client-electron/src/settings/actionTypes.js new file mode 100644 index 00000000..ec360ef2 --- /dev/null +++ b/packages/xod-client-electron/src/settings/actionTypes.js @@ -0,0 +1,5 @@ +export const CREATE_WORKSPACE_REQUESTED = 'CREATE_WORKSPACE_REQUESTED'; +export const SWITCH_WORKSPACE_REQUESTED = 'SWITCH_WORKSPACE_REQUESTED'; + +export const CREATE_WORKSPACE = 'CREATE_WORKSPACE'; +export const SWITCH_WORKSPACE = 'SWITCH_WORKSPACE'; diff --git a/packages/xod-client-electron/src/settings/actions.js b/packages/xod-client-electron/src/settings/actions.js index 0f1d42c3..98cc60ce 100644 --- a/packages/xod-client-electron/src/settings/actions.js +++ b/packages/xod-client-electron/src/settings/actions.js @@ -1,57 +1,24 @@ -import R from 'ramda'; -import { openWorkspace } from 'xod-client'; - import { - SET_WORKSPACE, - CHECK_WORKSPACE, - CHANGE_WORKSPACE, + CREATE_WORKSPACE_REQUESTED, + SWITCH_WORKSPACE_REQUESTED, + CREATE_WORKSPACE, + SWITCH_WORKSPACE, } from './actionTypes'; -import { createAsyncAction } from '../view/actions'; -export const setWorkspace = newPath => ({ - type: SET_WORKSPACE, - payload: newPath, +export const requestCreateWorkspace = (path, force) => ({ + type: CREATE_WORKSPACE_REQUESTED, + payload: { path, force }, +}); +export const requestSwitchWorkspace = opts => ({ + type: SWITCH_WORKSPACE_REQUESTED, + payload: opts, }); -export const checkWorkspace = createAsyncAction({ - eventName: 'checkWorkspace', - actionType: CHECK_WORKSPACE, - notify: false, - silent: true, - onComplete: (data, dispatch) => { - if (data.valid && data.libs) { - dispatch(openWorkspace(R.values(data.libs))); - return; - } - - // ask user to define workspace - dispatch(setWorkspace(null)); - }, - onError: (data, dispatch) => { - // ask again - dispatch(setWorkspace(null)); - }, +export const createWorkspace = path => ({ + type: CREATE_WORKSPACE, + payload: { path }, }); - -export const changeWorkspace = createAsyncAction({ - eventName: 'changeWorkspace', - actionType: CHANGE_WORKSPACE, - messages: { - complete: 'Workspace has been changed!', - error: 'Failed to change workspace.', - }, - silent: true, - onComplete: (data, dispatch) => { - dispatch(setWorkspace(data.path)); - dispatch(openWorkspace(R.values(data.libs))); - }, - onError: (data, dispatch) => { - // ask again - dispatch(setWorkspace(null)); - }, +export const switchWorkspace = path => ({ + type: SWITCH_WORKSPACE, + payload: { path }, }); - -export default { - setWorkspace, - changeWorkspace, -}; diff --git a/packages/xod-client-electron/src/upload/actionTypes.js b/packages/xod-client-electron/src/upload/actionTypes.js index 528decd5..77150b5a 100644 --- a/packages/xod-client-electron/src/upload/actionTypes.js +++ b/packages/xod-client-electron/src/upload/actionTypes.js @@ -1,7 +1,9 @@ export const UPLOAD = 'UPLOAD'; export const UPLOAD_TO_ARDUINO = 'UPLOAD_TO_ARDUINO'; +export const REQUEST_INSTALL_ARDUINO_IDE = 'REQUEST_INSTALL_ARDUINO_IDE'; export default { UPLOAD, UPLOAD_TO_ARDUINO, + REQUEST_INSTALL_ARDUINO_IDE, }; diff --git a/packages/xod-client-electron/src/upload/actions.js b/packages/xod-client-electron/src/upload/actions.js index 5ffb1e9e..07f0f423 100644 --- a/packages/xod-client-electron/src/upload/actions.js +++ b/packages/xod-client-electron/src/upload/actions.js @@ -3,7 +3,7 @@ import { transpileForEspruino } from 'xod-js'; import { foldEither } from 'xod-func-tools'; import uploadToEspruino from 'xod-espruino-upload'; -import { UPLOAD } from './actionTypes'; +import { UPLOAD, REQUEST_INSTALL_ARDUINO_IDE } from './actionTypes'; const progressUpload = (dispatch, id) => (message, percentage) => dispatch( client.progressProcess( @@ -50,6 +50,11 @@ export const uploadToArduino = () => (dispatch) => { }; }; +export const requestInstallArduinoIDE = () => ({ + type: REQUEST_INSTALL_ARDUINO_IDE, + payload: {}, +}); + export default { upload, uploadToArduino, diff --git a/packages/xod-client-electron/src/view/containers/App.jsx b/packages/xod-client-electron/src/view/containers/App.jsx index c21f6682..0d836f12 100644 --- a/packages/xod-client-electron/src/view/containers/App.jsx +++ b/packages/xod-client-electron/src/view/containers/App.jsx @@ -20,6 +20,7 @@ import { import * as actions from '../actions'; import * as uploadActions from '../../upload/actions'; import { getUploadProcess } from '../../upload/selectors'; +import * as settingsActions from '../../settings/actions'; import { SAVE_PROJECT } from '../actionTypes'; import { UPLOAD, UPLOAD_TO_ARDUINO } from '../../upload/actionTypes'; import PopupSetWorkspace from '../../settings/components/PopupSetWorkspace'; @@ -93,10 +94,10 @@ class App extends client.App { this.onArduinoPathChange = this.onArduinoPathChange.bind(this); this.hideAllPopups = this.hideAllPopups.bind(this); + this.showPopupCreateProject = this.showPopupCreateProject.bind(this); this.showPopupProjectSelection = this.showPopupProjectSelection.bind(this); this.showPopupSetWorkspace = this.showPopupSetWorkspace.bind(this); this.showPopupSetWorkspaceNotCancellable = this.showPopupSetWorkspaceNotCancellable.bind(this); - this.showPopupCreateProject = this.showPopupCreateProject.bind(this); this.showArduinoIdeNotFoundPopup = this.showArduinoIdeNotFoundPopup.bind(this); this.showCreateWorkspacePopup = this.showCreateWorkspacePopup.bind(this); @@ -141,7 +142,6 @@ class App extends client.App { } onUpload() { - this.showUploadProgressPopup(); this.props.actions.upload(); } @@ -149,7 +149,6 @@ class App extends client.App { const { project, currentPatchPath } = this.props; const proc = (processActions !== null) ? processActions : this.props.actions.uploadToArduino(); - this.showUploadProgressPopup(); ipcRenderer.send(UPLOAD_TO_ARDUINO, { pab, project, @@ -165,7 +164,6 @@ class App extends client.App { } if (payload.failure) { if (payload.errorCode === ERROR_CODES.IDE_NOT_FOUND) { - this.hideAllPopups(); this.showArduinoIdeNotFoundPopup(); ipcRenderer.once('SET_ARDUINO_IDE', (evt, response) => { @@ -223,12 +221,12 @@ class App extends client.App { } onWorkspaceChange(val) { - this.hideAllPopups(); + this.props.actions.switchWorkspace(val); ipcRenderer.send(EVENTS.SWITCH_WORKSPACE, val); } onWorkspaceCreate(path) { - this.hideAllPopups(); + this.props.actions.createWorkspace(path); ipcRenderer.send(EVENTS.CREATE_WORKSPACE, path); } @@ -241,7 +239,6 @@ class App extends client.App { } onUploadPopupClose(id) { - this.hideAllPopups(); this.props.actions.deleteProcess(id, UPLOAD); } @@ -409,16 +406,8 @@ class App extends client.App { Menu.setApplicationMenu(menu); } - showUploadProgressPopup() { - this.props.actions.showPopup(client.POPUP_ID.UPLOADING); - } - - showCodePopup() { - this.props.actions.showPopup(client.POPUP_ID.SHOWING_CODE, { code: this.state.code }); - } - showPopupCreateProject() { - this.props.actions.showPopup(client.POPUP_ID.CREATING_PROJECT); + this.props.actions.requestCreateProject(); } showPopupProjectSelection(projects) { @@ -429,23 +418,23 @@ class App extends client.App { status: REDUCER_STATUS.PENDING, }; - this.props.actions.showPopup(client.POPUP_ID.OPENING_PROJECT, data); + this.props.actions.requestOpenProject(data); } showArduinoIdeNotFoundPopup() { - this.props.actions.showPopup(client.POPUP_ID.ARDUINO_IDE_NOT_FOUND); + this.props.actions.requestInstallArduinoIDE(); } showPopupSetWorkspace() { - this.props.actions.showPopup(client.POPUP_ID.SWITCHING_WORKSPACE, { disposable: false }); + this.props.actions.requestSwitchWorkspace({ disposable: false }); } showPopupSetWorkspaceNotCancellable() { - this.props.actions.showPopup(client.POPUP_ID.SWITCHING_WORKSPACE, { disposable: true }); + this.props.actions.requestSwitchWorkspace({ disposable: true }); } showCreateWorkspacePopup(path, force) { - this.props.actions.showPopup(client.POPUP_ID.CREATING_WORKSPACE, { path, force }); + this.props.actions.requestCreateWorkspace(path, force); } hideAllPopups() { @@ -562,6 +551,13 @@ const mapStateToProps = (state) => { const mapDispatchToProps = dispatch => ({ actions: bindActionCreators({ + requestCreateProject: client.requestCreateProject, + requestOpenProject: client.requestOpenProject, + requestInstallArduinoIDE: uploadActions.requestInstallArduinoIDE, + requestSwitchWorkspace: settingsActions.requestSwitchWorkspace, + requestCreateWorkspace: settingsActions.requestCreateWorkspace, + createWorkspace: settingsActions.createWorkspace, + switchWorkspace: settingsActions.switchWorkspace, createProject: client.createProject, requestRenameProject: client.requestRenameProject, setMode: client.setMode, diff --git a/packages/xod-client/src/core/actionTypes.js b/packages/xod-client/src/core/actionTypes.js index c3caa6f5..88d4d045 100644 --- a/packages/xod-client/src/core/actionTypes.js +++ b/packages/xod-client/src/core/actionTypes.js @@ -1,3 +1,5 @@ export * from '../editor/actionTypes'; export * from '../project/actionTypes'; export * from '../messages/actionTypes'; + +export const SHOW_CODE = 'SHOW_CODE'; diff --git a/packages/xod-client/src/core/actions.js b/packages/xod-client/src/core/actions.js index aa5970dc..5e8c36d2 100644 --- a/packages/xod-client/src/core/actions.js +++ b/packages/xod-client/src/core/actions.js @@ -2,6 +2,9 @@ import { undoPatch, redoPatch, } from '../project/actions'; +import { + SHOW_CODE, +} from './actionTypes'; import { getCurrentPatchPath } from '../editor/selectors'; export const undoCurrentPatch = () => (dispatch, getState) => { @@ -14,6 +17,11 @@ export const redoCurrentPatch = () => (dispatch, getState) => { if (currentPatchPath) dispatch(redoPatch(currentPatchPath)); }; +export const showCode = code => ({ + actionType: SHOW_CODE, + payload: { code }, +}); + export * from '../editor/actions'; export * from '../project/actions'; export * from '../messages/actions'; diff --git a/packages/xod-client/src/core/containers/App.jsx b/packages/xod-client/src/core/containers/App.jsx index b1e0aec5..ffe8f11c 100644 --- a/packages/xod-client/src/core/containers/App.jsx +++ b/packages/xod-client/src/core/containers/App.jsx @@ -69,8 +69,7 @@ export default class App extends React.Component { this.props.actions.addError(error.message); }, (code) => { - this.setState({ code }); - this.showCodePopup(); + this.props.actions.showCode(code); }, eitherCode ); @@ -87,5 +86,6 @@ App.propTypes = { actions: React.PropTypes.shape({ addError: React.PropTypes.func.isRequired, importProject: React.PropTypes.func.isRequired, + showCode: React.PropTypes.func.isRequired, }), }; diff --git a/packages/xod-client/src/index.js b/packages/xod-client/src/index.js index 393e735c..2ddd77ab 100644 --- a/packages/xod-client/src/index.js +++ b/packages/xod-client/src/index.js @@ -16,6 +16,8 @@ import * as EditorConstants from './editor/constants'; import * as UtilsConstants from './utils/constants'; import * as PopupConstants from './popups/constants'; +import popupsReducer, { showOnlyPopup, hideOnePopup } from './popups/reducer'; + import * as BrowserUtils from './utils/browser'; import * as MenuUtils from './utils/menu'; import sanctuaryPropType from './utils/sanctuaryPropType'; @@ -70,6 +72,8 @@ export { default as DevTools } from './core/containers/DevTools'; export { default as initialState } from './core/state'; +export { default as popupsReducer, showOnlyPopup, hideOnePopup } from './popups/reducer'; + export default Object.assign({ App, Root, @@ -86,6 +90,9 @@ export default Object.assign({ menu: MenuUtils, sanctuaryPropType, initialState, + popupsReducer, + showOnlyPopup, + hideOnePopup, }, UtilsSelectors, EditorSelectors, diff --git a/packages/xod-client/src/popups/actionTypes.js b/packages/xod-client/src/popups/actionTypes.js index 58e32603..b69bc95d 100644 --- a/packages/xod-client/src/popups/actionTypes.js +++ b/packages/xod-client/src/popups/actionTypes.js @@ -1,4 +1,3 @@ -export const SHOW_POPUP = 'SHOW_POPUP'; export const HIDE_ALL_POPUPS = 'HIDE_ALL_POPUPS'; export default {}; diff --git a/packages/xod-client/src/popups/actions.js b/packages/xod-client/src/popups/actions.js index 5363c74b..b248754f 100644 --- a/packages/xod-client/src/popups/actions.js +++ b/packages/xod-client/src/popups/actions.js @@ -1,12 +1,4 @@ -import { SHOW_POPUP, HIDE_ALL_POPUPS } from './actionTypes'; - -export const showPopup = (popupId, data = {}) => ({ - type: SHOW_POPUP, - payload: { - id: popupId, - data, - }, -}); +import { HIDE_ALL_POPUPS } from './actionTypes'; export const hideAllPopups = () => ({ type: HIDE_ALL_POPUPS, diff --git a/packages/xod-client/src/popups/reducer.js b/packages/xod-client/src/popups/reducer.js index 12de033a..179e4fef 100644 --- a/packages/xod-client/src/popups/reducer.js +++ b/packages/xod-client/src/popups/reducer.js @@ -9,7 +9,6 @@ import { PROJECT_RENAME_REQUESTED, } from '../projectBrowser/actionTypes'; import { - SHOW_POPUP, HIDE_ALL_POPUPS, } from './actionTypes'; @@ -17,8 +16,15 @@ import { PATCH_ADD, PATCH_DELETE, PATCH_RENAME, + PROJECT_CREATE_REQUESTED, + PROJECT_OPEN_REQUESTED, + PROJECT_CREATE, + PROJECT_OPEN, PROJECT_RENAME, } from '../project/actionTypes'; +import { + SHOW_CODE, +} from '../core/actionTypes'; // ============================================================================= // @@ -46,7 +52,7 @@ const showPopup = R.curry( const hideAll = R.map(hidePopup); // :: State -> State -const hideOnePopup = R.curry( +export const hideOnePopup = R.curry( (id, state) => R.over( R.lensProp(id), hidePopup, @@ -64,7 +70,7 @@ const showOnePopup = R.curry( ); // :: State -> State -const showOnlyPopup = R.curry( +export const showOnlyPopup = R.curry( (id, data, state) => R.compose( showOnePopup(id, data), hideAll @@ -80,34 +86,38 @@ const popupsReducer = (state = initialState, action) => { switch (action.type) { case PATCH_CREATE_REQUESTED: return showOnlyPopup(POPUP_ID.CREATING_PATCH, {}, state); - case PATCH_RENAME_REQUESTED: return showOnlyPopup(POPUP_ID.RENAMING_PATCH, {}, state); - case PATCH_DELETE_REQUESTED: return showOnlyPopup(POPUP_ID.DELETING_PATCH, {}, state); + case PROJECT_CREATE_REQUESTED: + return showOnlyPopup(POPUP_ID.CREATING_PROJECT, {}, state); + case PROJECT_OPEN_REQUESTED: + return showOnlyPopup(POPUP_ID.OPENING_PROJECT, action.payload, state); case PROJECT_RENAME_REQUESTED: return showOnlyPopup(POPUP_ID.RENAMING_PROJECT, {}, state); + case SHOW_CODE: + return showOnlyPopup(POPUP_ID.SHOWING_CODE, action.payload, state); + case PATCH_ADD: return hideOnePopup(POPUP_ID.CREATING_PATCH, state); - case PATCH_RENAME: return hideOnePopup(POPUP_ID.RENAMING_PATCH, state); - case PATCH_DELETE: return hideOnePopup(POPUP_ID.DELETING_PATCH, state); + case PROJECT_CREATE: + return hideOnePopup(POPUP_ID.CREATING_PROJECT, state); + case PROJECT_OPEN: + return hideOnePopup(POPUP_ID.OPENING_PROJECT, state); case PROJECT_RENAME: return hideOnePopup(POPUP_ID.RENAMING_PROJECT, state); case HIDE_ALL_POPUPS: return initialState; - case SHOW_POPUP: - return showOnlyPopup(action.payload.id, action.payload.data, state); - default: return state; } diff --git a/packages/xod-client/src/project/actionTypes.js b/packages/xod-client/src/project/actionTypes.js index c39fb942..3f478c26 100644 --- a/packages/xod-client/src/project/actionTypes.js +++ b/packages/xod-client/src/project/actionTypes.js @@ -1,3 +1,6 @@ +export const PROJECT_CREATE_REQUESTED = 'PROJECT_CREATE_REQUESTED'; +export const PROJECT_OPEN_REQUESTED = 'PROJECT_OPEN_REQUESTED'; + export const PROJECT_CREATE = 'PROJECT_CREATE'; export const PROJECT_RENAME = 'PROJECT_RENAME'; export const PROJECT_OPEN = 'PROJECT_OPEN'; diff --git a/packages/xod-client/src/project/actions.js b/packages/xod-client/src/project/actions.js index a9c37c79..ffd8489c 100644 --- a/packages/xod-client/src/project/actions.js +++ b/packages/xod-client/src/project/actions.js @@ -6,6 +6,16 @@ import * as ActionType from './actionTypes'; import { isPatchPathTaken } from './utils'; import { getCurrentPatchPath } from '../editor/selectors'; +export const requestCreateProject = () => ({ + type: ActionType.PROJECT_CREATE_REQUESTED, + payload: {}, +}); + +export const requestOpenProject = data => ({ + type: ActionType.PROJECT_OPEN_REQUESTED, + payload: data, +}); + export const createProject = projectName => (dispatch) => { if (!isValidIdentifier(projectName)) { return dispatch(addError(PROJECT_BROWSER_ERRORS.INVALID_PROJECT_NAME));