From 0a26ee422403d78a1e1ef56270deb11b6e646156 Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Tue, 17 Sep 2019 12:22:15 +0300 Subject: [PATCH] - client: fix upstream DNS servers form Closes #1000 --- client/src/actions/index.js | 19 +- .../components/Settings/Dns/Access/Form.js | 20 +- .../components/Settings/Dns/Access/index.js | 7 +- .../components/Settings/Dns/Upstream/Form.js | 10 +- client/src/components/Settings/Dns/index.js | 11 +- client/src/components/Settings/Settings.css | 5 + client/src/containers/Dns.js | 3 +- client/src/reducers/index.js | 581 +++++++++--------- 8 files changed, 360 insertions(+), 296 deletions(-) diff --git a/client/src/actions/index.js b/client/src/actions/index.js index 88e14ef9..351b8221 100644 --- a/client/src/actions/index.js +++ b/client/src/actions/index.js @@ -227,7 +227,22 @@ export const getDnsStatus = () => async (dispatch) => { dispatch(getTlsStatus()); } catch (error) { dispatch(addErrorToast({ error })); - dispatch(initSettingsFailure()); + dispatch(dnsStatusFailure()); + } +}; + +export const getDnsSettingsRequest = createAction('GET_DNS_SETTINGS_REQUEST'); +export const getDnsSettingsFailure = createAction('GET_DNS_SETTINGS_FAILURE'); +export const getDnsSettingsSuccess = createAction('GET_DNS_SETTINGS_SUCCESS'); + +export const getDnsSettings = () => async (dispatch) => { + dispatch(getDnsSettingsRequest()); + try { + const dnsStatus = await apiClient.getGlobalStatus(); + dispatch(getDnsSettingsSuccess(dnsStatus)); + } catch (error) { + dispatch(addErrorToast({ error })); + dispatch(getDnsSettingsFailure()); } }; @@ -279,7 +294,7 @@ export const setUpstream = config => async (dispatch) => { await apiClient.setUpstream(values); dispatch(addSuccessToast('updated_upstream_dns_toast')); - dispatch(setUpstreamSuccess()); + dispatch(setUpstreamSuccess(config)); } catch (error) { dispatch(addErrorToast({ error })); dispatch(setUpstreamFailure()); diff --git a/client/src/components/Settings/Dns/Access/Form.js b/client/src/components/Settings/Dns/Access/Form.js index 9096102d..29c9bc8b 100644 --- a/client/src/components/Settings/Dns/Access/Form.js +++ b/client/src/components/Settings/Dns/Access/Form.js @@ -5,7 +5,9 @@ import { Trans, withNamespaces } from 'react-i18next'; import flow from 'lodash/flow'; const Form = (props) => { - const { handleSubmit, submitting, invalid } = props; + const { + handleSubmit, submitting, invalid, processingSet, + } = props; return (
@@ -22,6 +24,7 @@ const Form = (props) => { component="textarea" type="text" className="form-control form-control--textarea" + disabled={processingSet} />
@@ -37,6 +40,7 @@ const Form = (props) => { component="textarea" type="text" className="form-control form-control--textarea" + disabled={processingSet} />
@@ -52,6 +56,7 @@ const Form = (props) => { component="textarea" type="text" className="form-control form-control--textarea" + disabled={processingSet} />
@@ -59,7 +64,7 @@ const Form = (props) => { @@ -70,11 +75,12 @@ const Form = (props) => { }; Form.propTypes = { - handleSubmit: PropTypes.func, - submitting: PropTypes.bool, - invalid: PropTypes.bool, - initialValues: PropTypes.object, - t: PropTypes.func, + handleSubmit: PropTypes.func.isRequired, + submitting: PropTypes.bool.isRequired, + invalid: PropTypes.bool.isRequired, + initialValues: PropTypes.object.isRequired, + processingSet: PropTypes.bool.isRequired, + t: PropTypes.func.isRequired, }; export default flow([withNamespaces(), reduxForm({ form: 'accessForm' })])(Form); diff --git a/client/src/components/Settings/Dns/Access/index.js b/client/src/components/Settings/Dns/Access/index.js index 93d28bf7..ed11e960 100644 --- a/client/src/components/Settings/Dns/Access/index.js +++ b/client/src/components/Settings/Dns/Access/index.js @@ -13,11 +13,7 @@ class Access extends Component { render() { const { t, access } = this.props; - const { - processing, - processingSet, - ...values - } = access; + const { processing, processingSet, ...values } = access; return ( ); diff --git a/client/src/components/Settings/Dns/Upstream/Form.js b/client/src/components/Settings/Dns/Upstream/Form.js index d055f274..e6164818 100644 --- a/client/src/components/Settings/Dns/Upstream/Form.js +++ b/client/src/components/Settings/Dns/Upstream/Form.js @@ -43,6 +43,7 @@ let Form = (props) => { type="text" className="form-control form-control--textarea" placeholder={t('upstream_dns')} + disabled={processingSetUpstream || processingTestUpstream} />
@@ -53,6 +54,7 @@ let Form = (props) => { type="checkbox" component={renderSelectField} placeholder={t('upstream_parallel')} + disabled={processingSetUpstream} /> @@ -62,7 +64,10 @@ let Form = (props) => {
-
diff --git a/client/src/components/Settings/Dns/index.js b/client/src/components/Settings/Dns/index.js index cb9c9e4a..f64b3f3c 100644 --- a/client/src/components/Settings/Dns/index.js +++ b/client/src/components/Settings/Dns/index.js @@ -10,6 +10,7 @@ import Loading from '../../ui/Loading'; class Dns extends Component { componentDidMount() { + this.props.getDnsSettings(); this.props.getAccessList(); this.props.getRewritesList(); } @@ -30,11 +31,16 @@ class Dns extends Component { toggleRewritesModal, } = this.props; + const isDataLoading = + dashboard.processingDnsSettings || access.processing || rewrites.processing; + const isDataReady = + !dashboard.processingDnsSettings && !access.processing && !rewrites.processing; + return ( - {(dashboard.processing || access.processing) && } - {!dashboard.processing && !access.processing && ( + {isDataLoading && } + {isDataReady && ( ({ ...state, processing: true }), - [actions.initSettingsFailure]: state => ({ ...state, processing: false }), - [actions.initSettingsSuccess]: (state, { payload }) => { - const { settingsList } = payload; - const newState = { ...state, settingsList, processing: false }; - return newState; - }, - [actions.toggleSettingStatus]: (state, { payload }) => { - const { settingsList } = state; - const { settingKey } = payload; +const settings = handleActions( + { + [actions.initSettingsRequest]: state => ({ ...state, processing: true }), + [actions.initSettingsFailure]: state => ({ ...state, processing: false }), + [actions.initSettingsSuccess]: (state, { payload }) => { + const { settingsList } = payload; + const newState = { ...state, settingsList, processing: false }; + return newState; + }, + [actions.toggleSettingStatus]: (state, { payload }) => { + const { settingsList } = state; + const { settingKey } = payload; - const setting = settingsList[settingKey]; + const setting = settingsList[settingKey]; - const newSetting = { ...setting, enabled: !setting.enabled }; - const newSettingsList = { ...settingsList, [settingKey]: newSetting }; - return { ...state, settingsList: newSettingsList }; - }, - [actions.setUpstreamRequest]: state => ({ ...state, processingUpstream: true }), - [actions.setUpstreamFailure]: state => ({ ...state, processingUpstream: false }), - [actions.setUpstreamSuccess]: state => ({ ...state, processingUpstream: false }), - - [actions.testUpstreamRequest]: state => ({ ...state, processingTestUpstream: true }), - [actions.testUpstreamFailure]: state => ({ ...state, processingTestUpstream: false }), - [actions.testUpstreamSuccess]: state => ({ ...state, processingTestUpstream: false }), -}, { - processing: true, - processingTestUpstream: false, - processingSetUpstream: false, - processingDhcpStatus: false, - settingsList: {}, -}); - -const dashboard = handleActions({ - [actions.dnsStatusRequest]: state => ({ ...state, processing: true }), - [actions.dnsStatusFailure]: state => ({ ...state, processing: false }), - [actions.dnsStatusSuccess]: (state, { payload }) => { - const { - version, - running, - dns_port: dnsPort, - dns_addresses: dnsAddresses, - upstream_dns: upstreamDns, - bootstrap_dns: bootstrapDns, - all_servers: allServers, - protection_enabled: protectionEnabled, - language, - http_port: httpPort, - } = payload; - const newState = { + const newSetting = { ...setting, enabled: !setting.enabled }; + const newSettingsList = { ...settingsList, [settingKey]: newSetting }; + return { ...state, settingsList: newSettingsList }; + }, + [actions.setUpstreamRequest]: state => ({ ...state, processingSetUpstream: true }), + [actions.setUpstreamFailure]: state => ({ ...state, processingSetUpstream: false }), + [actions.setUpstreamSuccess]: (state, { payload }) => ({ ...state, - isCoreRunning: running, - processing: false, - dnsVersion: version, - dnsPort, - dnsAddresses, - upstreamDns: upstreamDns.join('\n'), - bootstrapDns: bootstrapDns.join('\n'), - allServers, - protectionEnabled, - language, - httpPort, - }; - return newState; + ...payload, + processingSetUpstream: false, + }), + + [actions.testUpstreamRequest]: state => ({ ...state, processingTestUpstream: true }), + [actions.testUpstreamFailure]: state => ({ ...state, processingTestUpstream: false }), + [actions.testUpstreamSuccess]: state => ({ ...state, processingTestUpstream: false }), }, - - [actions.enableDnsRequest]: state => ({ ...state, processing: true }), - [actions.enableDnsFailure]: state => ({ ...state, processing: false }), - [actions.enableDnsSuccess]: (state) => { - const newState = { ...state, isCoreRunning: !state.isCoreRunning, processing: false }; - return newState; + { + processing: true, + processingTestUpstream: false, + processingSetUpstream: false, + processingDhcpStatus: false, + settingsList: {}, }, +); - [actions.disableDnsRequest]: state => ({ ...state, processing: true }), - [actions.disableDnsFailure]: state => ({ ...state, processing: false }), - [actions.disableDnsSuccess]: (state) => { - const newState = { ...state, isCoreRunning: !state.isCoreRunning, processing: false }; - return newState; - }, - - [actions.getVersionRequest]: state => ({ ...state, processingVersion: true }), - [actions.getVersionFailure]: state => ({ ...state, processingVersion: false }), - [actions.getVersionSuccess]: (state, { payload }) => { - const currentVersion = state.dnsVersion === 'undefined' ? 0 : state.dnsVersion; - - if (payload && versionCompare(currentVersion, payload.new_version) === -1) { +const dashboard = handleActions( + { + [actions.dnsStatusRequest]: state => ({ ...state, processing: true }), + [actions.dnsStatusFailure]: state => ({ ...state, processing: false }), + [actions.dnsStatusSuccess]: (state, { payload }) => { const { - announcement_url: announcementUrl, - new_version: newVersion, - can_autoupdate: canAutoUpdate, + version, + running, + dns_port: dnsPort, + dns_addresses: dnsAddresses, + upstream_dns: upstreamDns, + bootstrap_dns: bootstrapDns, + all_servers: allServers, + protection_enabled: protectionEnabled, + language, + http_port: httpPort, } = payload; + const newState = { + ...state, + isCoreRunning: running, + processing: false, + dnsVersion: version, + dnsPort, + dnsAddresses, + upstreamDns: upstreamDns.join('\n'), + bootstrapDns: bootstrapDns.join('\n'), + allServers, + protectionEnabled, + language, + httpPort, + }; + return newState; + }, + + [actions.enableDnsRequest]: state => ({ ...state, processing: true }), + [actions.enableDnsFailure]: state => ({ ...state, processing: false }), + [actions.enableDnsSuccess]: (state) => { + const newState = { ...state, isCoreRunning: !state.isCoreRunning, processing: false }; + return newState; + }, + + [actions.disableDnsRequest]: state => ({ ...state, processing: true }), + [actions.disableDnsFailure]: state => ({ ...state, processing: false }), + [actions.disableDnsSuccess]: (state) => { + const newState = { ...state, isCoreRunning: !state.isCoreRunning, processing: false }; + return newState; + }, + + [actions.getVersionRequest]: state => ({ ...state, processingVersion: true }), + [actions.getVersionFailure]: state => ({ ...state, processingVersion: false }), + [actions.getVersionSuccess]: (state, { payload }) => { + const currentVersion = state.dnsVersion === 'undefined' ? 0 : state.dnsVersion; + + if (payload && versionCompare(currentVersion, payload.new_version) === -1) { + const { + announcement_url: announcementUrl, + new_version: newVersion, + can_autoupdate: canAutoUpdate, + } = payload; + + const newState = { + ...state, + announcementUrl, + newVersion, + canAutoUpdate, + isUpdateAvailable: true, + processingVersion: false, + }; + return newState; + } + + return { + ...state, + processingVersion: false, + }; + }, + + [actions.getUpdateRequest]: state => ({ ...state, processingUpdate: true }), + [actions.getUpdateFailure]: state => ({ ...state, processingUpdate: false }), + [actions.getUpdateSuccess]: (state) => { + const newState = { ...state, processingUpdate: false }; + return newState; + }, + + [actions.toggleProtectionRequest]: state => ({ ...state, processingProtection: true }), + [actions.toggleProtectionFailure]: state => ({ ...state, processingProtection: false }), + [actions.toggleProtectionSuccess]: (state) => { + const newState = { + ...state, + protectionEnabled: !state.protectionEnabled, + processingProtection: false, + }; + return newState; + }, + + [actions.handleUpstreamChange]: (state, { payload }) => { + const { upstreamDns } = payload; + return { ...state, upstreamDns }; + }, + + [actions.getLanguageSuccess]: (state, { payload }) => { + const newState = { ...state, language: payload }; + return newState; + }, + + [actions.getClientsRequest]: state => ({ ...state, processingClients: true }), + [actions.getClientsFailure]: state => ({ ...state, processingClients: false }), + [actions.getClientsSuccess]: (state, { payload }) => { + const newState = { + ...state, + clients: payload.clients, + autoClients: payload.autoClients, + processingClients: false, + }; + return newState; + }, + + [actions.getDnsSettingsRequest]: state => ({ ...state, processingDnsSettings: true }), + [actions.getDnsSettingsFailure]: state => ({ ...state, processingDnsSettings: false }), + [actions.getDnsSettingsSuccess]: (state, { payload }) => { + const { + upstream_dns: upstreamDns, + bootstrap_dns: bootstrapDns, + all_servers: allServers, + } = payload; + + return { + ...state, + allServers, + upstreamDns: (upstreamDns && upstreamDns.join('\n')) || '', + bootstrapDns: (bootstrapDns && bootstrapDns.join('\n')) || '', + processingDnsSettings: false, + }; + }, + }, + { + processing: true, + isCoreRunning: false, + processingVersion: true, + processingFiltering: true, + processingClients: true, + processingUpdate: false, + processingDnsSettings: true, + upstreamDns: '', + bootstrapDns: '', + allServers: false, + protectionEnabled: false, + processingProtection: false, + httpPort: 80, + dnsPort: 53, + dnsAddresses: [], + dnsVersion: '', + clients: [], + autoClients: [], + }, +); + +const dhcp = handleActions( + { + [actions.getDhcpStatusRequest]: state => ({ ...state, processing: true }), + [actions.getDhcpStatusFailure]: state => ({ ...state, processing: false }), + [actions.getDhcpStatusSuccess]: (state, { payload }) => { + const { static_leases: staticLeases, ...values } = payload; const newState = { ...state, - announcementUrl, - newVersion, - canAutoUpdate, - isUpdateAvailable: true, - processingVersion: false, + staticLeases, + processing: false, + ...values, + }; + + return newState; + }, + + [actions.getDhcpInterfacesRequest]: state => ({ ...state, processingInterfaces: true }), + [actions.getDhcpInterfacesFailure]: state => ({ ...state, processingInterfaces: false }), + [actions.getDhcpInterfacesSuccess]: (state, { payload }) => { + const newState = { + ...state, + interfaces: payload, + processingInterfaces: false, }; return newState; - } + }, - return { - ...state, - processingVersion: false, - }; + [actions.findActiveDhcpRequest]: state => ({ ...state, processingStatus: true }), + [actions.findActiveDhcpFailure]: state => ({ ...state, processingStatus: false }), + [actions.findActiveDhcpSuccess]: (state, { payload }) => { + const { other_server: otherServer, static_ip: staticIP } = payload; + + const newState = { + ...state, + check: { + otherServer, + staticIP, + }, + processingStatus: false, + }; + return newState; + }, + + [actions.toggleDhcpRequest]: state => ({ ...state, processingDhcp: true }), + [actions.toggleDhcpFailure]: state => ({ ...state, processingDhcp: false }), + [actions.toggleDhcpSuccess]: (state) => { + const { config } = state; + const newConfig = { ...config, enabled: !config.enabled }; + const newState = { + ...state, + config: newConfig, + check: null, + processingDhcp: false, + }; + return newState; + }, + + [actions.setDhcpConfigRequest]: state => ({ ...state, processingConfig: true }), + [actions.setDhcpConfigFailure]: state => ({ ...state, processingConfig: false }), + [actions.setDhcpConfigSuccess]: (state, { payload }) => { + const { config } = state; + const newConfig = { ...config, ...payload }; + const newState = { ...state, config: newConfig, processingConfig: false }; + return newState; + }, + + [actions.toggleLeaseModal]: (state) => { + const newState = { + ...state, + isModalOpen: !state.isModalOpen, + }; + return newState; + }, + + [actions.addStaticLeaseRequest]: state => ({ ...state, processingAdding: true }), + [actions.addStaticLeaseFailure]: state => ({ ...state, processingAdding: false }), + [actions.addStaticLeaseSuccess]: (state, { payload }) => { + const { ip, mac, hostname } = payload; + const newLease = { + ip, + mac, + hostname: hostname || '', + }; + const leases = [...state.staticLeases, newLease]; + const newState = { + ...state, + staticLeases: leases, + processingAdding: false, + }; + return newState; + }, + + [actions.removeStaticLeaseRequest]: state => ({ ...state, processingDeleting: true }), + [actions.removeStaticLeaseFailure]: state => ({ ...state, processingDeleting: false }), + [actions.removeStaticLeaseSuccess]: (state, { payload }) => { + const leaseToRemove = payload.ip; + const leases = state.staticLeases.filter(item => item.ip !== leaseToRemove); + const newState = { + ...state, + staticLeases: leases, + processingDeleting: false, + }; + return newState; + }, }, - - [actions.getUpdateRequest]: state => ({ ...state, processingUpdate: true }), - [actions.getUpdateFailure]: state => ({ ...state, processingUpdate: false }), - [actions.getUpdateSuccess]: (state) => { - const newState = { ...state, processingUpdate: false }; - return newState; + { + processing: true, + processingStatus: false, + processingInterfaces: false, + processingDhcp: false, + processingConfig: false, + processingAdding: false, + processingDeleting: false, + config: { + enabled: false, + }, + check: null, + leases: [], + staticLeases: [], + isModalOpen: false, }, - - [actions.toggleProtectionRequest]: state => ({ ...state, processingProtection: true }), - [actions.toggleProtectionFailure]: state => ({ ...state, processingProtection: false }), - [actions.toggleProtectionSuccess]: (state) => { - const newState = { - ...state, - protectionEnabled: !state.protectionEnabled, - processingProtection: false, - }; - return newState; - }, - - [actions.handleUpstreamChange]: (state, { payload }) => { - const { upstreamDns } = payload; - return { ...state, upstreamDns }; - }, - - [actions.getLanguageSuccess]: (state, { payload }) => { - const newState = { ...state, language: payload }; - return newState; - }, - - [actions.getClientsRequest]: state => ({ ...state, processingClients: true }), - [actions.getClientsFailure]: state => ({ ...state, processingClients: false }), - [actions.getClientsSuccess]: (state, { payload }) => { - const newState = { - ...state, - clients: payload.clients, - autoClients: payload.autoClients, - processingClients: false, - }; - return newState; - }, -}, { - processing: true, - isCoreRunning: false, - processingVersion: true, - processingFiltering: true, - processingClients: true, - processingUpdate: false, - upstreamDns: '', - bootstrapDns: '', - allServers: false, - protectionEnabled: false, - processingProtection: false, - httpPort: 80, - dnsPort: 53, - dnsAddresses: [], - dnsVersion: '', - clients: [], - autoClients: [], -}); - -const dhcp = handleActions({ - [actions.getDhcpStatusRequest]: state => ({ ...state, processing: true }), - [actions.getDhcpStatusFailure]: state => ({ ...state, processing: false }), - [actions.getDhcpStatusSuccess]: (state, { payload }) => { - const { - static_leases: staticLeases, - ...values - } = payload; - - const newState = { - ...state, - staticLeases, - processing: false, - ...values, - }; - - return newState; - }, - - [actions.getDhcpInterfacesRequest]: state => ({ ...state, processingInterfaces: true }), - [actions.getDhcpInterfacesFailure]: state => ({ ...state, processingInterfaces: false }), - [actions.getDhcpInterfacesSuccess]: (state, { payload }) => { - const newState = { - ...state, - interfaces: payload, - processingInterfaces: false, - }; - return newState; - }, - - [actions.findActiveDhcpRequest]: state => ({ ...state, processingStatus: true }), - [actions.findActiveDhcpFailure]: state => ({ ...state, processingStatus: false }), - [actions.findActiveDhcpSuccess]: (state, { payload }) => { - const { - other_server: otherServer, - static_ip: staticIP, - } = payload; - - const newState = { - ...state, - check: { - otherServer, - staticIP, - }, - processingStatus: false, - }; - return newState; - }, - - [actions.toggleDhcpRequest]: state => ({ ...state, processingDhcp: true }), - [actions.toggleDhcpFailure]: state => ({ ...state, processingDhcp: false }), - [actions.toggleDhcpSuccess]: (state) => { - const { config } = state; - const newConfig = { ...config, enabled: !config.enabled }; - const newState = { - ...state, config: newConfig, check: null, processingDhcp: false, - }; - return newState; - }, - - [actions.setDhcpConfigRequest]: state => ({ ...state, processingConfig: true }), - [actions.setDhcpConfigFailure]: state => ({ ...state, processingConfig: false }), - [actions.setDhcpConfigSuccess]: (state, { payload }) => { - const { config } = state; - const newConfig = { ...config, ...payload }; - const newState = { ...state, config: newConfig, processingConfig: false }; - return newState; - }, - - [actions.toggleLeaseModal]: (state) => { - const newState = { - ...state, - isModalOpen: !state.isModalOpen, - }; - return newState; - }, - - [actions.addStaticLeaseRequest]: state => ({ ...state, processingAdding: true }), - [actions.addStaticLeaseFailure]: state => ({ ...state, processingAdding: false }), - [actions.addStaticLeaseSuccess]: (state, { payload }) => { - const { - ip, mac, hostname, - } = payload; - const newLease = { - ip, - mac, - hostname: hostname || '', - }; - const leases = [...state.staticLeases, newLease]; - const newState = { - ...state, - staticLeases: leases, - processingAdding: false, - }; - return newState; - }, - - [actions.removeStaticLeaseRequest]: state => ({ ...state, processingDeleting: true }), - [actions.removeStaticLeaseFailure]: state => ({ ...state, processingDeleting: false }), - [actions.removeStaticLeaseSuccess]: (state, { payload }) => { - const leaseToRemove = payload.ip; - const leases = state.staticLeases.filter(item => item.ip !== leaseToRemove); - const newState = { - ...state, - staticLeases: leases, - processingDeleting: false, - }; - return newState; - }, -}, { - processing: true, - processingStatus: false, - processingInterfaces: false, - processingDhcp: false, - processingConfig: false, - processingAdding: false, - processingDeleting: false, - config: { - enabled: false, - }, - check: null, - leases: [], - staticLeases: [], - isModalOpen: false, -}); +); export default combineReducers({ settings,