Initial Skynet premium portal suppport
This commit is contained in:
@@ -7,8 +7,10 @@
|
|||||||
},
|
},
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:react/recommended"
|
"plugin:react/recommended",
|
||||||
|
"plugin:prettier/recommended"
|
||||||
],
|
],
|
||||||
|
"parser": "babel-eslint",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"jsx": true
|
"jsx": true
|
||||||
@@ -17,9 +19,14 @@
|
|||||||
"sourceType": "module"
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
"prettier",
|
||||||
"react",
|
"react",
|
||||||
"jest"
|
"jest"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"prettier/prettier": "warn",
|
||||||
|
"react/prop-types": "warn",
|
||||||
|
"no-prototype-builtins": "warn",
|
||||||
|
"react/no-string-refs": "warn"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
.vimrc
2
.vimrc
@@ -1,6 +1,6 @@
|
|||||||
set autoread
|
set autoread
|
||||||
set path+=.,public/**,src/**,test/**
|
set path+=.,public/**,src/**,test/**
|
||||||
if has('win32')
|
if has('win32') || has('win64')
|
||||||
let &makeprg="create_dist.cmd"
|
let &makeprg="create_dist.cmd"
|
||||||
else
|
else
|
||||||
let &makeprg="./create_dist.sh"
|
let &makeprg="./create_dist.sh"
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"focus-trap-react": "^8.4.2",
|
"focus-trap-react": "^8.4.2",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"node-cron": "1.2.1",
|
"node-cron": "1.2.1",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
"randomstring": "^1.1.5",
|
"randomstring": "^1.1.5",
|
||||||
"react": "16.14.0",
|
"react": "16.14.0",
|
||||||
"react-checkbox-tree": "^1.6.0",
|
"react-checkbox-tree": "^1.6.0",
|
||||||
@@ -37,8 +38,11 @@
|
|||||||
"electron-builder": "22.9.1",
|
"electron-builder": "22.9.1",
|
||||||
"electron-webpack": "^2.8.2",
|
"electron-webpack": "^2.8.2",
|
||||||
"eslint": "^7.22.0",
|
"eslint": "^7.22.0",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-jest": "^24.3.2",
|
"eslint-plugin-jest": "^24.3.2",
|
||||||
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
"eslint-plugin-react": "^7.23.0",
|
"eslint-plugin-react": "^7.23.0",
|
||||||
|
"prettier": "2.2.1",
|
||||||
"webpack": "4.44.2",
|
"webpack": "4.44.2",
|
||||||
"webpack-dev-server": "3.11.1"
|
"webpack-dev-server": "3.11.1"
|
||||||
},
|
},
|
||||||
|
|||||||
16
src/App.jsx
16
src/App.jsx
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
import AddEditHost from './containers/AddEditHost/AddEditHost';
|
||||||
import Box from './components/UI/Box/Box';
|
import Box from './components/UI/Box/Box';
|
||||||
import Configuration from './containers/Configuration/Configuration';
|
import Configuration from './containers/Configuration/Configuration';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
@@ -176,6 +177,15 @@ class App extends IPCContainer {
|
|||||||
!this.props.DismissNewReleasesAvailable &&
|
!this.props.DismissNewReleasesAvailable &&
|
||||||
this.props.NewReleasesAvailable.length > 0;
|
this.props.NewReleasesAvailable.length > 0;
|
||||||
|
|
||||||
|
const showAddEditHost =
|
||||||
|
!showDependencies &&
|
||||||
|
!this.props.DownloadActive &&
|
||||||
|
!showNewReleases &&
|
||||||
|
!this.props.RebootRequired &&
|
||||||
|
!this.props.DisplaySelectAppPlatform &&
|
||||||
|
!showUpgrade &&
|
||||||
|
this.props.DisplayAddEditHost;
|
||||||
|
|
||||||
const showSkynetImport =
|
const showSkynetImport =
|
||||||
!showConfig &&
|
!showConfig &&
|
||||||
!showDependencies &&
|
!showDependencies &&
|
||||||
@@ -204,6 +214,10 @@ class App extends IPCContainer {
|
|||||||
remoteSupported={remoteSupported}
|
remoteSupported={remoteSupported}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
const addEditHostDisplay = createModalConditionally(
|
||||||
|
showAddEditHost,
|
||||||
|
<AddEditHost />
|
||||||
|
);
|
||||||
const pinnedManagerDisplay = createModalConditionally(
|
const pinnedManagerDisplay = createModalConditionally(
|
||||||
showPinnedManager,
|
showPinnedManager,
|
||||||
<PinnedManager version={selectedVersion} />
|
<PinnedManager version={selectedVersion} />
|
||||||
@@ -358,6 +372,7 @@ class App extends IPCContainer {
|
|||||||
{upgradeDisplay}
|
{upgradeDisplay}
|
||||||
{pinnedManagerDisplay}
|
{pinnedManagerDisplay}
|
||||||
{configDisplay}
|
{configDisplay}
|
||||||
|
{addEditHostDisplay}
|
||||||
{infoDisplay}
|
{infoDisplay}
|
||||||
{confirmDisplay}
|
{confirmDisplay}
|
||||||
{downloadDisplay}
|
{downloadDisplay}
|
||||||
@@ -378,6 +393,7 @@ const mapStateToProps = (state) => {
|
|||||||
AppBusyTransparent: state.common.AppBusyTransparent,
|
AppBusyTransparent: state.common.AppBusyTransparent,
|
||||||
AppReady: state.common.AppReady,
|
AppReady: state.common.AppReady,
|
||||||
DismissDependencies: state.install.DismissDependencies,
|
DismissDependencies: state.install.DismissDependencies,
|
||||||
|
DisplayAddEditHost: state.host.DisplayAddEditHost,
|
||||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||||
DisplayConfirmYesNo: state.common.DisplayConfirmYesNo,
|
DisplayConfirmYesNo: state.common.DisplayConfirmYesNo,
|
||||||
DisplayError: state.error.DisplayError,
|
DisplayError: state.error.DisplayError,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import Box from '../UI/Box/Box';
|
import Box from '../UI/Box/Box';
|
||||||
import Loader from 'react-loader-spinner';
|
import Loader from 'react-loader-spinner';
|
||||||
import Text from '../UI/Text/Text';
|
import Text from '../UI/Text/Text';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const ApplicationBusy = ({ title }) => {
|
const ApplicationBusy = ({ title }) => {
|
||||||
return (
|
return (
|
||||||
@@ -27,4 +28,8 @@ const ApplicationBusy = ({ title }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ApplicationBusy.propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
export default ApplicationBusy;
|
export default ApplicationBusy;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import './DependencyList.css';
|
import './DependencyList.css';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
|
import { createDismissDisplay } from '../../utils.jsx';
|
||||||
import Dependency from './Dependency/Dependency';
|
import Dependency from './Dependency/Dependency';
|
||||||
import Box from '../UI/Box/Box';
|
import Box from '../UI/Box/Box';
|
||||||
import { downloadItem } from '../../redux/actions/download_actions';
|
import { downloadItem } from '../../redux/actions/download_actions';
|
||||||
@@ -45,33 +46,12 @@ export default connect(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const dismissDisplay = (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
float: 'right',
|
|
||||||
margin: 0,
|
|
||||||
paddingRight: '4px',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
display: 'block',
|
|
||||||
}}>
|
|
||||||
<a
|
|
||||||
href={'#'}
|
|
||||||
onClick={
|
|
||||||
props.AllowDismissDependencies
|
|
||||||
? () => props.setDismissDependencies(true)
|
|
||||||
: (e) => e.preventDefault()
|
|
||||||
}
|
|
||||||
style={{
|
|
||||||
cursor: props.AllowDismissDependencies ? 'pointer' : 'no-drop',
|
|
||||||
}}>
|
|
||||||
X
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box dxStyle={{ width: '300px', height: 'auto', padding: '5px' }}>
|
<Box dxStyle={{ width: '300px', height: 'auto', padding: '5px' }}>
|
||||||
{dismissDisplay}
|
{createDismissDisplay(
|
||||||
|
() => props.setDismissDependencies(true),
|
||||||
|
!props.AllowDismissDependencies
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|||||||
232
src/containers/AddEditHost/AddEditHost.js
Normal file
232
src/containers/AddEditHost/AddEditHost.js
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Box from '../../components/UI/Box/Box';
|
||||||
|
import Button from '../../components/UI/Button/Button';
|
||||||
|
import DropDown from '../../components/UI/DropDown/DropDown';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Text from '../../components/UI/Text/Text';
|
||||||
|
import { Component } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { createDismissDisplay } from '../../utils.jsx';
|
||||||
|
import {
|
||||||
|
addEditHost,
|
||||||
|
completeAddEditHost,
|
||||||
|
} from '../../redux/actions/host_actions';
|
||||||
|
|
||||||
|
class AddEditHost extends Component {
|
||||||
|
state = {
|
||||||
|
AgentString: '',
|
||||||
|
ApiPassword: '',
|
||||||
|
ApiPort: 443,
|
||||||
|
AuthPassword: '',
|
||||||
|
AuthURL: '',
|
||||||
|
AuthUser: '',
|
||||||
|
HostNameOrIp: '',
|
||||||
|
Path: '',
|
||||||
|
Protocol: 'https',
|
||||||
|
TimeoutMs: 60000,
|
||||||
|
};
|
||||||
|
|
||||||
|
originalState = {};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.props.HostData) {
|
||||||
|
const state = { ...this.state, ...this.props.HostData };
|
||||||
|
this.originalState = { ...state };
|
||||||
|
this.setState(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSave = () => {
|
||||||
|
this.props.completeAddEditHost(this.state);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Box dxStyle={{ width: '430px', height: 'auto', padding: '5px' }}>
|
||||||
|
{createDismissDisplay(this.props.Close)}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: 'auto',
|
||||||
|
paddingBottom: '5px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
}}>
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
textAlign: 'center',
|
||||||
|
color: 'var(--text_color_error)',
|
||||||
|
}}>
|
||||||
|
Portal Settings
|
||||||
|
</h1>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'Host / IP'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<input
|
||||||
|
onChange={(e) =>
|
||||||
|
this.setState({ HostNameOrIp: e.target.value.trim() })
|
||||||
|
}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.HostNameOrIp}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'Protocol'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'Port'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'Timeout (ms)'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<DropDown
|
||||||
|
changed={(e) => this.setState({ Protocol: e.target.value })}
|
||||||
|
items={['https', 'http']}
|
||||||
|
selected={this.state.Protocol}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ ApiPort: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'number'}
|
||||||
|
min={1}
|
||||||
|
max={65535}
|
||||||
|
value={this.state.ApiPort}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ TimeoutMs: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'number'}
|
||||||
|
min={1000}
|
||||||
|
step={1000}
|
||||||
|
value={this.state.TimeoutMs}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text
|
||||||
|
text={'Agent String (optional)'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<Text
|
||||||
|
text={'API Key (optional)'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ AgentString: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ flex: '1' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AgentString}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ ApiPassword: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ flex: '1' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.ApiPassword}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text
|
||||||
|
text={'Authentication URL (premium)'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ AuthURL: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AuthURL}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text
|
||||||
|
text={'User Name (premium)'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<Text
|
||||||
|
text={'Password (premium)'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ AuthUser: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ flex: '1' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AuthUser}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ AuthPassword: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ flex: '1' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AuthPassword}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<p>
|
||||||
|
<b>
|
||||||
|
{'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()
|
||||||
|
: '')}
|
||||||
|
</b>
|
||||||
|
</p>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
</div>
|
||||||
|
<Button clicked={this.handleSave}>Save</Button>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
@@ -36,7 +36,7 @@ const default_state = {
|
|||||||
DisplayS3: false,
|
DisplayS3: false,
|
||||||
HostNameOrIp: '',
|
HostNameOrIp: '',
|
||||||
Name: '',
|
Name: '',
|
||||||
Port: 20000,
|
Port: 2000,
|
||||||
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: '',
|
||||||
@@ -47,7 +47,7 @@ export default connect(
|
|||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(
|
)(
|
||||||
class extends Component {
|
class AddMount extends Component {
|
||||||
state = {
|
state = {
|
||||||
...default_state,
|
...default_state,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Configuration.css';
|
import './Configuration.css';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { createDismissDisplay } from '../../utils.jsx';
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
import ConfigurationItem from './ConfigurationItem/ConfigurationItem';
|
import ConfigurationItem from './ConfigurationItem/ConfigurationItem';
|
||||||
@@ -35,6 +36,27 @@ class Configuration extends IPCContainer {
|
|||||||
}
|
}
|
||||||
return itemA.value.filter((i) => !itemB.value.includes(i)).length !== 0;
|
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;
|
return itemA.value !== itemB.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,9 +137,11 @@ class Configuration extends IPCContainer {
|
|||||||
remote: template[key] ? template[key].remote : false,
|
remote: template[key] ? template[key].remote : false,
|
||||||
type: template[key] ? template[key].type : null,
|
type: template[key] ? template[key].type : null,
|
||||||
value:
|
value:
|
||||||
template[key] && template[key].type === 'object'
|
template[key] &&
|
||||||
|
(template[key].type === 'string_array' ||
|
||||||
|
template[key].type === 'object')
|
||||||
? config[key]
|
? config[key]
|
||||||
: template[key] && template[key].type === 'string_array'
|
: template[key] && template[key].type === 'host_list'
|
||||||
? config[key]
|
? config[key]
|
||||||
: config[key].toString(),
|
: config[key].toString(),
|
||||||
};
|
};
|
||||||
@@ -141,6 +165,8 @@ class Configuration extends IPCContainer {
|
|||||||
itemList[idx].value =
|
itemList[idx].value =
|
||||||
target.type === 'textarea'
|
target.type === 'textarea'
|
||||||
? target.string_array
|
? target.string_array
|
||||||
|
: target.type === 'host_list'
|
||||||
|
? target.value
|
||||||
: target.value.toString();
|
: target.value.toString();
|
||||||
this.setState({
|
this.setState({
|
||||||
ItemList: itemList,
|
ItemList: itemList,
|
||||||
@@ -156,6 +182,8 @@ class Configuration extends IPCContainer {
|
|||||||
itemList[idx].value =
|
itemList[idx].value =
|
||||||
target.type === 'textarea'
|
target.type === 'textarea'
|
||||||
? target.string_array
|
? target.string_array
|
||||||
|
: target.type === 'host_list'
|
||||||
|
? target.value
|
||||||
: target.value.toString();
|
: target.value.toString();
|
||||||
objectLookup[name] = itemList;
|
objectLookup[name] = itemList;
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -246,7 +274,11 @@ class Configuration extends IPCContainer {
|
|||||||
changedItems.push({
|
changedItems.push({
|
||||||
Name: item.label,
|
Name: item.label,
|
||||||
Value:
|
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:
|
Value:
|
||||||
item.type === 'string_array'
|
item.type === 'string_array'
|
||||||
? item.value.join(';')
|
? item.value.join(';')
|
||||||
|
: item.type === 'host_list'
|
||||||
|
? JSON.stringify(item.value)
|
||||||
: item.value,
|
: item.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -402,23 +436,8 @@ class Configuration extends IPCContainer {
|
|||||||
return (
|
return (
|
||||||
<div className={'Configuration'}>
|
<div className={'Configuration'}>
|
||||||
{confirmSave}
|
{confirmSave}
|
||||||
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)' }}>
|
<Box dxDark dxStyle={{ padding: '5px' }}>
|
||||||
<div
|
{createDismissDisplay(this.checkSaveRequired)}
|
||||||
style={{
|
|
||||||
float: 'right',
|
|
||||||
margin: 0,
|
|
||||||
padding: 0,
|
|
||||||
marginTop: '-4px',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
display: 'block',
|
|
||||||
}}>
|
|
||||||
<a
|
|
||||||
href={'#'}
|
|
||||||
onClick={this.checkSaveRequired}
|
|
||||||
style={{ cursor: 'pointer' }}>
|
|
||||||
X
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<h1 style={{ width: '100%', textAlign: 'center' }}>
|
<h1 style={{ width: '100%', textAlign: 'center' }}>
|
||||||
{(this.props.DisplayRemoteConfiguration
|
{(this.props.DisplayRemoteConfiguration
|
||||||
? this.props.DisplayConfiguration.substr(6)
|
? this.props.DisplayConfiguration.substr(6)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|||||||
import { notifyError, notifyInfo } from '../../../redux/actions/error_actions';
|
import { notifyError, notifyInfo } from '../../../redux/actions/error_actions';
|
||||||
import settings from '../../../assets/settings';
|
import settings from '../../../assets/settings';
|
||||||
import DropDown from '../../../components/UI/DropDown/DropDown';
|
import DropDown from '../../../components/UI/DropDown/DropDown';
|
||||||
|
import HostList from '../../HostList/HostList';
|
||||||
import Password from '../../../containers/UI/Password/Password';
|
import Password from '../../../containers/UI/Password/Password';
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
@@ -80,6 +81,25 @@ export default connect(
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'host_list':
|
||||||
|
data = (
|
||||||
|
<HostList
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
|
disabled={props.readOnly}
|
||||||
|
onChange={(items) =>
|
||||||
|
handleChanged({
|
||||||
|
target: {
|
||||||
|
type: 'host_list',
|
||||||
|
value: items,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
type={props.template.subtype}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'list':
|
case 'list':
|
||||||
data = (
|
data = (
|
||||||
<DropDown
|
<DropDown
|
||||||
|
|||||||
0
src/containers/HostList/Host/Host.css
Normal file
0
src/containers/HostList/Host/Host.css
Normal file
69
src/containers/HostList/Host/Host.js
Normal file
69
src/containers/HostList/Host/Host.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { addEditHost } from '../../../redux/actions/host_actions';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { faTrashAlt, faEdit } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
// const mapStateToProps = (state) => {
|
||||||
|
// 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 (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 0,
|
||||||
|
paddingRight: 'calc(var(--default_spacing) * 1.25)',
|
||||||
|
}}>
|
||||||
|
<a href={'#'} onClick={handleEditHost}>
|
||||||
|
<FontAwesomeIcon icon={faEdit} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{allowDelete ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 0,
|
||||||
|
paddingRight: 'calc(var(--default_spacing) * 1.25)',
|
||||||
|
}}>
|
||||||
|
<a href={'#'} onClick={onDelete}>
|
||||||
|
<FontAwesomeIcon icon={faTrashAlt} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<p>
|
||||||
|
{value.HostNameOrIp +
|
||||||
|
((value.Protocol === 'http' && value.ApiPort === 80) ||
|
||||||
|
(value.Protocol === 'https' && value.ApiPort === 443)
|
||||||
|
? ''
|
||||||
|
: ':' + value.ApiPort)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
0
src/containers/HostList/HostList.css
Normal file
0
src/containers/HostList/HostList.css
Normal file
122
src/containers/HostList/HostList.js
Normal file
122
src/containers/HostList/HostList.js
Normal file
@@ -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 (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
maxHeight: '80px',
|
||||||
|
maxWidth: '260px',
|
||||||
|
minWidth: '260px',
|
||||||
|
backgroundColor: 'var(--control_background)',
|
||||||
|
padding: 'var(--default_spacing)',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
}}>
|
||||||
|
{this.state.items.map((v, index) => {
|
||||||
|
return (
|
||||||
|
<Host
|
||||||
|
key={idx++}
|
||||||
|
onChange={(host_data) => this.handleChanged(host_data, index)}
|
||||||
|
onDelete={() => this.handleDeleted(index)}
|
||||||
|
allowDelete={this.state.items.length > 1}
|
||||||
|
value={v}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href={'#'}
|
||||||
|
onClick={this.handleAddHost}
|
||||||
|
style={{
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
}}>
|
||||||
|
<FontAwesomeIcon icon={faPlusCircle} />
|
||||||
|
<b>{' Add Portal '}</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './PinnedManager.css';
|
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 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 Button from '../../components/UI/Button/Button';
|
||||||
import CheckBox from '../../components/UI/CheckBox/CheckBox';
|
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');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,15 @@ import { getIPCRenderer } from '../../utils.jsx';
|
|||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
let yesNoResolvers = [];
|
let yesNoResolvers = [];
|
||||||
|
|
||||||
export const confirmYesNo = (title) => {
|
export const confirmYesNo = (title, cb) => {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
|
if (cb) {
|
||||||
|
dispatch(confirmYesNo(title)).then((confirmed) => cb(confirmed));
|
||||||
|
} else {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
dispatch(handleConfirmYesNo(true, title, resolve));
|
dispatch(handleConfirmYesNo(true, title, resolve));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -116,7 +120,7 @@ export const setRebootRequired = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const showWindow = () => {
|
export const showWindow = () => {
|
||||||
return (_) => {
|
return () => {
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.send(Constants.IPC_Show_Window);
|
ipcRenderer.send(Constants.IPC_Show_Window);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,13 +57,13 @@ export const downloadItem = (
|
|||||||
case Constants.INSTALL_TYPES.Upgrade:
|
case Constants.INSTALL_TYPES.Upgrade:
|
||||||
// const info =
|
// const info =
|
||||||
// this.props.LocationsLookup[this.props.AppPlatform][this.props.VersionLookup[this.props.AppPlatform][0]];
|
// this.props.LocationsLookup[this.props.AppPlatform][this.props.VersionLookup[this.props.AppPlatform][0]];
|
||||||
const sha256 = null; // info.sha256;
|
//const sha256 = null; // info.sha256;
|
||||||
const signature = null; // info.sig;
|
//const signature = null; // info.sig;
|
||||||
dispatch(
|
dispatch(
|
||||||
installUpgrade(
|
installUpgrade(
|
||||||
result.Destination,
|
result.Destination,
|
||||||
sha256,
|
null,
|
||||||
signature,
|
null,
|
||||||
!!result.SkipVerification
|
!!result.SkipVerification
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
41
src/redux/actions/host_actions.js
Normal file
41
src/redux/actions/host_actions.js
Normal file
@@ -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 } };
|
||||||
|
};
|
||||||
@@ -31,7 +31,7 @@ export const clearUIUpgrade = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const cleanupOldReleases = (versionList) => {
|
const cleanupOldReleases = (versionList) => {
|
||||||
return (_) => {
|
return () => {
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.sendSync(Constants.IPC_Cleanup_Releases + '_sync', {
|
ipcRenderer.sendSync(Constants.IPC_Cleanup_Releases + '_sync', {
|
||||||
|
|||||||
20
src/redux/reducers/host_reducer.js
Normal file
20
src/redux/reducers/host_reducer.js
Normal file
@@ -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 || {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
@@ -8,12 +8,14 @@ import { createMountReducer } from '../reducers/mount_reducer';
|
|||||||
import { pinnedManagerReducer } from '../reducers/pinned_manager_reducer';
|
import { pinnedManagerReducer } from '../reducers/pinned_manager_reducer';
|
||||||
import { releaseVersionReducer } from '../reducers/release_version_reducer';
|
import { releaseVersionReducer } from '../reducers/release_version_reducer';
|
||||||
import { skynetReducer } from '../reducers/skynet_reducer';
|
import { skynetReducer } from '../reducers/skynet_reducer';
|
||||||
|
import { hostReducer } from '../reducers/host_reducer';
|
||||||
|
|
||||||
export default function createAppStore(platformInfo, version, state) {
|
export default function createAppStore(platformInfo, version, state) {
|
||||||
const reducer = {
|
const reducer = {
|
||||||
common: createCommonReducer(platformInfo, version),
|
common: createCommonReducer(platformInfo, version),
|
||||||
download: downloadReducer,
|
download: downloadReducer,
|
||||||
error: errorReducer,
|
error: errorReducer,
|
||||||
|
host: hostReducer,
|
||||||
install: installReducer,
|
install: installReducer,
|
||||||
mounts: createMountReducer(state),
|
mounts: createMountReducer(state),
|
||||||
relver: releaseVersionReducer,
|
relver: releaseVersionReducer,
|
||||||
|
|||||||
@@ -24,6 +24,30 @@ export const checkNewReleases = (selectedVersion) => {
|
|||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createDismissDisplay = (closeHandler, preventClick) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
float: 'right',
|
||||||
|
margin: '0px',
|
||||||
|
paddingRight: '4px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
display: 'block',
|
||||||
|
}}>
|
||||||
|
<a
|
||||||
|
href={'#'}
|
||||||
|
onClick={(e) => {
|
||||||
|
preventClick ? e.preventDefault() : closeHandler();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
cursor: preventClick ? 'no-drop' : 'pointer',
|
||||||
|
}}>
|
||||||
|
X
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const createModalConditionally = (
|
export const createModalConditionally = (
|
||||||
condition,
|
condition,
|
||||||
jsx,
|
jsx,
|
||||||
|
|||||||
Reference in New Issue
Block a user