Refactor dialogs

This commit is contained in:
2021-05-04 01:15:06 -05:00
parent 8ffdd321b3
commit c6fb1d08e7
12 changed files with 371 additions and 397 deletions

View File

@@ -3,7 +3,7 @@ import Button from '../UI/Button/Button';
import Box from '../UI/Box/Box'; import Box from '../UI/Box/Box';
import React from 'react'; import React from 'react';
import './YesNo.css'; import './YesNo.css';
import { hideConfirmYesNo } from '../../redux/actions/common_actions'; import { confirmYesNoAction } from '../../redux/actions/common_actions';
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
@@ -13,7 +13,7 @@ const mapStateToProps = (state) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
hideConfirmYesNo: (confirmed) => dispatch(hideConfirmYesNo(confirmed)), confirm: (confirmed) => dispatch(confirmYesNoAction.complete(confirmed)),
}; };
}; };
@@ -35,14 +35,12 @@ export default connect(
<tbody> <tbody>
<tr> <tr>
<td width="50%"> <td width="50%">
<Button buttonStyles={{ width: '100%' }} clicked={() => props.hideConfirmYesNo(true)}> <Button buttonStyles={{ width: '100%' }} clicked={() => props.confirm(true)}>
Yes Yes
</Button> </Button>
</td> </td>
<td width="50%"> <td width="50%">
<Button <Button buttonStyles={{ width: '100%' }} clicked={() => props.confirm(false)}>
buttonStyles={{ width: '100%' }}
clicked={() => props.hideConfirmYesNo(false)}>
No No
</Button> </Button>
</td> </td>

View File

@@ -5,7 +5,7 @@ import DropDown from '../../components/UI/DropDown/DropDown';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Text from '../../components/UI/Text/Text'; import Text from '../../components/UI/Text/Text';
import { Component } from 'react'; import { Component } from 'react';
import { addEditHost, completeAddEditHost } from '../../redux/actions/host_actions'; import { addEditHostAction } from '../../redux/actions/host_actions';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createDismissDisplay } from '../../utils.jsx'; import { createDismissDisplay } from '../../utils.jsx';
import { notifyError } from '../../redux/actions/error_actions'; import { notifyError } from '../../redux/actions/error_actions';
@@ -217,8 +217,8 @@ const mapStateToProps = (state) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
Close: () => dispatch(addEditHost(false)), Close: () => dispatch(addEditHostAction.complete(false)),
completeAddEditHost: (host_data) => dispatch(completeAddEditHost(true, host_data)), completeAddEditHost: (host_data) => dispatch(addEditHostAction.complete(true, { host_data })),
notifyError: (msg) => dispatch(notifyError(msg)), notifyError: (msg) => dispatch(notifyError(msg)),
}; };
}; };

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { Component } from 'react'; import { Component } from 'react';
import './AddMount.css'; import './AddMount.css';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@@ -11,23 +12,6 @@ import { createModalConditionally } from '../../utils.jsx';
import DropDown from '../../components/UI/DropDown/DropDown'; import DropDown from '../../components/UI/DropDown/DropDown';
import * as Constants from '../../constants'; import * as Constants from '../../constants';
const mapStateToProps = (state) => {
return {
RemoteMounts: state.mounts.RemoteMounts,
S3Mounts: state.mounts.S3Mounts,
};
};
const mapDispatchToProps = (dispatch) => {
return {
addRemoteMount: (hostNameOrIp, port, token) =>
dispatch(addRemoteMount(hostNameOrIp, port, token)),
addS3Mount: (name, accessKey, secretKey, region, bucketName, url) =>
dispatch(addS3Mount(name, accessKey, secretKey, region, bucketName, url)),
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
};
};
const default_state = { const default_state = {
AccessKey: '', AccessKey: '',
BucketName: '', BucketName: '',
@@ -35,18 +19,14 @@ const default_state = {
DisplayS3: false, DisplayS3: false,
HostNameOrIp: '', HostNameOrIp: '',
Name: '', Name: '',
Port: 2000, Port: 20000,
Provider: Constants.S3_PROVIDER_LIST[0], Provider: Constants.S3_PROVIDER_LIST[0],
Region: Constants.S3_REGION_PROVIDER_REGION[0], Region: Constants.S3_REGION_PROVIDER_REGION[0],
SecretKey: '', SecretKey: '',
Token: '', Token: '',
}; };
export default connect( class AddMount extends Component {
mapStateToProps,
mapDispatchToProps
)(
class AddMount extends Component {
state = { state = {
...default_state, ...default_state,
}; };
@@ -296,5 +276,33 @@ export default connect(
</div> </div>
); );
} }
} }
);
const mapStateToProps = (state) => {
return {
RemoteMounts: state.mounts.RemoteMounts,
S3Mounts: state.mounts.S3Mounts,
};
};
const mapDispatchToProps = (dispatch) => {
return {
addRemoteMount: (hostNameOrIp, port, token) =>
dispatch(addRemoteMount(hostNameOrIp, port, token)),
addS3Mount: (name, accessKey, secretKey, region, bucketName, url) =>
dispatch(addS3Mount(name, accessKey, secretKey, region, bucketName, url)),
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
};
};
AddMount.propTypes = {
RemoteMounts: PropTypes.array.isRequired,
S3Mounts: PropTypes.array.isRequired,
addRemoteMount: PropTypes.func.isRequired,
addS3Mount: PropTypes.func.isRequired,
notifyError: PropTypes.func.isRequired,
remoteSupported: PropTypes.bool,
s3Supported: PropTypes.bool,
};
export default connect(mapStateToProps, mapDispatchToProps)(AddMount);

