From aff7e8cb3a48962d758af0ca6e6b1a4fcc70234f Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sun, 6 Oct 2019 19:05:25 -0500 Subject: [PATCH] Added remove remote mount --- src/App.js | 4 +++ src/components/MountItem/MountItem.js | 27 +++++++++++++++++- src/components/YesNo/YesNo.css | 0 src/components/YesNo/YesNo.js | 41 +++++++++++++++++++++++++++ src/constants.js | 3 ++ src/redux/actions/common_actions.js | 39 +++++++++++++++++++++++++ src/redux/actions/mount_actions.js | 26 +++++++++++++++++ src/redux/reducers/common_reducer.js | 10 +++++++ src/redux/reducers/mount_reducer.js | 11 +++++++ src/renderer/ipc/MountsIPC.js | 13 +++++++++ 10 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/components/YesNo/YesNo.css create mode 100644 src/components/YesNo/YesNo.js diff --git a/src/App.js b/src/App.js index 81808ee..baa6a0e 100644 --- a/src/App.js +++ b/src/App.js @@ -27,6 +27,7 @@ import { loadReleases, setDismissUIUpgrade } from './redux/actions/release_version_actions'; +import YesNo from './components/YesNo/YesNo'; const Constants = require('./constants'); const Scheduler = require('node-schedule'); @@ -125,6 +126,7 @@ class App extends IPCContainer { !this.props.DismissDependencies && this.props.AllowMount; + const confirmDisplay = this.createModalConditionally(this.props.DisplayConfirmYesNo, ); const infoDisplay = this.createModalConditionally(this.props.DisplayInfo, , true); const rebootDisplay = this.createModalConditionally(this.props.RebootRequired, ); const configDisplay = this.createModalConditionally(showConfig, ); @@ -165,6 +167,7 @@ class App extends IPCContainer { {upgradeDisplay} {configDisplay} {infoDisplay} + {confirmDisplay} {downloadDisplay} {rebootDisplay} {errorDisplay} @@ -208,6 +211,7 @@ const mapStateToProps = state => { AppReady: state.common.AppReady, DismissDependencies: state.install.DismissDependencies, DisplayConfiguration: state.mounts.DisplayConfiguration, + DisplayConfirmYesNo: state.common.DisplayConfirmYesNo, DisplayError: state.error.DisplayError, DisplayInfo: state.error.DisplayInfo, DisplaySelectAppPlatform: state.common.DisplaySelectAppPlatform, diff --git a/src/components/MountItem/MountItem.js b/src/components/MountItem/MountItem.js index 943f622..494fb7f 100644 --- a/src/components/MountItem/MountItem.js +++ b/src/components/MountItem/MountItem.js @@ -8,7 +8,9 @@ import Text from '../UI/Text/Text'; import Grid from '../UI/Grid/Grid'; import configureImage from '../../assets/images/configure.png'; import RootElem from '../../hoc/RootElem/RootElem'; -import {displayConfiguration, setProviderState} from '../../redux/actions/mount_actions'; +import {displayConfiguration, removeRemoteMount, setProviderState} from '../../redux/actions/mount_actions'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import { faTrashAlt} from '@fortawesome/free-solid-svg-icons'; const mapStateToProps = (state, ownProps) => { return { @@ -21,6 +23,7 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { displayConfiguration: (provider, remote) => dispatch(displayConfiguration(provider, remote)), + removeRemoteMount: provider => dispatch(removeRemoteMount(provider)), setProviderState: (provider, state) => dispatch(setProviderState(provider, state)), } }; @@ -139,6 +142,27 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => { ); + let removeControl; + if (props.remote) { + const removeDisabled = !props.MState.AllowMount || props.MState.Mounted; + const removeStyle = { + cursor: removeDisabled ? 'no-drop' : 'pointer' + }; + const handleRemoveMount = () => { + if (!removeDisabled) { + props.removeRemoteMount(props.provider); + } + }; + removeControl = ( + dimensions.columns - 6} + href={void(0)} + onClick={handleRemoveMount} + row={secondRow + 3} + style={removeStyle}> + + ); + } + return (
@@ -152,6 +176,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => { {actionsDisplay} {autoMountControl} {autoRestartControl} + {removeControl}
); diff --git a/src/components/YesNo/YesNo.css b/src/components/YesNo/YesNo.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/YesNo/YesNo.js b/src/components/YesNo/YesNo.js new file mode 100644 index 0000000..9c9be90 --- /dev/null +++ b/src/components/YesNo/YesNo.js @@ -0,0 +1,41 @@ +import {connect} from 'react-redux'; +import Button from '../UI/Button/Button'; +import Box from '../UI/Box/Box'; +import React from 'react'; +import './YesNo.css'; +import {hideConfirmYesNo} from '../../redux/actions/common_actions'; + +const mapStateToProps = state => { + return { + Title: state.common.ConfirmTitle, + } +}; + +const mapDispatchToProps = dispatch => { + return { + hideConfirmYesNo: confirmed => dispatch(hideConfirmYesNo(confirmed)), + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(props => { + return ( + +
+

{props.Title}

+
+ + + + + + + +
+ + + +
+
); +}); \ No newline at end of file diff --git a/src/constants.js b/src/constants.js index 4924199..5af89d2 100644 --- a/src/constants.js +++ b/src/constants.js @@ -118,6 +118,9 @@ exports.IPC_Install_Upgrade_Reply = 'install_upgrade_reply'; exports.IPC_Mount_Drive = 'mount_drive'; exports.IPC_Mount_Drive_Reply = 'mount_drive_reply'; +exports.IPC_Remove_Remote_Mount = 'remove_remote_mount'; +exports.IPC_Remove_Remote_Mount_Reply = 'remove_remote_mount_reply'; + exports.IPC_Reboot_System = 'reboot_system'; exports.IPC_Save_State = 'save_state'; diff --git a/src/redux/actions/common_actions.js b/src/redux/actions/common_actions.js index b602564..fa94d05 100644 --- a/src/redux/actions/common_actions.js +++ b/src/redux/actions/common_actions.js @@ -3,6 +3,45 @@ import {createAction} from 'redux-starter-kit'; import {getIPCRenderer} from '../../utils'; const ipcRenderer = getIPCRenderer(); +let yesNoResolvers = []; + +export const confirmYesNo = title => { + return dispatch => { + return new Promise(resolve => { + dispatch(handleConfirmYesNo(true, title, resolve)); + }); + }; +}; + +export const hideConfirmYesNo = confirmed => { + return dispatch => { + dispatch(handleConfirmYesNo(false, confirmed)); + }; +}; + +const handleConfirmYesNo = (show, titleOrConfirmed, resolve) => { + return dispatch => { + if (show) { + yesNoResolvers.push(resolve); + dispatch(displayConfirmYesNo(show, titleOrConfirmed)) + } else { + yesNoResolvers[0](titleOrConfirmed); + yesNoResolvers.splice(0, 1); + dispatch(displayConfirmYesNo(false)) + } + }; +}; + +export const DISPLAY_CONFIRM_YES_NO = 'common/displayConfirmYesNo'; +const displayConfirmYesNo = (show, title) => { + return { + type: DISPLAY_CONFIRM_YES_NO, + payload: { + show, + title + }, + }; +}; export const displaySelectAppPlatform = display => { return dispatch => { diff --git a/src/redux/actions/mount_actions.js b/src/redux/actions/mount_actions.js index 3f6667e..0219cc2 100644 --- a/src/redux/actions/mount_actions.js +++ b/src/redux/actions/mount_actions.js @@ -1,6 +1,7 @@ import * as Constants from '../../constants'; import {createAction} from 'redux-starter-kit'; import {getIPCRenderer} from '../../utils'; +import {confirmYesNo, displayConfirmYesNo} from './common_actions'; export const DISPLAY_CONFIGURATION = 'mounts/displayConfiguration'; export const displayConfiguration = (provider, remote) => { @@ -13,6 +14,31 @@ export const displayConfiguration = (provider, remote) => { }; }; +export const removeRemoteMount = provider => { + return dispatch => { + dispatch(confirmYesNo('Delete [' + provider.substr(6) + ']?')) + .then(confirmed => { + if (confirmed) { + dispatch(removeRemoteMount2(provider)); + } + }); + }; +}; + +const removeRemoteMount2 = provider => { + return dispatch => { + const ipcRenderer = getIPCRenderer(); + ipcRenderer.once(Constants.IPC_Remove_Remote_Mount_Reply, (_, arg) => { + if (arg.data.Success) { + dispatch(removeRemoteMount3(provider)); + } + }); + ipcRenderer.send(Constants.IPC_Remove_Remote_Mount, provider.substr(6)); + }; +}; + +export const removeRemoteMount3 = createAction('mounts/removeRemoteMount3'); + export const RESET_MOUNTS_STATE = 'mounts/resetMountsState'; export const resetMountsState = () => { return { diff --git a/src/redux/reducers/common_reducer.js b/src/redux/reducers/common_reducer.js index b4072c1..173db4b 100644 --- a/src/redux/reducers/common_reducer.js +++ b/src/redux/reducers/common_reducer.js @@ -1,5 +1,6 @@ import {createReducer} from 'redux-starter-kit'; import { + DISPLAY_CONFIRM_YES_NO, notifyRebootRequired, setAllowMount, setApplicationReady, @@ -12,11 +13,20 @@ export const createCommonReducer = (platformInfo, version) => { AllowMount: false, AppPlatform: platformInfo.AppPlatform, AppReady: false, + DisplayConfirmYesNo: false, + ConfirmTitle: null, DisplaySelectAppPlatform: false, Platform: platformInfo.Platform, RebootRequired: false, Version: version, }, { + [DISPLAY_CONFIRM_YES_NO]: (state, action) => { + return { + ...state, + DisplayConfirmYesNo: action.payload.show, + ConfirmTitle: action.payload.show ? action.payload.title : null, + } + }, [SET_DISPLAY_SELECT_APPPLATFORM]: (state, action) => { return { ...state, diff --git a/src/redux/reducers/mount_reducer.js b/src/redux/reducers/mount_reducer.js index 4f8b5ff..e4e2837 100644 --- a/src/redux/reducers/mount_reducer.js +++ b/src/redux/reducers/mount_reducer.js @@ -2,6 +2,7 @@ import * as Constants from '../../constants'; import {createReducer} from 'redux-starter-kit'; import { DISPLAY_CONFIGURATION, + removeRemoteMount3, RESET_MOUNTS_STATE, SET_ALLOW_MOUNT, setAutoMountProcessed, @@ -62,6 +63,16 @@ export const createMountReducer = state => { DisplayRemoteConfiguration: action.payload.remote, }; }, + [removeRemoteMount3]: (state, action) => { + let providerState = {...state.ProviderState}; + delete providerState[action.payload]; + const remoteMounts = state.RemoteMounts.filter(i => i !== action.payload); + return { + ...state, + ProviderState: providerState, + RemoteMounts: remoteMounts, + }; + }, [RESET_MOUNTS_STATE]: (state, action) => { return { ...state, diff --git a/src/renderer/ipc/MountsIPC.js b/src/renderer/ipc/MountsIPC.js index dd224c6..6e26fcf 100644 --- a/src/renderer/ipc/MountsIPC.js +++ b/src/renderer/ipc/MountsIPC.js @@ -2,6 +2,7 @@ const Constants = require('../../constants'); const fs = require('fs'); const helpers = require('../../helpers'); const os = require('os'); +const path = require('path'); let expectedUnmount = {}; let firstMountCheck = true; @@ -230,6 +231,18 @@ const addListeners = (ipcMain, setTrayImage, standardIPCReply) => { } }); + ipcMain.on(Constants.IPC_Remove_Remote_Mount, (event, data) => { + data = data.replace(':', '_'); + const dataDirectory = path.resolve(path.join(helpers.getDataDirectory(), '..', 'remote', data)); + + try { + helpers.removeDirectoryRecursively(dataDirectory); + standardIPCReply(event, Constants.IPC_Remove_Remote_Mount_Reply, {DataDirectory: dataDirectory}); + } catch (e) { + standardIPCReply(event, Constants.IPC_Remove_Remote_Mount_Reply, {DataDirectory: dataDirectory}, e); + } + }); + ipcMain.on(Constants.IPC_Unmount_All_Drives, (event, data) => { unmountAllDrives(); standardIPCReply(event, Constants.IPC_Unmount_All_Drives_Reply);