From a4c3dbdb946dfe8d4be8e9cdf901cb7a5a2a7bd0 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sat, 1 May 2021 00:41:25 -0500 Subject: [PATCH] Initial Skynet premium portal suppport --- .eslintrc.json | 9 +- .vimrc | 2 +- package.json | 4 + src/App.jsx | 16 ++ .../ApplicationBusy/ApplicationBusy.js | 5 + .../DependencyList/DependencyList.js | 30 +-- src/containers/AddEditHost/AddEditHost.js | 232 ++++++++++++++++++ src/containers/AddMount/AddMount.js | 4 +- src/containers/Configuration/Configuration.js | 59 +++-- .../ConfigurationItem/ConfigurationItem.js | 20 ++ src/containers/HostList/Host/Host.css | 0 src/containers/HostList/Host/Host.js | 69 ++++++ src/containers/HostList/HostList.css | 0 src/containers/HostList/HostList.js | 122 +++++++++ src/containers/PinnedManager/PinnedManager.js | 14 +- src/redux/actions/common_actions.js | 14 +- src/redux/actions/download_actions.js | 8 +- src/redux/actions/host_actions.js | 41 ++++ src/redux/actions/release_version_actions.js | 2 +- src/redux/reducers/host_reducer.js | 20 ++ src/redux/store/createAppStore.js | 2 + src/utils.jsx | 24 ++ 22 files changed, 631 insertions(+), 66 deletions(-) create mode 100644 src/containers/AddEditHost/AddEditHost.js create mode 100644 src/containers/HostList/Host/Host.css create mode 100644 src/containers/HostList/Host/Host.js create mode 100644 src/containers/HostList/HostList.css create mode 100644 src/containers/HostList/HostList.js create mode 100644 src/redux/actions/host_actions.js create mode 100644 src/redux/reducers/host_reducer.js diff --git a/.eslintrc.json b/.eslintrc.json index 4e02ad7..1f9f7c0 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,8 +7,10 @@ }, "extends": [ "eslint:recommended", - "plugin:react/recommended" + "plugin:react/recommended", + "plugin:prettier/recommended" ], + "parser": "babel-eslint", "parserOptions": { "ecmaFeatures": { "jsx": true @@ -17,9 +19,14 @@ "sourceType": "module" }, "plugins": [ + "prettier", "react", "jest" ], "rules": { + "prettier/prettier": "warn", + "react/prop-types": "warn", + "no-prototype-builtins": "warn", + "react/no-string-refs": "warn" } } diff --git a/.vimrc b/.vimrc index cbde2c6..b8dd2cb 100644 --- a/.vimrc +++ b/.vimrc @@ -1,6 +1,6 @@ set autoread set path+=.,public/**,src/**,test/** -if has('win32') +if has('win32') || has('win64') let &makeprg="create_dist.cmd" else let &makeprg="./create_dist.sh" diff --git a/package.json b/package.json index 824a517..ff4d9dc 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "focus-trap-react": "^8.4.2", "font-awesome": "^4.7.0", "node-cron": "1.2.1", + "prop-types": "^15.7.2", "randomstring": "^1.1.5", "react": "16.14.0", "react-checkbox-tree": "^1.6.0", @@ -37,8 +38,11 @@ "electron-builder": "22.9.1", "electron-webpack": "^2.8.2", "eslint": "^7.22.0", + "eslint-config-prettier": "^8.3.0", "eslint-plugin-jest": "^24.3.2", + "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-react": "^7.23.0", + "prettier": "2.2.1", "webpack": "4.44.2", "webpack-dev-server": "3.11.1" }, diff --git a/src/App.jsx b/src/App.jsx index 4b862bd..5c2b9c3 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,6 @@ import React from 'react'; import './App.css'; +import AddEditHost from './containers/AddEditHost/AddEditHost'; import Box from './components/UI/Box/Box'; import Configuration from './containers/Configuration/Configuration'; import { connect } from 'react-redux'; @@ -176,6 +177,15 @@ class App extends IPCContainer { !this.props.DismissNewReleasesAvailable && this.props.NewReleasesAvailable.length > 0; + const showAddEditHost = + !showDependencies && + !this.props.DownloadActive && + !showNewReleases && + !this.props.RebootRequired && + !this.props.DisplaySelectAppPlatform && + !showUpgrade && + this.props.DisplayAddEditHost; + const showSkynetImport = !showConfig && !showDependencies && @@ -204,6 +214,10 @@ class App extends IPCContainer { remoteSupported={remoteSupported} /> ); + const addEditHostDisplay = createModalConditionally( + showAddEditHost, + + ); const pinnedManagerDisplay = createModalConditionally( showPinnedManager, @@ -358,6 +372,7 @@ class App extends IPCContainer { {upgradeDisplay} {pinnedManagerDisplay} {configDisplay} + {addEditHostDisplay} {infoDisplay} {confirmDisplay} {downloadDisplay} @@ -378,6 +393,7 @@ const mapStateToProps = (state) => { AppBusyTransparent: state.common.AppBusyTransparent, AppReady: state.common.AppReady, DismissDependencies: state.install.DismissDependencies, + DisplayAddEditHost: state.host.DisplayAddEditHost, DisplayConfiguration: state.mounts.DisplayConfiguration, DisplayConfirmYesNo: state.common.DisplayConfirmYesNo, DisplayError: state.error.DisplayError, diff --git a/src/components/ApplicationBusy/ApplicationBusy.js b/src/components/ApplicationBusy/ApplicationBusy.js index 709cc02..0e2b83b 100644 --- a/src/components/ApplicationBusy/ApplicationBusy.js +++ b/src/components/ApplicationBusy/ApplicationBusy.js @@ -2,6 +2,7 @@ import React from 'react'; import Box from '../UI/Box/Box'; import Loader from 'react-loader-spinner'; import Text from '../UI/Text/Text'; +import PropTypes from 'prop-types'; const ApplicationBusy = ({ title }) => { return ( @@ -27,4 +28,8 @@ const ApplicationBusy = ({ title }) => { ); }; +ApplicationBusy.propTypes = { + title: PropTypes.string, +}; + export default ApplicationBusy; diff --git a/src/components/DependencyList/DependencyList.js b/src/components/DependencyList/DependencyList.js index b3fbfd5..33eb089 100644 --- a/src/components/DependencyList/DependencyList.js +++ b/src/components/DependencyList/DependencyList.js @@ -2,6 +2,7 @@ import React from 'react'; import './DependencyList.css'; import { connect } from 'react-redux'; import * as Constants from '../../constants'; +import { createDismissDisplay } from '../../utils.jsx'; import Dependency from './Dependency/Dependency'; import Box from '../UI/Box/Box'; import { downloadItem } from '../../redux/actions/download_actions'; @@ -45,33 +46,12 @@ export default connect( ); }); - const dismissDisplay = ( -
- props.setDismissDependencies(true) - : (e) => e.preventDefault() - } - style={{ - cursor: props.AllowDismissDependencies ? 'pointer' : 'no-drop', - }}> - X - -
- ); - return ( - {dismissDisplay} + {createDismissDisplay( + () => props.setDismissDependencies(true), + !props.AllowDismissDependencies + )}
{ + this.props.completeAddEditHost(this.state); + }; + + render() { + return ( + + {createDismissDisplay(this.props.Close)} +
+

+ Portal Settings +

+
+ +
+
+ + this.setState({ HostNameOrIp: e.target.value.trim() }) + } + className={'ConfigurationItemInput'} + style={{ width: '100%' }} + type={'text'} + value={this.state.HostNameOrIp} + /> +
+
+
+ +
+ +
+ +
+
+ this.setState({ Protocol: e.target.value })} + items={['https', 'http']} + selected={this.state.Protocol} + /> +
+
+ this.setState({ ApiPort: e.target.value })} + className={'ConfigurationItemInput'} + style={{ width: '100%' }} + type={'number'} + min={1} + max={65535} + value={this.state.ApiPort} + /> +
+
+ this.setState({ TimeoutMs: e.target.value })} + className={'ConfigurationItemInput'} + style={{ width: '100%' }} + type={'number'} + min={1000} + step={1000} + value={this.state.TimeoutMs} + /> +
+
+
+ +
+ +
+
+ this.setState({ AgentString: e.target.value })} + className={'ConfigurationItemInput'} + style={{ flex: '1' }} + type={'text'} + value={this.state.AgentString} + /> +
+ this.setState({ ApiPassword: e.target.value })} + className={'ConfigurationItemInput'} + style={{ flex: '1' }} + type={'text'} + value={this.state.ApiPassword} + /> +
+
+
+ +
+
+ this.setState({ AuthURL: e.target.value })} + className={'ConfigurationItemInput'} + type={'text'} + value={this.state.AuthURL} + /> +
+
+
+ +
+ +
+
+ this.setState({ AuthUser: e.target.value })} + className={'ConfigurationItemInput'} + style={{ flex: '1' }} + type={'text'} + value={this.state.AuthUser} + /> +
+ this.setState({ AuthPassword: e.target.value })} + className={'ConfigurationItemInput'} + style={{ flex: '1' }} + type={'text'} + value={this.state.AuthPassword} + /> +
+
+

+ + {'Portal URL: ' + + this.state.Protocol + + '://' + + this.state.HostNameOrIp + + ((this.state.Protocol === 'http' && this.state.ApiPort != 80) || + (this.state.Protocol === 'https' && this.state.ApiPort != 443) + ? ':' + this.state.ApiPort.toString() + : '')} + +

+
+
+ + + ); + } +} + +const mapStateToProps = (state) => { + return { + HostData: state.host.HostData, + }; +}; + +const mapDispatchToProps = (dispatch) => { + return { + Close: () => dispatch(addEditHost(false)), + completeAddEditHost: (host_data) => + dispatch(completeAddEditHost(true, host_data)), + }; +}; + +AddEditHost.propTypes = { + Close: PropTypes.func.isRequired, + completeAddEditHost: PropTypes.func.isRequired, + HostData: PropTypes.object, +}; + +export default connect(mapStateToProps, mapDispatchToProps)(AddEditHost); diff --git a/src/containers/AddMount/AddMount.js b/src/containers/AddMount/AddMount.js index 68a2371..8dd3596 100644 --- a/src/containers/AddMount/AddMount.js +++ b/src/containers/AddMount/AddMount.js @@ -36,7 +36,7 @@ const default_state = { DisplayS3: false, HostNameOrIp: '', Name: '', - Port: 20000, + Port: 2000, Provider: Constants.S3_PROVIDER_LIST[0], Region: Constants.S3_REGION_PROVIDER_REGION[0], SecretKey: '', @@ -47,7 +47,7 @@ export default connect( mapStateToProps, mapDispatchToProps )( - class extends Component { + class AddMount extends Component { state = { ...default_state, }; diff --git a/src/containers/Configuration/Configuration.js b/src/containers/Configuration/Configuration.js index 5cbbd1d..17163fa 100644 --- a/src/containers/Configuration/Configuration.js +++ b/src/containers/Configuration/Configuration.js @@ -1,6 +1,7 @@ import React from 'react'; import './Configuration.css'; import { connect } from 'react-redux'; +import { createDismissDisplay } from '../../utils.jsx'; import Box from '../../components/UI/Box/Box'; import Button from '../../components/UI/Button/Button'; import ConfigurationItem from './ConfigurationItem/ConfigurationItem'; @@ -35,6 +36,27 @@ class Configuration extends IPCContainer { } return itemA.value.filter((i) => !itemB.value.includes(i)).length !== 0; } + if (itemA.type === 'host_list') { + if (itemA.value.length !== itemB.value.length) { + return true; + } + return ( + itemA.value.filter((i) => + itemB.value.find( + (j) => + j.HostNameOrIp === i.HostNameOrIp && + j.ApiPort === i.ApiPort && + j.Protocol === i.Protocol && + j.TimeoutMs === i.TimeoutMs && + j.AgentString === i.AgentString && + j.ApiPassword === i.ApiPassword && + j.AuthURL === i.AuthURL && + j.AuthUser === i.AuthUser && + j.AuthPassword === i.AuthPassword + ) + ).length === 0 + ); + } return itemA.value !== itemB.value; }; @@ -115,9 +137,11 @@ class Configuration extends IPCContainer { remote: template[key] ? template[key].remote : false, type: template[key] ? template[key].type : null, value: - template[key] && template[key].type === 'object' + template[key] && + (template[key].type === 'string_array' || + template[key].type === 'object') ? config[key] - : template[key] && template[key].type === 'string_array' + : template[key] && template[key].type === 'host_list' ? config[key] : config[key].toString(), }; @@ -141,6 +165,8 @@ class Configuration extends IPCContainer { itemList[idx].value = target.type === 'textarea' ? target.string_array + : target.type === 'host_list' + ? target.value : target.value.toString(); this.setState({ ItemList: itemList, @@ -156,6 +182,8 @@ class Configuration extends IPCContainer { itemList[idx].value = target.type === 'textarea' ? target.string_array + : target.type === 'host_list' + ? target.value : target.value.toString(); objectLookup[name] = itemList; this.setState({ @@ -246,7 +274,11 @@ class Configuration extends IPCContainer { changedItems.push({ Name: item.label, Value: - item.type === 'string_array' ? item.value.join(';') : item.value, + item.type === 'string_array' + ? item.value.join(';') + : item.type === 'host_list' + ? JSON.stringify(item.value) + : item.value, }); } @@ -258,6 +290,8 @@ class Configuration extends IPCContainer { Value: item.type === 'string_array' ? item.value.join(';') + : item.type === 'host_list' + ? JSON.stringify(item.value) : item.value, }); } @@ -402,23 +436,8 @@ class Configuration extends IPCContainer { return (
{confirmSave} - - + + {createDismissDisplay(this.checkSaveRequired)}

{(this.props.DisplayRemoteConfiguration ? this.props.DisplayConfiguration.substr(6) diff --git a/src/containers/Configuration/ConfigurationItem/ConfigurationItem.js b/src/containers/Configuration/ConfigurationItem/ConfigurationItem.js index b59b359..56c20d5 100644 --- a/src/containers/Configuration/ConfigurationItem/ConfigurationItem.js +++ b/src/containers/Configuration/ConfigurationItem/ConfigurationItem.js @@ -7,6 +7,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { notifyError, notifyInfo } from '../../../redux/actions/error_actions'; import settings from '../../../assets/settings'; import DropDown from '../../../components/UI/DropDown/DropDown'; +import HostList from '../../HostList/HostList'; import Password from '../../../containers/UI/Password/Password'; const mapDispatchToProps = (dispatch) => { @@ -80,6 +81,25 @@ export default connect( ); break; + case 'host_list': + data = ( + + handleChanged({ + target: { + type: 'host_list', + value: items, + }, + }) + } + type={props.template.subtype} + value={props.value} + /> + ); + break; + case 'list': data = ( { +// return {}; +// }; +// +const mapDispatchToProps = (dispatch) => { + return { + addEditHost: (host_data, cb) => dispatch(addEditHost(true, host_data, cb)), + }; +}; + +const Host = ({ allowDelete, addEditHost, value, onChange, onDelete }) => { + const handleEditHost = () => { + addEditHost(value, (changed, host_data) => { + if (changed) { + onChange(host_data); + } + }); + }; + + return ( +
+
+ + + +
+ {allowDelete ? ( +
+ + + +
+ ) : null} +

+ {value.HostNameOrIp + + ((value.Protocol === 'http' && value.ApiPort === 80) || + (value.Protocol === 'https' && value.ApiPort === 443) + ? '' + : ':' + value.ApiPort)} +

+
+ ); +}; + +Host.propTypes = { + allowDelete: PropTypes.bool.isRequired, + addEditHost: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, + onDelete: PropTypes.func.isRequired, + value: PropTypes.object.isRequired, +}; + +export default connect(null, mapDispatchToProps)(Host); +// export default Host; diff --git a/src/containers/HostList/HostList.css b/src/containers/HostList/HostList.css new file mode 100644 index 0000000..e69de29 diff --git a/src/containers/HostList/HostList.js b/src/containers/HostList/HostList.js new file mode 100644 index 0000000..85826d5 --- /dev/null +++ b/src/containers/HostList/HostList.js @@ -0,0 +1,122 @@ +import React from 'react'; +import './HostList.css'; +import Host from './Host/Host'; +import PropTypes from 'prop-types'; +import { Component } from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { confirmYesNo } from '../../redux/actions/common_actions'; +import { connect } from 'react-redux'; +import { addEditHost } from '../../redux/actions/host_actions'; +import { faPlusCircle } from '@fortawesome/free-solid-svg-icons'; + +class HostList extends Component { + state = { + items: [], + }; + // autoFocus={props.autoFocus} + // disabled={props.readOnly} + // type={props.template.subtype} + + componentDidMount() { + this.setState({ items: this.props.value }); + } + + componentWillUnmount() {} + + checkDuplicates = () => { + return false; + }; + + handleAddHost = () => { + this.props.addEditHost((changed, host_data) => { + if (changed) { + const items = [...this.state.items, host_data]; + this.updateItems(items); + } + }); + }; + + handleChanged = (host_data, index) => { + const items = [...this.state.items]; + items[index] = host_data; + this.updateItems(items); + }; + + handleDeleted = (index) => { + this.props.ConfirmRemoveHost( + 'Delete [' + this.state.items[index].HostNameOrIp + ']?', + (confirmed) => { + if (confirmed) { + const items = [...this.state.items]; + items.splice(index, 1); + this.updateItems(items); + } + } + ); + }; + + updateItems = (items) => { + this.setState( + { + items, + }, + () => { + this.props.onChange(this.state.items); + } + ); + }; + + render() { + let idx = 0; + return ( +
+
+ {this.state.items.map((v, index) => { + return ( + this.handleChanged(host_data, index)} + onDelete={() => this.handleDeleted(index)} + allowDelete={this.state.items.length > 1} + value={v} + /> + ); + })} +
+ + + {' Add Portal '} + +
+ ); + } +} + +const mapDispatchToProps = (dispatch) => { + return { + addEditHost: (cb) => dispatch(addEditHost(true, null, cb)), + ConfirmRemoveHost: (title, cb) => dispatch(confirmYesNo(title, cb)), + }; +}; + +HostList.propTypes = { + addEditHost: PropTypes.func.isRequired, + ConfirmRemoveHost: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, + value: PropTypes.array.isRequired, +}; + +export default connect(null, mapDispatchToProps)(HostList); diff --git a/src/containers/PinnedManager/PinnedManager.js b/src/containers/PinnedManager/PinnedManager.js index e3008ab..1f0dbae 100644 --- a/src/containers/PinnedManager/PinnedManager.js +++ b/src/containers/PinnedManager/PinnedManager.js @@ -1,15 +1,15 @@ import React from 'react'; import './PinnedManager.css'; -import { connect } from 'react-redux'; -import IPCContainer from '../IPCContainer/IPCContainer'; -import { notifyApplicationBusy } from '../../redux/actions/common_actions'; -import { notifyError, notifyInfo } from '../../redux/actions/error_actions'; import Box from '../../components/UI/Box/Box'; -import { displayPinnedManager } from '../../redux/actions/pinned_manager_actions'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faFolder } from '@fortawesome/free-solid-svg-icons'; import Button from '../../components/UI/Button/Button'; import CheckBox from '../../components/UI/CheckBox/CheckBox'; +import IPCContainer from '../IPCContainer/IPCContainer'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { connect } from 'react-redux'; +import { displayPinnedManager } from '../../redux/actions/pinned_manager_actions'; +import { faFolder } from '@fortawesome/free-solid-svg-icons'; +import { notifyApplicationBusy } from '../../redux/actions/common_actions'; +import { notifyError, notifyInfo } from '../../redux/actions/error_actions'; const Constants = require('../../constants'); diff --git a/src/redux/actions/common_actions.js b/src/redux/actions/common_actions.js index 592c6e8..871a6d8 100644 --- a/src/redux/actions/common_actions.js +++ b/src/redux/actions/common_actions.js @@ -6,11 +6,15 @@ import { getIPCRenderer } from '../../utils.jsx'; const ipcRenderer = getIPCRenderer(); let yesNoResolvers = []; -export const confirmYesNo = (title) => { +export const confirmYesNo = (title, cb) => { return (dispatch) => { - return new Promise((resolve) => { - dispatch(handleConfirmYesNo(true, title, resolve)); - }); + if (cb) { + dispatch(confirmYesNo(title)).then((confirmed) => cb(confirmed)); + } else { + return new Promise((resolve) => { + dispatch(handleConfirmYesNo(true, title, resolve)); + }); + } }; }; @@ -116,7 +120,7 @@ export const setRebootRequired = () => { }; export const showWindow = () => { - return (_) => { + return () => { if (ipcRenderer) { ipcRenderer.send(Constants.IPC_Show_Window); } diff --git a/src/redux/actions/download_actions.js b/src/redux/actions/download_actions.js index 146551a..a5bfbdc 100644 --- a/src/redux/actions/download_actions.js +++ b/src/redux/actions/download_actions.js @@ -57,13 +57,13 @@ export const downloadItem = ( case Constants.INSTALL_TYPES.Upgrade: // const info = // this.props.LocationsLookup[this.props.AppPlatform][this.props.VersionLookup[this.props.AppPlatform][0]]; - const sha256 = null; // info.sha256; - const signature = null; // info.sig; + //const sha256 = null; // info.sha256; + //const signature = null; // info.sig; dispatch( installUpgrade( result.Destination, - sha256, - signature, + null, + null, !!result.SkipVerification ) ); diff --git a/src/redux/actions/host_actions.js b/src/redux/actions/host_actions.js new file mode 100644 index 0000000..41306ab --- /dev/null +++ b/src/redux/actions/host_actions.js @@ -0,0 +1,41 @@ +let addEditHostResolvers = []; + +export const addEditHost = (display, host_data, cb) => { + return (dispatch) => { + if (cb) { + dispatch(addEditHost(display, host_data)).then(({ changed, host_data }) => + cb(changed, host_data) + ); + } else { + return new Promise((resolve) => { + dispatch(handleDisplayAddEditHost(display, host_data, resolve)); + }); + } + }; +}; + +const handleDisplayAddEditHost = (display, host_data, resolve) => { + return (dispatch) => { + if (display) { + addEditHostResolvers.push(resolve); + dispatch(displayAddEditHost(display, 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_data) => { + return { type: DISPLAY_ADD_EDIT_HOST, payload: { display, host_data } }; +}; diff --git a/src/redux/actions/release_version_actions.js b/src/redux/actions/release_version_actions.js index 46d465f..96e04e2 100644 --- a/src/redux/actions/release_version_actions.js +++ b/src/redux/actions/release_version_actions.js @@ -31,7 +31,7 @@ export const clearUIUpgrade = () => { }; const cleanupOldReleases = (versionList) => { - return (_) => { + return () => { const ipcRenderer = getIPCRenderer(); if (ipcRenderer) { ipcRenderer.sendSync(Constants.IPC_Cleanup_Releases + '_sync', { diff --git a/src/redux/reducers/host_reducer.js b/src/redux/reducers/host_reducer.js new file mode 100644 index 0000000..9284ff4 --- /dev/null +++ b/src/redux/reducers/host_reducer.js @@ -0,0 +1,20 @@ +import { createReducer } from '@reduxjs/toolkit'; +import * as Actions from '../actions/host_actions'; + +export const hostReducer = createReducer( + { + DisplayAddEditHost: false, + Edit: false, + HostData: {}, + }, + { + [Actions.DISPLAY_ADD_EDIT_HOST]: (state, action) => { + return { + ...state, + DisplayAddEditHost: action.payload.display, + Edit: !!action.payload.host_data, + HostData: action.payload.host_data || {}, + }; + }, + } +); diff --git a/src/redux/store/createAppStore.js b/src/redux/store/createAppStore.js index 390d077..e26dbec 100644 --- a/src/redux/store/createAppStore.js +++ b/src/redux/store/createAppStore.js @@ -8,12 +8,14 @@ import { createMountReducer } from '../reducers/mount_reducer'; import { pinnedManagerReducer } from '../reducers/pinned_manager_reducer'; import { releaseVersionReducer } from '../reducers/release_version_reducer'; import { skynetReducer } from '../reducers/skynet_reducer'; +import { hostReducer } from '../reducers/host_reducer'; export default function createAppStore(platformInfo, version, state) { const reducer = { common: createCommonReducer(platformInfo, version), download: downloadReducer, error: errorReducer, + host: hostReducer, install: installReducer, mounts: createMountReducer(state), relver: releaseVersionReducer, diff --git a/src/utils.jsx b/src/utils.jsx index 58a4e0e..7564810 100644 --- a/src/utils.jsx +++ b/src/utils.jsx @@ -24,6 +24,30 @@ export const checkNewReleases = (selectedVersion) => { return []; }; +export const createDismissDisplay = (closeHandler, preventClick) => { + return ( + + ); +}; + export const createModalConditionally = ( condition, jsx,