View File

@@ -1,24 +1,20 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { addEditHost } from '../../../redux/actions/host_actions'; import { addEditHostAction } from '../../../redux/actions/host_actions';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { faTrashAlt, faEdit } from '@fortawesome/free-solid-svg-icons'; import { faTrashAlt, faEdit } from '@fortawesome/free-solid-svg-icons';
// const mapStateToProps = (state) => {
// return {};
// };
//
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
addEditHost: (host_list, host_data, cb) => editHost: (host_list, host_data, cb) =>
dispatch(addEditHost(true, host_list, host_data, cb)), dispatch(addEditHostAction.display(true, cb, { host_list, host_data })),
}; };
}; };
const Host = ({ allowDelete, addEditHost, host_list, host_data, onChange, onDelete }) => { const Host = ({ allowDelete, editHost, host_list, host_data, onChange, onDelete }) => {
const handleEditHost = () => { const handleEditHost = () => {
addEditHost(host_list, host_data, (changed, host_data) => { editHost(host_list, host_data, (changed, { host_data }) => {
if (changed) { if (changed) {
onChange(host_data); onChange(host_data);
} }
@@ -74,7 +70,7 @@ const Host = ({ allowDelete, addEditHost, host_list, host_data, onChange, onDele
Host.propTypes = { Host.propTypes = {
allowDelete: PropTypes.bool.isRequired, allowDelete: PropTypes.bool.isRequired,
addEditHost: PropTypes.func.isRequired, editHost: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired,
host_data: PropTypes.object.isRequired, host_data: PropTypes.object.isRequired,

View File

@@ -4,9 +4,9 @@ import Host from './Host/Host';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Component } from 'react'; import { Component } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { confirmYesNo } from '../../redux/actions/common_actions'; import { confirmYesNoAction } from '../../redux/actions/common_actions';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { addEditHost } from '../../redux/actions/host_actions'; import { addEditHostAction } from '../../redux/actions/host_actions';
import { faPlusCircle } from '@fortawesome/free-solid-svg-icons'; import { faPlusCircle } from '@fortawesome/free-solid-svg-icons';
class HostList extends Component { class HostList extends Component {
@@ -24,7 +24,7 @@ class HostList extends Component {
componentWillUnmount() {} componentWillUnmount() {}
handleAddHost = () => { handleAddHost = () => {
this.props.addEditHost(this.state.items, (changed, host_data) => { this.props.AddHost(this.state.items, (changed, host_data) => {
if (changed) { if (changed) {
const items = [...this.state.items, host_data]; const items = [...this.state.items, host_data];
this.updateItems(items); this.updateItems(items);
@@ -104,13 +104,13 @@ class HostList extends Component {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
addEditHost: (list, cb) => dispatch(addEditHost(true, list, null, cb)), AddHost: (host_list, cb) => dispatch(addEditHostAction.display(true, cb, { host_list })),
ConfirmRemoveHost: (title, cb) => dispatch(confirmYesNo(title, cb)), ConfirmRemoveHost: (title, cb) => dispatch(confirmYesNoAction.display(true, cb, { title })),
}; };
}; };
HostList.propTypes = { HostList.propTypes = {
addEditHost: PropTypes.func.isRequired, AddHost: PropTypes.func.isRequired,
ConfirmRemoveHost: PropTypes.func.isRequired, ConfirmRemoveHost: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
value: PropTypes.array.isRequired, value: PropTypes.array.isRequired,

View File

@@ -1,30 +1,12 @@
import { createAction } from '@reduxjs/toolkit'; import { createAction } from '@reduxjs/toolkit';
import { createResponseDialogAction } from '../utils';
export const confirmYesNoAction = createResponseDialogAction('common', 'confirmYesNo');
import * as Constants from '../../constants'; import * as Constants from '../../constants';
import { getIPCRenderer } from '../../utils.jsx'; import { getIPCRenderer } from '../../utils.jsx';
const ipcRenderer = getIPCRenderer(); const ipcRenderer = getIPCRenderer();
let yesNoResolvers = [];
export const confirmYesNo = (title, cb) => {
return (dispatch) => {
if (cb) {
dispatch(confirmYesNo(title)).then((confirmed) => cb(confirmed));
} else {
return new Promise((resolve) => {
dispatch(handleConfirmYesNo(true, title, resolve));
});
}
};
};
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) => { export const displaySelectAppPlatform = (display) => {
return (dispatch) => { return (dispatch) => {
@@ -36,25 +18,6 @@ export const displaySelectAppPlatform = (display) => {
}; };
}; };
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 NOTIFY_APPLICATION_BUSY = 'common/notifyApplicationBusy'; export const NOTIFY_APPLICATION_BUSY = 'common/notifyApplicationBusy';
export const notifyApplicationBusy = (busy, transparent) => { export const notifyApplicationBusy = (busy, transparent) => {
return { return {

View File

@@ -1,41 +1,3 @@
let addEditHostResolvers = []; import { createResponseDialogAction } from '../utils';
export const addEditHost = (display, host_list, host_data, cb) => { export const addEditHostAction = createResponseDialogAction('host', 'displayAddEditHost');
return (dispatch) => {
if (cb) {
dispatch(addEditHost(display, host_list, host_data)).then(({ changed, host_data }) =>
cb(changed, host_data)
);
} else {
return new Promise((resolve) => {
dispatch(handleDisplayAddEditHost(display, host_list, host_data, resolve));
});
}
};
};
const handleDisplayAddEditHost = (display, host_list, host_data, resolve) => {
return (dispatch) => {
if (display) {
addEditHostResolvers.push(resolve);
dispatch(displayAddEditHost(display, host_list, host_data));
} else {
dispatch(completeAddEditHost(false));
}
};
};
export const completeAddEditHost = (changed, host_data) => {
return (dispatch) => {
if (changed) {
addEditHostResolvers[0]({ changed, host_data });
}
addEditHostResolvers.splice(0, 1);
dispatch(displayAddEditHost(false));
};
};
export const DISPLAY_ADD_EDIT_HOST = 'host/displayAddEditHost';
export const displayAddEditHost = (display, host_list, host_data) => {
return { type: DISPLAY_ADD_EDIT_HOST, payload: { display, host_data, host_list } };
};

View File

@@ -4,7 +4,7 @@ import * as Constants from '../../constants';
import { getIPCRenderer, getSelectedVersionFromState } from '../../utils.jsx'; import { getIPCRenderer, getSelectedVersionFromState } from '../../utils.jsx';
import { import {
confirmYesNo, confirmYesNoAction,
displaySelectAppPlatform, displaySelectAppPlatform,
setAllowMount, setAllowMount,
setApplicationReady, setApplicationReady,
@@ -206,9 +206,9 @@ export const installReleaseByVersion = (release, version) => {
}; };
if (getState().mounts.MountsBusy) { if (getState().mounts.MountsBusy) {
dispatch(confirmYesNo('Unmount all drives?')) dispatch(confirmYesNoAction.display(true, null, { title: 'Unmount all drives?' }))
.then((confirmed) => { .then(({ changed }) => {
if (confirmed) { if (changed) {
dispatch(unmountAll(install)); dispatch(unmountAll(install));
} }
}) })

View File

@@ -3,7 +3,7 @@ import { createAction } from '@reduxjs/toolkit';
import * as Constants from '../../constants'; import * as Constants from '../../constants';
import { getIPCRenderer } from '../../utils.jsx'; import { getIPCRenderer } from '../../utils.jsx';
import { confirmYesNo, saveState } from './common_actions'; import { confirmYesNoAction, saveState } from './common_actions';
import { notifyError } from './error_actions'; import { notifyError } from './error_actions';
export const addRemoteMount = (hostNameOrIp, port, token) => { export const addRemoteMount = (hostNameOrIp, port, token) => {
@@ -23,7 +23,7 @@ export const addRemoteMount = (hostNameOrIp, port, token) => {
Version: getState().relver.InstalledVersion, Version: getState().relver.InstalledVersion,
}); });
} else { } else {
dispatch(notifyError('Failed to create S3 instance: ' + arg.data.Error)); dispatch(notifyError('Failed to create remote mount: ' + arg.data.Error));
dispatch(setBusy(false)); dispatch(setBusy(false));
} }
}); });
@@ -32,7 +32,7 @@ export const addRemoteMount = (hostNameOrIp, port, token) => {
Items: [ Items: [
{ Name: 'RemoteMount.RemoteHostNameOrIp', Value: hostNameOrIp }, { Name: 'RemoteMount.RemoteHostNameOrIp', Value: hostNameOrIp },
{ Name: 'RemoteMount.RemoteToken', Value: token }, { Name: 'RemoteMount.RemoteToken', Value: token },
{ Name: 'RemoteMount.RemotePort', Value: port }, { Name: 'RemoteMount.RemotePort', Value: port.toString() },
{ Name: 'RemoteMount.IsRemoteMount', Value: 'true' }, { Name: 'RemoteMount.IsRemoteMount', Value: 'true' },
], ],
Provider: provider, Provider: provider,
@@ -96,13 +96,15 @@ export const displayConfiguration = (provider, remote, s3) => {
export const removeMount = (provider) => { export const removeMount = (provider) => {
return (dispatch) => { return (dispatch) => {
const isRemote = provider.startsWith('Remote'); const isRemote = provider.startsWith('Remote');
dispatch(confirmYesNo('Delete [' + provider.substr(isRemote ? 6 : 2) + ']?')).then( dispatch(
(confirmed) => { confirmYesNoAction.display(true, null, {
if (confirmed) { title: 'Delete [' + provider.substr(isRemote ? 6 : 2) + ']?',
})
).then(({ changed }) => {
if (changed) {
dispatch(removeMount2(provider)); dispatch(removeMount2(provider));
} }
} });
);
}; };
}; };

View File

@@ -1,7 +1,6 @@
import { createReducer } from '@reduxjs/toolkit'; import { createReducer } from '@reduxjs/toolkit';
import { import {
DISPLAY_CONFIRM_YES_NO, confirmYesNoAction,
NOTIFY_APPLICATION_BUSY, NOTIFY_APPLICATION_BUSY,
notifyRebootRequired, notifyRebootRequired,
SET_DISPLAY_SELECT_APPPLATFORM, SET_DISPLAY_SELECT_APPPLATFORM,
@@ -26,11 +25,12 @@ export const createCommonReducer = (platformInfo, version) => {
Version: version, Version: version,
}, },
{ {
[DISPLAY_CONFIRM_YES_NO]: (state, action) => { [confirmYesNoAction.action_type]: (state, action) => {
return { return {
...state, ...state,
DisplayConfirmYesNo: action.payload.show, DisplayConfirmYesNo: action.payload.display,
ConfirmTitle: action.payload.show ? action.payload.title : null, ConfirmTitle:
action.payload.display && action.payload.data ? action.payload.data.title : null,
}; };
}, },
[SET_DISPLAY_SELECT_APPPLATFORM]: (state, action) => { [SET_DISPLAY_SELECT_APPPLATFORM]: (state, action) => {

View File

@@ -1,21 +1,19 @@
import { createReducer } from '@reduxjs/toolkit'; import { createReducer } from '@reduxjs/toolkit';
import * as Actions from '../actions/host_actions'; import { addEditHostAction } from '../actions/host_actions';
export const hostReducer = createReducer( export const hostReducer = createReducer(
{ {
DisplayAddEditHost: false, DisplayAddEditHost: false,
Edit: false,
HostData: {}, HostData: {},
HostList: [], HostList: [],
}, },
{ {
[Actions.DISPLAY_ADD_EDIT_HOST]: (state, action) => { [addEditHostAction.action_type]: (state, action) => {
return { return {
...state, ...state,
DisplayAddEditHost: action.payload.display, DisplayAddEditHost: action.payload.display,
Edit: !!action.payload.host_data, HostData: action.payload.data ? action.payload.data.host_data || {} : {},
HostData: action.payload.host_data || {}, HostList: action.payload.data ? action.payload.data.host_list || [] : [],
HostList: action.payload.host_list || [],
}; };
}, },
} }

47
src/redux/utils.js Normal file
View File

@@ -0,0 +1,47 @@
export const createResponseDialogAction = (type, name) => {
let resolverList = [];
const display = (show, cb, data) => {
return (dispatch) => {
if (cb) {
dispatch(display(show, null, data)).then(({ changed, data }) => cb(changed, data));
} else {
return new Promise((resolve) => {
dispatch(handleDisplay(show, data, resolve));
});
}
};
};
const handleDisplay = (show, data, resolve) => {
return (dispatch) => {
if (show) {
resolverList.push(resolve);
dispatch(displayAction(show, data));
} else {
dispatch(complete(false));
}
};
};
const complete = (changed, data) => {
return (dispatch) => {
if (changed) {
resolverList[0]({ changed, data });
}
resolverList.splice(0, 1);
dispatch(displayAction(false));
};
};
const DISPLAY_ACTION = type + '/' + name;
const displayAction = (display, data) => {
return { type: DISPLAY_ACTION, payload: { display, data } };
};
return {
action_type: DISPLAY_ACTION,
complete,
display,
};
};