Prettier support
This commit is contained in:
@@ -1,29 +1,32 @@
|
||||
import React from 'react';
|
||||
import {Component} from 'react';
|
||||
import { Component } from 'react';
|
||||
import './AddMount.css';
|
||||
import {connect} from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import Button from '../../components/UI/Button/Button';
|
||||
import Box from '../../components/UI/Box/Box';
|
||||
import Text from '../../components/UI/Text/Text';
|
||||
import {notifyError} from '../../redux/actions/error_actions';
|
||||
import {addRemoteMount, addS3Mount} from '../../redux/actions/mount_actions';
|
||||
import {createModalConditionally} from '../../utils';
|
||||
import { notifyError } from '../../redux/actions/error_actions';
|
||||
import { addRemoteMount, addS3Mount } from '../../redux/actions/mount_actions';
|
||||
import { createModalConditionally } from '../../utils.jsx';
|
||||
import DropDown from '../../components/UI/DropDown/DropDown';
|
||||
import * as Constants from '../../constants';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
RemoteMounts: state.mounts.RemoteMounts,
|
||||
S3Mounts: state.mounts.S3Mounts,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
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)),
|
||||
}
|
||||
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 = {
|
||||
@@ -40,207 +43,288 @@ const default_state = {
|
||||
Token: '',
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(class extends Component {
|
||||
state = {
|
||||
...default_state,
|
||||
};
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(
|
||||
class extends Component {
|
||||
state = {
|
||||
...default_state,
|
||||
};
|
||||
|
||||
addRemoteMount = () => {
|
||||
if (this.state.HostNameOrIp.length === 0) {
|
||||
this.props.notifyError('Hostname or IP cannot be empty.');
|
||||
} else {
|
||||
const provider = 'Remote' + this.state.HostNameOrIp + ':' + this.state.Port;
|
||||
if (this.props.RemoteMounts.includes(provider)) {
|
||||
this.props.notifyError('Remote host already exists');
|
||||
addRemoteMount = () => {
|
||||
if (this.state.HostNameOrIp.length === 0) {
|
||||
this.props.notifyError('Hostname or IP cannot be empty.');
|
||||
} else {
|
||||
this.setState({
|
||||
DisplayRemote: false
|
||||
}, () => {
|
||||
this.props.addRemoteMount(this.state.HostNameOrIp, this.state.Port, this.state.Token);
|
||||
this.setState({
|
||||
...default_state,
|
||||
});
|
||||
});
|
||||
const provider =
|
||||
'Remote' + this.state.HostNameOrIp + ':' + this.state.Port;
|
||||
if (this.props.RemoteMounts.includes(provider)) {
|
||||
this.props.notifyError('Remote host already exists');
|
||||
} else {
|
||||
this.setState(
|
||||
{
|
||||
DisplayRemote: false,
|
||||
},
|
||||
() => {
|
||||
this.props.addRemoteMount(
|
||||
this.state.HostNameOrIp,
|
||||
this.state.Port,
|
||||
this.state.Token
|
||||
);
|
||||
this.setState({
|
||||
...default_state,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
addS3Mount = () => {
|
||||
if (this.state.Name.length === 0) {
|
||||
this.props.notifyError('Name cannot be empty.');
|
||||
} else if (this.state.AccessKey.length === 0) {
|
||||
this.props.notifyError('AccessKey cannot be empty.');
|
||||
} else if (this.state.SecretKey.length === 0) {
|
||||
this.props.notifyError('SecretKey cannot be empty.')
|
||||
} else {
|
||||
const provider = 'S3' + this.state.Name;
|
||||
if (this.props.S3Mounts.includes(provider)) {
|
||||
this.props.notifyError('Remote host already exists');
|
||||
addS3Mount = () => {
|
||||
if (this.state.Name.length === 0) {
|
||||
this.props.notifyError('Name cannot be empty.');
|
||||
} else if (this.state.AccessKey.length === 0) {
|
||||
this.props.notifyError('AccessKey cannot be empty.');
|
||||
} else if (this.state.SecretKey.length === 0) {
|
||||
this.props.notifyError('SecretKey cannot be empty.');
|
||||
} else {
|
||||
this.setState({
|
||||
DisplayS3: false
|
||||
}, () => {
|
||||
this.props.addS3Mount(this.state.Name, this.state.AccessKey, this.state.SecretKey,
|
||||
this.state.Region, this.state.BucketName, Constants.S3_PROVIDER_URL[this.state.Provider]);
|
||||
this.setState({
|
||||
...default_state,
|
||||
});
|
||||
});
|
||||
const provider = 'S3' + this.state.Name;
|
||||
if (this.props.S3Mounts.includes(provider)) {
|
||||
this.props.notifyError('Remote host already exists');
|
||||
} else {
|
||||
this.setState(
|
||||
{
|
||||
DisplayS3: false,
|
||||
},
|
||||
() => {
|
||||
this.props.addS3Mount(
|
||||
this.state.Name,
|
||||
this.state.AccessKey,
|
||||
this.state.SecretKey,
|
||||
this.state.Region,
|
||||
this.state.BucketName,
|
||||
Constants.S3_PROVIDER_URL[this.state.Provider]
|
||||
);
|
||||
this.setState({
|
||||
...default_state,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleAddS3Mount = () => {
|
||||
this.setState({
|
||||
DisplayRemote: false,
|
||||
DisplayS3: true,
|
||||
});
|
||||
};
|
||||
|
||||
handleAddRemoteMount = () => {
|
||||
this.setState({
|
||||
DisplayRemote: true,
|
||||
DisplayS3: false,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const displayAddRemote = createModalConditionally(
|
||||
this.state.DisplayRemote,
|
||||
<Box
|
||||
dxDark
|
||||
dxStyle={{
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
padding: 'var(--default_spacing)',
|
||||
}}
|
||||
>
|
||||
<h1
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
paddingBottom: 'var(--default_spacing)',
|
||||
}}
|
||||
>
|
||||
Add Remote Mount
|
||||
</h1>
|
||||
<Text text={'Hostname or IP'} textAlign={'left'} type={'Heading2'} />
|
||||
<input
|
||||
onChange={(e) =>
|
||||
this.setState({ HostNameOrIp: e.target.value.trim() })
|
||||
}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.HostNameOrIp}
|
||||
/>
|
||||
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||
<Text text={'Port'} textAlign={'left'} type={'Heading2'} />
|
||||
<input
|
||||
max={65535}
|
||||
min={1025}
|
||||
onChange={(e) => this.setState({ Port: e.target.value })}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={this.state.Port}
|
||||
/>
|
||||
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||
<Text text={'Remote Token'} textAlign={'left'} type={'Heading2'} />
|
||||
<input
|
||||
onChange={(e) => this.setState({ Token: e.target.value })}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.Token}
|
||||
/>
|
||||
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<Button
|
||||
buttonStyles={{ width: '100%' }}
|
||||
clicked={() => this.addRemoteMount()}
|
||||
>
|
||||
OK
|
||||
</Button>
|
||||
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||
<Button
|
||||
buttonStyles={{ width: '100%' }}
|
||||
clicked={() => this.setState({ DisplayRemote: false })}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
|
||||
const displayAddS3 = createModalConditionally(
|
||||
this.state.DisplayS3,
|
||||
<Box
|
||||
dxDark
|
||||
dxStyle={{
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
padding: 'var(--default_spacing)',
|
||||
}}
|
||||
>
|
||||
<h1
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
paddingBottom: 'var(--default_spacing)',
|
||||
}}
|
||||
>
|
||||
Add S3 Mount
|
||||
</h1>
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<Text text={'Name'} textAlign={'left'} type={'Heading2'} />
|
||||
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||
<Text text={'Provider'} textAlign={'left'} type={'Heading2'} />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<input
|
||||
onChange={(e) => this.setState({ Name: e.target.value.trim() })}
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{ width: '100%' }}
|
||||
type={'text'}
|
||||
value={this.state.Name}
|
||||
/>
|
||||
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||
<DropDown
|
||||
changed={(e) => this.setState({ Provider: e.target.value })}
|
||||
items={Constants.S3_PROVIDER_LIST}
|
||||
selected={this.state.Provider}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<Text
|
||||
text={'Bucket Name (optional)'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}
|
||||
/>
|
||||
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||
<Text text={'Region'} textAlign={'left'} type={'Heading2'} />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<input
|
||||
onChange={(e) => this.setState({ BucketName: e.target.value })}
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{ width: '100%' }}
|
||||
type={'text'}
|
||||
value={this.state.BucketName}
|
||||
/>
|
||||
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||
<input
|
||||
onChange={(e) => this.setState({ Region: e.target.value })}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.Region}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<Text text={'Access Key'} textAlign={'left'} type={'Heading2'} />
|
||||
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||
<Text text={'Secret Key'} textAlign={'left'} type={'Heading2'} />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<input
|
||||
onChange={(e) => this.setState({ AccessKey: e.target.value })}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.AccessKey}
|
||||
/>
|
||||
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||
<input
|
||||
onChange={(e) => this.setState({ SecretKey: e.target.value })}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.SecretKey}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ paddingTop: 'calc(var(--default_spacing) * 2)' }} />
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<div style={{ width: '200%' }} />
|
||||
<Button
|
||||
buttonStyles={{ width: '100%' }}
|
||||
clicked={() => this.addS3Mount()}
|
||||
>
|
||||
OK
|
||||
</Button>
|
||||
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||
<Button
|
||||
buttonStyles={{ width: '100%' }}
|
||||
clicked={() => this.setState({ DisplayS3: false })}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={'AddMount'}>
|
||||
{displayAddRemote}
|
||||
{displayAddS3}
|
||||
<div className={'AddMountButtons'}>
|
||||
{this.props.remoteSupported ? (
|
||||
<Button
|
||||
className={'AddMountButton'}
|
||||
clicked={this.handleAddRemoteMount}
|
||||
>
|
||||
Add Remote Mount
|
||||
</Button>
|
||||
) : null}
|
||||
{this.props.remoteSupported && this.props.s3Supported ? (
|
||||
<div style={{ paddingRight: 'var(--default_spacing)' }} />
|
||||
) : null}
|
||||
{this.props.s3Supported ? (
|
||||
<Button
|
||||
className={'AddMountButton'}
|
||||
clicked={this.handleAddS3Mount}
|
||||
>
|
||||
Add S3 Mount
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
handleAddS3Mount = () => {
|
||||
this.setState({
|
||||
DisplayRemote: false,
|
||||
DisplayS3: true,
|
||||
});
|
||||
};
|
||||
|
||||
handleAddRemoteMount = () => {
|
||||
this.setState({
|
||||
DisplayRemote: true,
|
||||
DisplayS3: false,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const displayAddRemote = createModalConditionally(this.state.DisplayRemote, (
|
||||
<Box dxDark
|
||||
dxStyle={{width: 'auto', height: 'auto', padding: 'var(--default_spacing)'}}>
|
||||
<h1 style={{textAlign: 'center', paddingBottom: 'var(--default_spacing)'}}>Add Remote
|
||||
Mount</h1>
|
||||
<Text text={'Hostname or IP'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
<input onChange={e => this.setState({HostNameOrIp: e.target.value.trim()})}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.HostNameOrIp}/>
|
||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||
<Text text={'Port'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
<input max={65535}
|
||||
min={1025}
|
||||
onChange={e => this.setState({Port: e.target.value})}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={this.state.Port}/>
|
||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||
<Text text={'Remote Token'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
<input onChange={e => this.setState({Token: e.target.value})}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.Token}/>
|
||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<Button buttonStyles={{width: '100%'}}
|
||||
clicked={() => this.addRemoteMount()}>OK</Button>
|
||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||
<Button buttonStyles={{width: '100%'}}
|
||||
clicked={() => this.setState({DisplayRemote: false})}>Cancel</Button>
|
||||
</div>
|
||||
</Box>
|
||||
));
|
||||
|
||||
const displayAddS3 = createModalConditionally(this.state.DisplayS3, (
|
||||
<Box dxDark
|
||||
dxStyle={{width: 'auto', height: 'auto', padding: 'var(--default_spacing)'}}>
|
||||
<h1 style={{textAlign: 'center', paddingBottom: 'var(--default_spacing)'}}>Add S3
|
||||
Mount</h1>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<Text text={'Name'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||
<Text text={'Provider'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
</div>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<input onChange={e => this.setState({Name: e.target.value.trim()})}
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{width: '100%'}}
|
||||
type={'text'}
|
||||
value={this.state.Name}/>
|
||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||
<DropDown changed={e => this.setState({Provider: e.target.value})}
|
||||
items={Constants.S3_PROVIDER_LIST}
|
||||
selected={this.state.Provider}/>
|
||||
</div>
|
||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<Text text={'Bucket Name (optional)'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||
<Text text={'Region'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
</div>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<input onChange={e => this.setState({BucketName: e.target.value})}
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{width: '100%'}}
|
||||
type={'text'}
|
||||
value={this.state.BucketName}/>
|
||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||
<input onChange={e => this.setState({Region: e.target.value})}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.Region}/>
|
||||
</div>
|
||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<Text text={'Access Key'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||
<Text text={'Secret Key'}
|
||||
textAlign={'left'}
|
||||
type={'Heading2'}/>
|
||||
</div>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<input onChange={e => this.setState({AccessKey: e.target.value})}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.AccessKey}/>
|
||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||
<input onChange={e => this.setState({SecretKey: e.target.value})}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'text'}
|
||||
value={this.state.SecretKey}/>
|
||||
</div>
|
||||
<div style={{paddingTop: 'calc(var(--default_spacing) * 2)'}}/>
|
||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||
<div style={{width: '200%'}}/>
|
||||
<Button buttonStyles={{width: '100%'}}
|
||||
clicked={() => this.addS3Mount()}>OK</Button>
|
||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||
<Button buttonStyles={{width: '100%'}}
|
||||
clicked={() => this.setState({DisplayS3: false})}>Cancel</Button>
|
||||
</div>
|
||||
</Box>
|
||||
));
|
||||
|
||||
return (
|
||||
<div className={'AddMount'}>
|
||||
{displayAddRemote}
|
||||
{displayAddS3}
|
||||
<div className={'AddMountButtons'}>
|
||||
{this.props.remoteSupported ?
|
||||
<Button className={'AddMountButton'}
|
||||
clicked={this.handleAddRemoteMount}>Add Remote Mount</Button> : null}
|
||||
{this.props.remoteSupported && this.props.s3Supported ?
|
||||
<div style={{paddingRight: 'var(--default_spacing)'}}/> : null}
|
||||
{this.props.s3Supported ?
|
||||
<Button className={'AddMountButton'}
|
||||
clicked={this.handleAddS3Mount}>Add S3 Mount</Button> : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React from 'react';
|
||||
import './Configuration.css';
|
||||
import {connect} from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import Box from '../../components/UI/Box/Box';
|
||||
import Button from '../../components/UI/Button/Button';
|
||||
import ConfigurationItem from './ConfigurationItem/ConfigurationItem';
|
||||
import Modal from '../../components/UI/Modal/Modal';
|
||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||
import {displayConfiguration} from '../../redux/actions/mount_actions';
|
||||
import {notifyError} from '../../redux/actions/error_actions';
|
||||
import {displayPinnedManager} from '../../redux/actions/pinned_manager_actions';
|
||||
import { displayConfiguration } from '../../redux/actions/mount_actions';
|
||||
import { notifyError } from '../../redux/actions/error_actions';
|
||||
import { displayPinnedManager } from '../../redux/actions/pinned_manager_actions';
|
||||
|
||||
const Constants = require('../../constants');
|
||||
|
||||
@@ -25,7 +25,7 @@ class Configuration extends IPCContainer {
|
||||
ItemList: [],
|
||||
Saving: false,
|
||||
ShowAdvanced: false,
|
||||
Template: {}
|
||||
Template: {},
|
||||
};
|
||||
|
||||
checkItemChanged = (itemA, itemB) => {
|
||||
@@ -33,7 +33,7 @@ class Configuration extends IPCContainer {
|
||||
if (itemA.value.length !== itemB.value.length) {
|
||||
return true;
|
||||
}
|
||||
return itemA.value.filter(i => !itemB.value.includes(i)).length !== 0;
|
||||
return itemA.value.filter((i) => !itemB.value.includes(i)).length !== 0;
|
||||
}
|
||||
return itemA.value !== itemB.value;
|
||||
};
|
||||
@@ -52,7 +52,9 @@ class Configuration extends IPCContainer {
|
||||
const changedObjectItems = [];
|
||||
let j = 0;
|
||||
for (const item of this.state.ObjectLookup[key]) {
|
||||
if (this.checkItemChanged(this.state.OriginalObjectLookup[key][j++], item)) {
|
||||
if (
|
||||
this.checkItemChanged(this.state.OriginalObjectLookup[key][j++], item)
|
||||
) {
|
||||
changedObjectItems.push(item);
|
||||
}
|
||||
}
|
||||
@@ -65,7 +67,7 @@ class Configuration extends IPCContainer {
|
||||
}
|
||||
}
|
||||
|
||||
if ((changedItems.length > 0) || changedObjectLookup) {
|
||||
if (changedItems.length > 0 || changedObjectLookup) {
|
||||
this.setState({
|
||||
ChangedItems: changedItems,
|
||||
ChangedObjectLookup: changedObjectLookup,
|
||||
@@ -77,9 +79,18 @@ class Configuration extends IPCContainer {
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this.setRequestHandler(Constants.IPC_Get_Config_Template_Reply, this.onGetConfigTemplateReply);
|
||||
this.setRequestHandler(Constants.IPC_Get_Config_Reply, this.onGetConfigReply);
|
||||
this.setRequestHandler(Constants.IPC_Set_Config_Values_Reply, this.onSetConfigValuesReply);
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Get_Config_Template_Reply,
|
||||
this.onGetConfigTemplateReply
|
||||
);
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Get_Config_Reply,
|
||||
this.onGetConfigReply
|
||||
);
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Set_Config_Values_Reply,
|
||||
this.onSetConfigValuesReply
|
||||
);
|
||||
this.sendRequest(Constants.IPC_Get_Config_Template, {
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
@@ -95,55 +106,57 @@ class Configuration extends IPCContainer {
|
||||
|
||||
createItemList = (config, template) => {
|
||||
const objectList = [];
|
||||
const itemList = Object
|
||||
.keys(config)
|
||||
.map(key => {
|
||||
return {
|
||||
advanced: template[key] ? template[key].advanced : false,
|
||||
hide_remote: template[key] ? template[key].hide_remote : false,
|
||||
label: key,
|
||||
remote: template[key] ? template[key].remote : false,
|
||||
type: template[key] ? template[key].type : null,
|
||||
value: (template[key] && (template[key].type === 'object')) ?
|
||||
config[key] :
|
||||
(template[key] && (template[key].type === 'string_array')) ?
|
||||
config[key] :
|
||||
config[key].toString(),
|
||||
};
|
||||
})
|
||||
.filter(i => {
|
||||
let ret = template[i.label];
|
||||
if (ret && (template[i.label].type === 'object')) {
|
||||
objectList.push(i);
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
const itemList = Object.keys(config)
|
||||
.map((key) => {
|
||||
return {
|
||||
advanced: template[key] ? template[key].advanced : false,
|
||||
hide_remote: template[key] ? template[key].hide_remote : false,
|
||||
label: key,
|
||||
remote: template[key] ? template[key].remote : false,
|
||||
type: template[key] ? template[key].type : null,
|
||||
value:
|
||||
template[key] && template[key].type === 'object'
|
||||
? config[key]
|
||||
: template[key] && template[key].type === 'string_array'
|
||||
? config[key]
|
||||
: config[key].toString(),
|
||||
};
|
||||
})
|
||||
.filter((i) => {
|
||||
let ret = template[i.label];
|
||||
if (ret && template[i.label].type === 'object') {
|
||||
objectList.push(i);
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
return {
|
||||
ObjectList: objectList,
|
||||
ItemList: itemList,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
handleItemChanged = (target, idx) => {
|
||||
const itemList = [
|
||||
...this.state.ItemList
|
||||
];
|
||||
itemList[idx].value = target.type === 'textarea' ? target.string_array : target.value.toString();
|
||||
const itemList = [...this.state.ItemList];
|
||||
itemList[idx].value =
|
||||
target.type === 'textarea'
|
||||
? target.string_array
|
||||
: target.value.toString();
|
||||
this.setState({
|
||||
ItemList: itemList
|
||||
ItemList: itemList,
|
||||
});
|
||||
};
|
||||
|
||||
handleObjectItemChanged = (target, name, idx) => {
|
||||
const itemList = [
|
||||
...this.state.ObjectLookup[name]
|
||||
];
|
||||
const itemList = [...this.state.ObjectLookup[name]];
|
||||
const objectLookup = {
|
||||
...this.state.ObjectLookup,
|
||||
};
|
||||
|
||||
itemList[idx].value = target.type === 'textarea' ? target.string_array : target.value.toString();
|
||||
itemList[idx].value =
|
||||
target.type === 'textarea'
|
||||
? target.string_array
|
||||
: target.value.toString();
|
||||
objectLookup[name] = itemList;
|
||||
this.setState({
|
||||
ObjectLookup: objectLookup,
|
||||
@@ -157,12 +170,19 @@ class Configuration extends IPCContainer {
|
||||
|
||||
let objectLookup = {};
|
||||
for (const obj of list.ObjectList) {
|
||||
const list2 = this.createItemList(obj.value, this.state.Template[obj.label].template);
|
||||
const list2 = this.createItemList(
|
||||
obj.value,
|
||||
this.state.Template[obj.label].template
|
||||
);
|
||||
objectLookup[obj.label] = list2.ItemList;
|
||||
}
|
||||
|
||||
const isRemoteMount = this.props.remoteSupported &&
|
||||
JSON.parse(objectLookup['RemoteMount'].find(s => s.label === 'IsRemoteMount').value);
|
||||
const isRemoteMount =
|
||||
this.props.remoteSupported &&
|
||||
JSON.parse(
|
||||
objectLookup['RemoteMount'].find((s) => s.label === 'IsRemoteMount')
|
||||
.value
|
||||
);
|
||||
if (isRemoteMount) {
|
||||
for (const obj of list.ObjectList) {
|
||||
if (obj.hide_remote) {
|
||||
@@ -172,15 +192,16 @@ class Configuration extends IPCContainer {
|
||||
}
|
||||
|
||||
const objectLookupCopy = JSON.parse(JSON.stringify(objectLookup));
|
||||
this.setState({
|
||||
IsRemoteMount: isRemoteMount,
|
||||
ItemList: list.ItemList,
|
||||
ObjectLookup: objectLookup,
|
||||
OriginalItemList: itemListCopy,
|
||||
OriginalObjectLookup: objectLookupCopy,
|
||||
}, () => {
|
||||
|
||||
});
|
||||
this.setState(
|
||||
{
|
||||
IsRemoteMount: isRemoteMount,
|
||||
ItemList: list.ItemList,
|
||||
ObjectLookup: objectLookup,
|
||||
OriginalItemList: itemListCopy,
|
||||
OriginalObjectLookup: objectLookupCopy,
|
||||
},
|
||||
() => {}
|
||||
);
|
||||
} else {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
}
|
||||
@@ -188,16 +209,19 @@ class Configuration extends IPCContainer {
|
||||
|
||||
onGetConfigTemplateReply = (event, arg) => {
|
||||
if (arg.data.Success) {
|
||||
this.setState({
|
||||
Template: arg.data.Template,
|
||||
}, () => {
|
||||
this.sendRequest(Constants.IPC_Get_Config, {
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
S3: this.props.DisplayS3Configuration,
|
||||
Version: this.props.version,
|
||||
});
|
||||
});
|
||||
this.setState(
|
||||
{
|
||||
Template: arg.data.Template,
|
||||
},
|
||||
() => {
|
||||
this.sendRequest(Constants.IPC_Get_Config, {
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
S3: this.props.DisplayS3Configuration,
|
||||
Version: this.props.version,
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.props.notifyError(arg.data.Error, false, () => {
|
||||
if (this._isMounted) {
|
||||
@@ -212,77 +236,102 @@ class Configuration extends IPCContainer {
|
||||
};
|
||||
|
||||
saveAndClose = () => {
|
||||
this.setState({
|
||||
Saving: true,
|
||||
}, () => {
|
||||
const changedItems = [];
|
||||
for (const item of this.state.ChangedItems) {
|
||||
changedItems.push({
|
||||
Name: item.label,
|
||||
Value: item.type === 'string_array' ?
|
||||
item.value.join(';') :
|
||||
item.value,
|
||||
});
|
||||
}
|
||||
this.setState(
|
||||
{
|
||||
Saving: true,
|
||||
},
|
||||
() => {
|
||||
const changedItems = [];
|
||||
for (const item of this.state.ChangedItems) {
|
||||
changedItems.push({
|
||||
Name: item.label,
|
||||
Value:
|
||||
item.type === 'string_array' ? item.value.join(';') : item.value,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.state.ChangedObjectLookup) {
|
||||
for (const key of Object.keys(this.state.ChangedObjectLookup)) {
|
||||
for (const item of this.state.ChangedObjectLookup[key]) {
|
||||
changedItems.push({
|
||||
Name: key + '.' + item.label,
|
||||
Value: item.type === 'string_array' ?
|
||||
item.value.join(';') :
|
||||
item.value,
|
||||
});
|
||||
if (this.state.ChangedObjectLookup) {
|
||||
for (const key of Object.keys(this.state.ChangedObjectLookup)) {
|
||||
for (const item of this.state.ChangedObjectLookup[key]) {
|
||||
changedItems.push({
|
||||
Name: key + '.' + item.label,
|
||||
Value:
|
||||
item.type === 'string_array'
|
||||
? item.value.join(';')
|
||||
: item.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.sendRequest(Constants.IPC_Set_Config_Values, {
|
||||
Items: changedItems,
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
S3: this.props.DisplayS3Configuration,
|
||||
Version: this.props.version,
|
||||
});
|
||||
});
|
||||
this.sendRequest(Constants.IPC_Set_Config_Values, {
|
||||
Items: changedItems,
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
S3: this.props.DisplayS3Configuration,
|
||||
Version: this.props.version,
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
showRemoteConfigItem = (item, itemList) => {
|
||||
if (item.advanced &&
|
||||
if (
|
||||
item.advanced &&
|
||||
item.remote &&
|
||||
this.props.remoteSupported &&
|
||||
(item.label !== 'IsRemoteMount')) {
|
||||
const isRemoteMount = JSON.parse(itemList.find(s => s.label === 'IsRemoteMount').value);
|
||||
const enableRemoteMount = !isRemoteMount &&
|
||||
JSON.parse(itemList.find(s => s.label === 'EnableRemoteMount').value);
|
||||
return (item.label === 'RemoteHostNameOrIp') || (item.label === 'RemoteMaxConnections') ?
|
||||
isRemoteMount :
|
||||
(item.label === 'RemoteReceiveTimeoutSeconds') || (item.label === 'RemoteSendTimeoutSeconds') || (item.label === 'RemotePort') || (item.label === 'RemoteToken') ?
|
||||
isRemoteMount || enableRemoteMount :
|
||||
(item.label === 'EnableRemoteMount') ?
|
||||
!isRemoteMount :
|
||||
enableRemoteMount;
|
||||
item.label !== 'IsRemoteMount'
|
||||
) {
|
||||
const isRemoteMount = JSON.parse(
|
||||
itemList.find((s) => s.label === 'IsRemoteMount').value
|
||||
);
|
||||
const enableRemoteMount =
|
||||
!isRemoteMount &&
|
||||
JSON.parse(itemList.find((s) => s.label === 'EnableRemoteMount').value);
|
||||
return item.label === 'RemoteHostNameOrIp' ||
|
||||
item.label === 'RemoteMaxConnections'
|
||||
? isRemoteMount
|
||||
: item.label === 'RemoteReceiveTimeoutSeconds' ||
|
||||
item.label === 'RemoteSendTimeoutSeconds' ||
|
||||
item.label === 'RemotePort' ||
|
||||
item.label === 'RemoteToken'
|
||||
? isRemoteMount || enableRemoteMount
|
||||
: item.label === 'EnableRemoteMount'
|
||||
? !isRemoteMount
|
||||
: enableRemoteMount;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
render() {
|
||||
let confirmSave = null;
|
||||
if ((this.state.ChangedItems.length > 0) || this.state.ChangedObjectLookup) {
|
||||
if (this.state.ChangedItems.length > 0 || this.state.ChangedObjectLookup) {
|
||||
confirmSave = (
|
||||
<Modal>
|
||||
<Box dxStyle={{width: '40vw', padding: 'var(--default_spacing)'}}>
|
||||
<h1 style={{width: '100%', textAlign: 'center'}}>Save Changes?</h1>
|
||||
<table width='100%'>
|
||||
<Box dxStyle={{ width: '40vw', padding: 'var(--default_spacing)' }}>
|
||||
<h1 style={{ width: '100%', textAlign: 'center' }}>
|
||||
Save Changes?
|
||||
</h1>
|
||||
<table width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align='center' width='50%'><Button clicked={this.saveAndClose}
|
||||
disabled={this.state.Saving}>Yes</Button>
|
||||
</td>
|
||||
<td align='center' width='50%'><Button clicked={this.props.hideConfiguration}
|
||||
disabled={this.state.Saving}>No</Button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" width="50%">
|
||||
<Button
|
||||
clicked={this.saveAndClose}
|
||||
disabled={this.state.Saving}
|
||||
>
|
||||
Yes
|
||||
</Button>
|
||||
</td>
|
||||
<td align="center" width="50%">
|
||||
<Button
|
||||
clicked={this.props.hideConfiguration}
|
||||
disabled={this.state.Saving}
|
||||
>
|
||||
No
|
||||
</Button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</Box>
|
||||
@@ -294,84 +343,105 @@ class Configuration extends IPCContainer {
|
||||
|
||||
let objectItems = [];
|
||||
for (const key of Object.keys(this.state.ObjectLookup)) {
|
||||
objectItems.push((
|
||||
objectItems.push(
|
||||
<div key={key}>
|
||||
<h2>{key}</h2>
|
||||
<div>
|
||||
{
|
||||
this.state.ObjectLookup[key].map((k, i) => {
|
||||
const shouldFocus = autoFocus;
|
||||
autoFocus = false;
|
||||
return (
|
||||
(!k.advanced || (this.state.ShowAdvanced && k.advanced && !k.remote) || this.showRemoteConfigItem(k, this.state.ObjectLookup[key])) ?
|
||||
<ConfigurationItem advanced={k.advanced}
|
||||
autoFocus={shouldFocus}
|
||||
changed={e => this.handleObjectItemChanged(e, key, i)}
|
||||
grouping={key}
|
||||
items={this.state.Template[key].template[k.label].items}
|
||||
key={i}
|
||||
label={k.label}
|
||||
readOnly={this.state.IsRemoteMount && ((k.label === 'RemoteHostNameOrIp') || (k.label === 'RemotePort'))}
|
||||
template={this.state.Template[key].template[k.label]}
|
||||
value={k.value}/> :
|
||||
null)
|
||||
})
|
||||
}
|
||||
{this.state.ObjectLookup[key].map((k, i) => {
|
||||
const shouldFocus = autoFocus;
|
||||
autoFocus = false;
|
||||
return !k.advanced ||
|
||||
(this.state.ShowAdvanced && k.advanced && !k.remote) ||
|
||||
this.showRemoteConfigItem(k, this.state.ObjectLookup[key]) ? (
|
||||
<ConfigurationItem
|
||||
advanced={k.advanced}
|
||||
autoFocus={shouldFocus}
|
||||
changed={(e) => this.handleObjectItemChanged(e, key, i)}
|
||||
grouping={key}
|
||||
items={this.state.Template[key].template[k.label].items}
|
||||
key={i}
|
||||
label={k.label}
|
||||
readOnly={
|
||||
this.state.IsRemoteMount &&
|
||||
(k.label === 'RemoteHostNameOrIp' ||
|
||||
k.label === 'RemotePort')
|
||||
}
|
||||
template={this.state.Template[key].template[k.label]}
|
||||
value={k.value}
|
||||
/>
|
||||
) : null;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
const configurationItems = this.state.ItemList
|
||||
.map((k, i) => {
|
||||
const configurationItems = this.state.ItemList.map((k, i) => {
|
||||
const shouldFocus = autoFocus;
|
||||
autoFocus = false;
|
||||
return (
|
||||
((!this.state.IsRemoteMount || !k.hide_remote) && (!k.advanced || (this.state.ShowAdvanced && k.advanced))) ?
|
||||
<ConfigurationItem advanced={k.advanced}
|
||||
autoFocus={shouldFocus}
|
||||
changed={e => this.handleItemChanged(e, i)}
|
||||
grouping={'Settings'}
|
||||
items={this.state.Template[k.label].items}
|
||||
key={i}
|
||||
label={k.label}
|
||||
template={this.state.Template[k.label]}
|
||||
value={k.value}/> :
|
||||
null
|
||||
);
|
||||
return (!this.state.IsRemoteMount || !k.hide_remote) &&
|
||||
(!k.advanced || (this.state.ShowAdvanced && k.advanced)) ? (
|
||||
<ConfigurationItem
|
||||
advanced={k.advanced}
|
||||
autoFocus={shouldFocus}
|
||||
changed={(e) => this.handleItemChanged(e, i)}
|
||||
grouping={'Settings'}
|
||||
items={this.state.Template[k.label].items}
|
||||
key={i}
|
||||
label={k.label}
|
||||
template={this.state.Template[k.label]}
|
||||
value={k.value}
|
||||
/>
|
||||
) : null;
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={'Configuration'}>
|
||||
{confirmSave}
|
||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
||||
<div style={{
|
||||
float: 'right',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
marginTop: '-4px',
|
||||
boxSizing: 'border-box',
|
||||
display: 'block'
|
||||
}}>
|
||||
<a href={'#'}
|
||||
onClick={this.checkSaveRequired}
|
||||
style={{cursor: 'pointer'}}>X</a>
|
||||
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)' }}>
|
||||
<div
|
||||
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'}}>{(
|
||||
this.props.DisplayRemoteConfiguration ?
|
||||
this.props.DisplayConfiguration.substr(6) :
|
||||
this.props.DisplayConfiguration) + ' Configuration '}
|
||||
<h1 style={{ width: '100%', textAlign: 'center' }}>
|
||||
{(this.props.DisplayRemoteConfiguration
|
||||
? this.props.DisplayConfiguration.substr(6)
|
||||
: this.props.DisplayConfiguration) + ' Configuration '}
|
||||
</h1>
|
||||
<div style={{overflowY: 'auto', height: '90%'}}>
|
||||
{this.props.MState.Mounted && (configurationItems.length > 0) ? <Button
|
||||
buttonStyles={{width: 'auto', height: 'auto', marginLeft: 'auto', marginRight: '4px'}}
|
||||
clicked={() => {
|
||||
this.props.displayPinnedManager(true);
|
||||
return false;
|
||||
}}> Pinned File Manager... </Button> : null}
|
||||
<div style={{marginBottom: '4px'}}/>
|
||||
<div style={{ overflowY: 'auto', height: '90%' }}>
|
||||
{this.props.MState.Mounted && configurationItems.length > 0 ? (
|
||||
<Button
|
||||
buttonStyles={{
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
marginLeft: 'auto',
|
||||
marginRight: '4px',
|
||||
}}
|
||||
clicked={() => {
|
||||
this.props.displayPinnedManager(true);
|
||||
return false;
|
||||
}}
|
||||
>
|
||||
Pinned File Manager...
|
||||
</Button>
|
||||
) : null}
|
||||
<div style={{ marginBottom: '4px' }} />
|
||||
{objectItems}
|
||||
{(configurationItems.length > 0) ? <h2>Settings</h2> : null}
|
||||
{configurationItems.length > 0 ? <h2>Settings</h2> : null}
|
||||
{configurationItems}
|
||||
</div>
|
||||
</Box>
|
||||
@@ -380,22 +450,23 @@ class Configuration extends IPCContainer {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
||||
DisplayS3Configuration: state.mounts.DisplayS3Configuration,
|
||||
MState: state.mounts.MountState[state.mounts.DisplayConfiguration],
|
||||
Platform: state.common.Platform,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
displayPinnedManager: display => dispatch(displayPinnedManager(display)),
|
||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||
displayPinnedManager: (display) => dispatch(displayPinnedManager(display)),
|
||||
notifyError: (msg, critical, callback) =>
|
||||
dispatch(notifyError(msg, critical, callback)),
|
||||
hideConfiguration: () => dispatch(displayConfiguration(null, false)),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Configuration);
|
||||
|
||||
@@ -29,7 +29,7 @@ textarea.ConfigurationItemInput {
|
||||
box-sizing: border-box;
|
||||
resize: none;
|
||||
overflow-y: scroll;
|
||||
overflow:-moz-scrollbars-horizontal;
|
||||
overflow: -moz-scrollbars-horizontal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
import React from 'react';
|
||||
import './ConfigurationItem.css';
|
||||
import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
||||
import {connect} from 'react-redux';
|
||||
import {faInfoCircle} from '@fortawesome/free-solid-svg-icons';
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
notifyError,
|
||||
notifyInfo
|
||||
} from '../../../redux/actions/error_actions';
|
||||
import { connect } from 'react-redux';
|
||||
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
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 Password from '../../../containers/UI/Password/Password';
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
notifyError: msg => dispatch(notifyError(msg)),
|
||||
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(null, mapDispatchToProps)(props => {
|
||||
export default connect(
|
||||
null,
|
||||
mapDispatchToProps
|
||||
)((props) => {
|
||||
const handleChanged = (e) => {
|
||||
const target = e.target;
|
||||
if (target.type === 'checkbox') {
|
||||
target.value = e.target.checked ? 'true' : 'false';
|
||||
} else if (target.type === 'textarea') {
|
||||
e.target.string_array = String(e.target.value).replace(/\r\n/g,'\n').split('\n');
|
||||
e.target.string_array = String(e.target.value)
|
||||
.replace(/\r\n/g, '\n')
|
||||
.split('\n');
|
||||
}
|
||||
props.changed(target);
|
||||
};
|
||||
@@ -37,137 +39,186 @@ export default connect(null, mapDispatchToProps)(props => {
|
||||
props.notifyInfo(props.label, description);
|
||||
};
|
||||
|
||||
infoDisplay = <a href={'#'}
|
||||
className={'ConfigurationInfo'}
|
||||
onClick={()=>{displayInfo(); return false;}}><FontAwesomeIcon icon={faInfoCircle}/></a>;
|
||||
infoDisplay = (
|
||||
<a
|
||||
href={'#'}
|
||||
className={'ConfigurationInfo'}
|
||||
onClick={() => {
|
||||
displayInfo();
|
||||
return false;
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faInfoCircle} />
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
let data;
|
||||
switch (props.template.type) {
|
||||
case 'bool':
|
||||
data = <CheckBox changed={handleChanged}
|
||||
checked={props.value}
|
||||
disabled={props.readOnly}
|
||||
autoFocus={props.autoFocus}/>;
|
||||
break;
|
||||
data = (
|
||||
<CheckBox
|
||||
changed={handleChanged}
|
||||
checked={props.value}
|
||||
disabled={props.readOnly}
|
||||
autoFocus={props.autoFocus}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
||||
case 'double':
|
||||
data = <input min={0.0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
step={'0.01'}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={parseFloat(props.value).toFixed(2)}/>;
|
||||
break;
|
||||
data = (
|
||||
<input
|
||||
min={0.0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={(e) => handleChanged(e)}
|
||||
step={'0.01'}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={parseFloat(props.value).toFixed(2)}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
data = <DropDown alt
|
||||
auto
|
||||
autoFocus={props.autoFocus}
|
||||
changed={handleChanged}
|
||||
disabled={props.readOnly}
|
||||
items={props.items}
|
||||
selected={props.value} />;
|
||||
break;
|
||||
data = (
|
||||
<DropDown
|
||||
alt
|
||||
auto
|
||||
autoFocus={props.autoFocus}
|
||||
changed={handleChanged}
|
||||
disabled={props.readOnly}
|
||||
items={props.items}
|
||||
selected={props.value}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
if (props.template.subtype === 'password') {
|
||||
data = (
|
||||
<Password autoFocus={props.autoFocus}
|
||||
changed={s => handleChanged({
|
||||
target: {
|
||||
type: 'password',
|
||||
value: s,
|
||||
},
|
||||
})}
|
||||
disabled={props.readOnly}
|
||||
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
||||
value={props.value} />
|
||||
<Password
|
||||
autoFocus={props.autoFocus}
|
||||
changed={(s) =>
|
||||
handleChanged({
|
||||
target: {
|
||||
type: 'password',
|
||||
value: s,
|
||||
},
|
||||
})
|
||||
}
|
||||
disabled={props.readOnly}
|
||||
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
||||
value={props.value}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
data = (
|
||||
<input onChange={e => handleChanged(e)}
|
||||
autoFocus={props.autoFocus}
|
||||
className={'ConfigurationItemInput'}
|
||||
disabled={props.readOnly}
|
||||
type={'text'}
|
||||
value={props.value}/>
|
||||
data = (
|
||||
<input
|
||||
onChange={(e) => handleChanged(e)}
|
||||
autoFocus={props.autoFocus}
|
||||
className={'ConfigurationItemInput'}
|
||||
disabled={props.readOnly}
|
||||
type={'text'}
|
||||
value={props.value}
|
||||
/>
|
||||
);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'uint8':
|
||||
data = <input max={255}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={props.value}/>;
|
||||
break;
|
||||
data = (
|
||||
<input
|
||||
max={255}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={(e) => handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={props.value}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
||||
case 'uint16':
|
||||
data = <input max={65535}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={props.value}/>;
|
||||
break;
|
||||
data = (
|
||||
<input
|
||||
max={65535}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={(e) => handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={props.value}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
||||
case 'uint32':
|
||||
data = <input max={4294967295}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={props.value}/>;
|
||||
break;
|
||||
data = (
|
||||
<input
|
||||
max={4294967295}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={(e) => handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={props.value}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
||||
case 'uint64':
|
||||
data = <input max={18446744073709551615}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={props.value}/>;
|
||||
break;
|
||||
data = (
|
||||
<input
|
||||
max={18446744073709551615}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={(e) => handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={props.value}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
||||
case 'string_array':
|
||||
data = (
|
||||
<textarea autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
rows={4}
|
||||
cols={36}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
value={props.value.join('\n')} />
|
||||
<textarea
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
rows={4}
|
||||
cols={36}
|
||||
onChange={(e) => handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
value={props.value.join('\n')}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'password':
|
||||
data = (
|
||||
<Password autoFocus={props.autoFocus}
|
||||
changed={s => handleChanged({
|
||||
target: {
|
||||
type: 'password',
|
||||
value: s,
|
||||
},
|
||||
})}
|
||||
disabled={props.readOnly}
|
||||
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
||||
value={props.value} />
|
||||
<Password
|
||||
autoFocus={props.autoFocus}
|
||||
changed={(s) =>
|
||||
handleChanged({
|
||||
target: {
|
||||
type: 'password',
|
||||
value: s,
|
||||
},
|
||||
})
|
||||
}
|
||||
disabled={props.readOnly}
|
||||
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
||||
value={props.value}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
data = <div>{props.value}</div>;
|
||||
@@ -175,13 +226,18 @@ export default connect(null, mapDispatchToProps)(props => {
|
||||
|
||||
return (
|
||||
<div className={'ConfigurationItem'}>
|
||||
<table cellPadding='2'
|
||||
width='100%'>
|
||||
<table cellPadding="2" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
{infoDisplay ?
|
||||
<td width='100%' valign={'top'}>{infoDisplay} {props.label}</td> :
|
||||
<td width='100%' valign={'top'}>{props.label}</td>}
|
||||
{infoDisplay ? (
|
||||
<td width="100%" valign={'top'}>
|
||||
{infoDisplay} {props.label}
|
||||
</td>
|
||||
) : (
|
||||
<td width="100%" valign={'top'}>
|
||||
{props.label}
|
||||
</td>
|
||||
)}
|
||||
<td>{data}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Component} from 'react';
|
||||
import {getIPCRenderer} from '../../utils';
|
||||
import { Component } from 'react';
|
||||
import { getIPCRenderer } from '../../utils.jsx';
|
||||
|
||||
const ipcRenderer = getIPCRenderer();
|
||||
|
||||
@@ -16,7 +16,7 @@ export default class IPCContainer extends Component {
|
||||
}
|
||||
|
||||
this.handlerList = {};
|
||||
};
|
||||
}
|
||||
|
||||
sendRequest = (name, data) => {
|
||||
if (ipcRenderer) {
|
||||
@@ -41,5 +41,4 @@ export default class IPCContainer extends Component {
|
||||
ipcRenderer.on(name, callback);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,4 +16,4 @@ input.MountItemInput {
|
||||
color: var(--text_color);
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import './MountItem.css';
|
||||
import {connect} from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import DropDown from '../../../components/UI/DropDown/DropDown';
|
||||
import Button from '../../../components/UI/Button/Button';
|
||||
import Loader from 'react-loader-spinner';
|
||||
@@ -11,36 +11,41 @@ import RootElem from '../../../components/UI/RootElem/RootElem';
|
||||
import {
|
||||
displayConfiguration,
|
||||
removeMount,
|
||||
setProviderState
|
||||
setProviderState,
|
||||
} from '../../../redux/actions/mount_actions';
|
||||
import {
|
||||
displaySkynetExport,
|
||||
displaySkynetImport,
|
||||
} from '../../../redux/actions/skynet_actions'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import { faTrashAlt} from '@fortawesome/free-solid-svg-icons';
|
||||
} from '../../../redux/actions/skynet_actions';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
MState: state.mounts.MountState[ownProps.provider],
|
||||
Platform: state.common.Platform,
|
||||
PState: state.mounts.ProviderState[ownProps.provider]
|
||||
PState: state.mounts.ProviderState[ownProps.provider],
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
displayConfiguration: (provider, remote, s3) => dispatch(displayConfiguration(provider, remote, s3)),
|
||||
displaySkynetExport: display => dispatch(displaySkynetExport(display)),
|
||||
displaySkynetImport: display => dispatch(displaySkynetImport(display)),
|
||||
removeMount: provider => dispatch(removeMount(provider)),
|
||||
setProviderState: (provider, state) => dispatch(setProviderState(provider, state)),
|
||||
}
|
||||
displayConfiguration: (provider, remote, s3) =>
|
||||
dispatch(displayConfiguration(provider, remote, s3)),
|
||||
displaySkynetExport: (display) => dispatch(displaySkynetExport(display)),
|
||||
displaySkynetImport: (display) => dispatch(displaySkynetImport(display)),
|
||||
removeMount: (provider) => dispatch(removeMount(provider)),
|
||||
setProviderState: (provider, state) =>
|
||||
dispatch(setProviderState(provider, state)),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
const handleAutoMountChanged = e => {
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)((props) => {
|
||||
const handleAutoMountChanged = (e) => {
|
||||
const state = {
|
||||
...props.PState,
|
||||
AutoMount: e.target.checked,
|
||||
@@ -48,7 +53,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
props.setProviderState(props.provider, state);
|
||||
};
|
||||
|
||||
const handleAutoRestartChanged = e => {
|
||||
const handleAutoRestartChanged = (e) => {
|
||||
const state = {
|
||||
...props.PState,
|
||||
AutoRestart: e.target.checked,
|
||||
@@ -57,18 +62,28 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
};
|
||||
|
||||
let secondRow = 6;
|
||||
const pointer = {cursor: props.MState.AllowMount ? 'pointer' : 'no-drop'};
|
||||
const pointer = { cursor: props.MState.AllowMount ? 'pointer' : 'no-drop' };
|
||||
const configButton = (
|
||||
<RootElem colSpan={4}
|
||||
rowSpan={6}>
|
||||
<img alt=''
|
||||
height={'16px'}
|
||||
onClick={props.MState.AllowMount ? () => props.displayConfiguration(props.provider, props.remote, props.s3) : e => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
src={configureImage}
|
||||
style={{padding: 0, border: 0, margin: 0, ...pointer}}
|
||||
width={'16px'}/>
|
||||
<RootElem colSpan={4} rowSpan={6}>
|
||||
<img
|
||||
alt=""
|
||||
height={'16px'}
|
||||
onClick={
|
||||
props.MState.AllowMount
|
||||
? () =>
|
||||
props.displayConfiguration(
|
||||
props.provider,
|
||||
props.remote,
|
||||
props.s3
|
||||
)
|
||||
: (e) => {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
src={configureImage}
|
||||
style={{ padding: 0, border: 0, margin: 0, ...pointer }}
|
||||
width={'16px'}
|
||||
/>
|
||||
</RootElem>
|
||||
);
|
||||
|
||||
@@ -77,80 +92,119 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
if (props.Platform === 'win32') {
|
||||
inputColumnSpan = 20;
|
||||
const index = props.MState.DriveLetters.indexOf(props.PState.MountLocation);
|
||||
inputControls = <DropDown changed={props.changed}
|
||||
colSpan={inputColumnSpan}
|
||||
disabled={!props.MState.AllowMount || props.MState.Mounted}
|
||||
items={props.MState.DriveLetters}
|
||||
row={secondRow}
|
||||
rowSpan={7}
|
||||
selected={index >= 0 ? props.PState.MountLocation : ''}/>;
|
||||
|
||||
inputControls = (
|
||||
<DropDown
|
||||
changed={props.changed}
|
||||
colSpan={inputColumnSpan}
|
||||
disabled={!props.MState.AllowMount || props.MState.Mounted}
|
||||
items={props.MState.DriveLetters}
|
||||
row={secondRow}
|
||||
rowSpan={7}
|
||||
selected={index >= 0 ? props.PState.MountLocation : ''}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
inputColumnSpan = 64;
|
||||
inputControls = [];
|
||||
let key = 0;
|
||||
inputControls.push((
|
||||
<RootElem colSpan={inputColumnSpan - 8}
|
||||
key={'i' + key++}
|
||||
row={secondRow}
|
||||
rowSpan={7}>
|
||||
<input disabled={!props.MState.AllowMount || props.MState.Mounted}
|
||||
maxLength={4096}
|
||||
onChange={props.changed}
|
||||
size={4096}
|
||||
className={'MountItemInput'}
|
||||
type={'text'}
|
||||
value={props.PState.MountLocation}/>
|
||||
inputControls.push(
|
||||
<RootElem
|
||||
colSpan={inputColumnSpan - 8}
|
||||
key={'i' + key++}
|
||||
row={secondRow}
|
||||
rowSpan={7}
|
||||
>
|
||||
<input
|
||||
disabled={!props.MState.AllowMount || props.MState.Mounted}
|
||||
maxLength={4096}
|
||||
onChange={props.changed}
|
||||
size={4096}
|
||||
className={'MountItemInput'}
|
||||
type={'text'}
|
||||
value={props.PState.MountLocation}
|
||||
/>
|
||||
</RootElem>
|
||||
));
|
||||
inputControls.push((
|
||||
<Button clicked={()=>props.browseClicked(props.provider, props.PState.MountLocation)}
|
||||
col={inputColumnSpan - 7}
|
||||
colSpan={7}
|
||||
disabled={props.MState.Mounted || !props.MState.AllowMount}
|
||||
key={'b' + key++}
|
||||
row={secondRow}
|
||||
rowSpan={7}>...</Button>
|
||||
));
|
||||
);
|
||||
inputControls.push(
|
||||
<Button
|
||||
clicked={() =>
|
||||
props.browseClicked(props.provider, props.PState.MountLocation)
|
||||
}
|
||||
col={inputColumnSpan - 7}
|
||||
colSpan={7}
|
||||
disabled={props.MState.Mounted || !props.MState.AllowMount}
|
||||
key={'b' + key++}
|
||||
row={secondRow}
|
||||
rowSpan={7}
|
||||
>
|
||||
...
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
const buttonDisplay = props.MState.AllowMount ?
|
||||
(props.MState.Mounted ? 'Unmount' : 'Mount') :
|
||||
<Loader color={'var(--heading_text_color)'}
|
||||
height={19}
|
||||
type='Circles'
|
||||
width={19}/>;
|
||||
const buttonDisplay = props.MState.AllowMount ? (
|
||||
props.MState.Mounted ? (
|
||||
'Unmount'
|
||||
) : (
|
||||
'Mount'
|
||||
)
|
||||
) : (
|
||||
<Loader
|
||||
color={'var(--heading_text_color)'}
|
||||
height={19}
|
||||
type="Circles"
|
||||
width={19}
|
||||
/>
|
||||
);
|
||||
|
||||
const actionsDisplay = (
|
||||
<Button
|
||||
clicked={() => props.clicked(props.provider, props.remote, props.s3, !props.MState.Mounted, props.PState.MountLocation)}
|
||||
clicked={() =>
|
||||
props.clicked(
|
||||
props.provider,
|
||||
props.remote,
|
||||
props.s3,
|
||||
!props.MState.Mounted,
|
||||
props.PState.MountLocation
|
||||
)
|
||||
}
|
||||
col={inputColumnSpan + 2}
|
||||
colSpan={21}
|
||||
disabled={!props.MState.AllowMount}
|
||||
row={secondRow}
|
||||
rowSpan={7}>
|
||||
rowSpan={7}
|
||||
>
|
||||
{buttonDisplay}
|
||||
</Button>);
|
||||
</Button>
|
||||
);
|
||||
|
||||
const autoMountControl = (
|
||||
<RootElem col={inputColumnSpan + 24}
|
||||
colSpan={28}
|
||||
row={secondRow}
|
||||
rowSpan={7}>
|
||||
<CheckBox changed={handleAutoMountChanged}
|
||||
checked={props.PState.AutoMount}
|
||||
label={'Auto-mount'}/>
|
||||
<RootElem
|
||||
col={inputColumnSpan + 24}
|
||||
colSpan={28}
|
||||
row={secondRow}
|
||||
rowSpan={7}
|
||||
>
|
||||
<CheckBox
|
||||
changed={handleAutoMountChanged}
|
||||
checked={props.PState.AutoMount}
|
||||
label={'Auto-mount'}
|
||||
/>
|
||||
</RootElem>
|
||||
);
|
||||
|
||||
const autoRestartControl = (
|
||||
<RootElem col={inputColumnSpan + 24 + 28}
|
||||
colSpan={24}
|
||||
row={secondRow}
|
||||
rowSpan={7}>
|
||||
<CheckBox changed={handleAutoRestartChanged}
|
||||
checked={props.PState.AutoRestart}
|
||||
label={'Restart'}/>
|
||||
<RootElem
|
||||
col={inputColumnSpan + 24 + 28}
|
||||
colSpan={24}
|
||||
row={secondRow}
|
||||
rowSpan={7}
|
||||
>
|
||||
<CheckBox
|
||||
changed={handleAutoRestartChanged}
|
||||
checked={props.PState.AutoRestart}
|
||||
label={'Restart'}
|
||||
/>
|
||||
</RootElem>
|
||||
);
|
||||
|
||||
@@ -158,7 +212,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
if (props.allowRemove) {
|
||||
const removeDisabled = !props.MState.AllowMount || props.MState.Mounted;
|
||||
const removeStyle = {
|
||||
cursor: removeDisabled ? 'no-drop' : 'pointer'
|
||||
cursor: removeDisabled ? 'no-drop' : 'pointer',
|
||||
};
|
||||
const handleRemoveMount = () => {
|
||||
if (!removeDisabled) {
|
||||
@@ -166,17 +220,18 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
}
|
||||
};
|
||||
removeControl = (
|
||||
<RootElem col={dimensions=>dimensions.columns - 6}
|
||||
row={secondRow + 3}>
|
||||
<a href={'#'}
|
||||
onClick={handleRemoveMount}
|
||||
style={removeStyle}>
|
||||
<FontAwesomeIcon icon={faTrashAlt}/>
|
||||
<RootElem
|
||||
col={(dimensions) => dimensions.columns - 6}
|
||||
row={secondRow + 3}
|
||||
>
|
||||
<a href={'#'} onClick={handleRemoveMount} style={removeStyle}>
|
||||
<FontAwesomeIcon icon={faTrashAlt} />
|
||||
</a>
|
||||
</RootElem>);
|
||||
</RootElem>
|
||||
);
|
||||
}
|
||||
|
||||
const isSkynet = (props.provider === 'Skynet');
|
||||
const isSkynet = props.provider === 'Skynet';
|
||||
return (
|
||||
<div className={'MountItem'}>
|
||||
<Grid noScroll>
|
||||
@@ -185,28 +240,49 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
col={configButton ? 6 : 0}
|
||||
rowSpan={5}
|
||||
colSpan={90}
|
||||
text={props.remote ? props.provider.substr(6) : props.s3 ? props.provider.substr(2) : isSkynet ? props.provider + ' [EXPERIMENTAL]' : props.provider}
|
||||
text={
|
||||
props.remote
|
||||
? props.provider.substr(6)
|
||||
: props.s3
|
||||
? props.provider.substr(2)
|
||||
: isSkynet
|
||||
? props.provider + ' [EXPERIMENTAL]'
|
||||
: props.provider
|
||||
}
|
||||
textAlign={'Left'}
|
||||
type={'Heading2'}/>
|
||||
{(isSkynet && (props.MState.Mounted)) ? (
|
||||
<a href={'#'}
|
||||
col={(configButton ? 24 : 18) + 34}
|
||||
onClick={props.MState.AllowMount ? () => props.displaySkynetExport(true) : e => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
rowSpan={5}
|
||||
style={{...pointer, fontWeight: 'normal'}}>
|
||||
type={'Heading2'}
|
||||
/>
|
||||
{isSkynet && props.MState.Mounted ? (
|
||||
<a
|
||||
href={'#'}
|
||||
col={(configButton ? 24 : 18) + 34}
|
||||
onClick={
|
||||
props.MState.AllowMount
|
||||
? () => props.displaySkynetExport(true)
|
||||
: (e) => {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
rowSpan={5}
|
||||
style={{ ...pointer, fontWeight: 'normal' }}
|
||||
>
|
||||
<u>Export</u>
|
||||
</a>
|
||||
) : null}
|
||||
{(isSkynet && (props.MState.Mounted)) ? (
|
||||
<a href={'#'}
|
||||
col={(configButton ? 24 + 13 : 18 + 13) + 34}
|
||||
onClick={props.MState.AllowMount ? () => props.displaySkynetImport(true) : e => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
rowSpan={5}
|
||||
style={{...pointer, fontWeight: 'normal'}}>
|
||||
{isSkynet && props.MState.Mounted ? (
|
||||
<a
|
||||
href={'#'}
|
||||
col={(configButton ? 24 + 13 : 18 + 13) + 34}
|
||||
onClick={
|
||||
props.MState.AllowMount
|
||||
? () => props.displaySkynetImport(true)
|
||||
: (e) => {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
rowSpan={5}
|
||||
style={{ ...pointer, fontWeight: 'normal' }}
|
||||
>
|
||||
<u>Import</u>
|
||||
</a>
|
||||
) : null}
|
||||
|
||||
@@ -15,4 +15,4 @@
|
||||
box-sizing: border-box;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import AddMount from '../AddMount/AddMount';
|
||||
import Box from '../../components/UI/Box/Box';
|
||||
import Button from '../../components/UI/Button/Button';
|
||||
import {connect} from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import './MountItems.css';
|
||||
import Modal from '../../components/UI/Modal/Modal';
|
||||
import MountItem from './MountItem/MountItem';
|
||||
@@ -14,9 +14,9 @@ import {
|
||||
setBusy,
|
||||
setMounted,
|
||||
setMountState,
|
||||
setProviderState
|
||||
setProviderState,
|
||||
} from '../../redux/actions/mount_actions';
|
||||
import {notifyError} from '../../redux/actions/error_actions';
|
||||
import { notifyError } from '../../redux/actions/error_actions';
|
||||
|
||||
const Constants = require('../../constants');
|
||||
|
||||
@@ -29,7 +29,7 @@ class MountItems extends IPCContainer {
|
||||
RetryItems: {},
|
||||
};
|
||||
|
||||
addMountsBusy = provider => {
|
||||
addMountsBusy = (provider) => {
|
||||
this.props.setMountsBusy(true);
|
||||
this.activeDetections.push(provider);
|
||||
};
|
||||
@@ -43,22 +43,34 @@ class MountItems extends IPCContainer {
|
||||
...this.state.RetryItems,
|
||||
};
|
||||
delete retryItems[provider];
|
||||
this.setState({
|
||||
DisplayRetry: Object.keys(retryItems).length > 0,
|
||||
RetryItems: retryItems,
|
||||
}, () => {
|
||||
if (this.state.DisplayRetry) {
|
||||
this.sendRequest(Constants.IPC_Show_Window);
|
||||
this.setState(
|
||||
{
|
||||
DisplayRetry: Object.keys(retryItems).length > 0,
|
||||
RetryItems: retryItems,
|
||||
},
|
||||
() => {
|
||||
if (this.state.DisplayRetry) {
|
||||
this.sendRequest(Constants.IPC_Show_Window);
|
||||
}
|
||||
stateCallback();
|
||||
}
|
||||
stateCallback();
|
||||
});
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.setRequestHandler(Constants.IPC_Detect_Mount_Reply, this.onDetectMountReply);
|
||||
this.setRequestHandler(Constants.IPC_Mount_Drive_Reply, this.onMountDriveReply);
|
||||
this.setRequestHandler(Constants.IPC_Unmount_Drive_Reply, this.onUnmountDriveReply);
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Detect_Mount_Reply,
|
||||
this.onDetectMountReply
|
||||
);
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Mount_Drive_Reply,
|
||||
this.onMountDriveReply
|
||||
);
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Unmount_Drive_Reply,
|
||||
this.onUnmountDriveReply
|
||||
);
|
||||
this.props.resetMountsState();
|
||||
this.detectMounts();
|
||||
}
|
||||
@@ -73,9 +85,9 @@ class MountItems extends IPCContainer {
|
||||
this.props.resetMountsState();
|
||||
this.activeDetections = [];
|
||||
super.componentWillUnmount();
|
||||
};
|
||||
}
|
||||
|
||||
detectMount = provider => {
|
||||
detectMount = (provider) => {
|
||||
this.addMountsBusy(provider);
|
||||
|
||||
this.sendRequest(Constants.IPC_Detect_Mount, {
|
||||
@@ -86,10 +98,10 @@ class MountItems extends IPCContainer {
|
||||
});
|
||||
};
|
||||
|
||||
detectMounts = ()=> {
|
||||
detectMounts = () => {
|
||||
if (!this.state.DisplayRetry) {
|
||||
const providerList = this.getProviderList();
|
||||
providerList.forEach(provider => {
|
||||
providerList.forEach((provider) => {
|
||||
this.detectMount(provider);
|
||||
});
|
||||
}
|
||||
@@ -98,7 +110,7 @@ class MountItems extends IPCContainer {
|
||||
displayRetryMount = (provider, remote, s3, mountLocation, msg) => {
|
||||
if (!this.state.RetryItems[provider]) {
|
||||
let retryItems = {
|
||||
...this.state.RetryItems
|
||||
...this.state.RetryItems,
|
||||
};
|
||||
retryItems[provider] = {
|
||||
RetrySeconds: 10,
|
||||
@@ -110,28 +122,37 @@ class MountItems extends IPCContainer {
|
||||
};
|
||||
this.props.setMountState(provider, mountState);
|
||||
|
||||
this.setState({
|
||||
DisplayRetry: true,
|
||||
RetryItems: retryItems,
|
||||
}, () => {
|
||||
this.sendRequest(Constants.IPC_Show_Window);
|
||||
this.retryIntervals[provider] = setInterval(() => {
|
||||
let retryItems = {
|
||||
...this.state.RetryItems,
|
||||
};
|
||||
const retrySeconds = retryItems[provider].RetrySeconds - 1;
|
||||
if (retrySeconds === 0) {
|
||||
this.cancelRetryMount(provider, () => {
|
||||
this.handleMountUnMount(provider, remote, s3, true, mountLocation);
|
||||
});
|
||||
} else {
|
||||
retryItems[provider].RetrySeconds = retrySeconds;
|
||||
this.setState({
|
||||
RetryItems: retryItems,
|
||||
});
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
this.setState(
|
||||
{
|
||||
DisplayRetry: true,
|
||||
RetryItems: retryItems,
|
||||
},
|
||||
() => {
|
||||
this.sendRequest(Constants.IPC_Show_Window);
|
||||
this.retryIntervals[provider] = setInterval(() => {
|
||||
let retryItems = {
|
||||
...this.state.RetryItems,
|
||||
};
|
||||
const retrySeconds = retryItems[provider].RetrySeconds - 1;
|
||||
if (retrySeconds === 0) {
|
||||
this.cancelRetryMount(provider, () => {
|
||||
this.handleMountUnMount(
|
||||
provider,
|
||||
remote,
|
||||
s3,
|
||||
true,
|
||||
mountLocation
|
||||
);
|
||||
});
|
||||
} else {
|
||||
retryItems[provider].RetrySeconds = retrySeconds;
|
||||
this.setState({
|
||||
RetryItems: retryItems,
|
||||
});
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -140,7 +161,7 @@ class MountItems extends IPCContainer {
|
||||
Title: provider + ' Mount Location',
|
||||
Location: location,
|
||||
});
|
||||
if (location && (location.length > 0)) {
|
||||
if (location && location.length > 0) {
|
||||
this.handleMountLocationChanged(provider, location);
|
||||
}
|
||||
};
|
||||
@@ -154,25 +175,29 @@ class MountItems extends IPCContainer {
|
||||
};
|
||||
|
||||
handleMountUnMount = (provider, remote, s3, mount, location) => {
|
||||
if (!location || (location.trim().length === 0)) {
|
||||
if (!location || location.trim().length === 0) {
|
||||
this.props.notifyError('Mount location is not set');
|
||||
} else {
|
||||
let allowAction = true;
|
||||
if (mount) {
|
||||
let result = remote || s3 || provider === 'Skynet' ?
|
||||
{Valid: true, Success: true} :
|
||||
this.sendSyncRequest(Constants.IPC_Check_Daemon_Version, {
|
||||
Provider: provider,
|
||||
Remote: remote,
|
||||
S3: s3,
|
||||
Version: this.props.InstalledVersion
|
||||
}).data;
|
||||
let result =
|
||||
remote || s3 || provider === 'Skynet'
|
||||
? { Valid: true, Success: true }
|
||||
: this.sendSyncRequest(Constants.IPC_Check_Daemon_Version, {
|
||||
Provider: provider,
|
||||
Remote: remote,
|
||||
S3: s3,
|
||||
Version: this.props.InstalledVersion,
|
||||
}).data;
|
||||
if (result.Success) {
|
||||
if (result.Valid) {
|
||||
if (this.props.Platform !== 'win32') {
|
||||
result = this.sendSyncRequest(Constants.IPC_Check_Mount_Location, {
|
||||
Location: location,
|
||||
});
|
||||
result = this.sendSyncRequest(
|
||||
Constants.IPC_Check_Mount_Location,
|
||||
{
|
||||
Location: location,
|
||||
}
|
||||
);
|
||||
if (!result.Success) {
|
||||
allowAction = false;
|
||||
this.props.notifyError(result.Error.toString());
|
||||
@@ -180,20 +205,56 @@ class MountItems extends IPCContainer {
|
||||
}
|
||||
} else {
|
||||
allowAction = false;
|
||||
if ((result.Code === new Uint32Array([-1])[0]) || (result.Code === new Uint8Array([-1])[0])) {
|
||||
this.displayRetryMount(provider, remote, s3, location, 'Failed to connect to ' + provider + ' daemon');
|
||||
} else if ((result.Code === new Uint32Array([-3])[0]) || (result.Code === new Uint8Array([-3])[0])) {
|
||||
this.displayRetryMount(provider, remote, s3, location, 'Incompatible ' + provider + ' daemon. Please upgrade ' + provider + '.');
|
||||
if (
|
||||
result.Code === new Uint32Array([-1])[0] ||
|
||||
result.Code === new Uint8Array([-1])[0]
|
||||
) {
|
||||
this.displayRetryMount(
|
||||
provider,
|
||||
remote,
|
||||
s3,
|
||||
location,
|
||||
'Failed to connect to ' + provider + ' daemon'
|
||||
);
|
||||
} else if (
|
||||
result.Code === new Uint32Array([-3])[0] ||
|
||||
result.Code === new Uint8Array([-3])[0]
|
||||
) {
|
||||
this.displayRetryMount(
|
||||
provider,
|
||||
remote,
|
||||
s3,
|
||||
location,
|
||||
'Incompatible ' +
|
||||
provider +
|
||||
' daemon. Please upgrade ' +
|
||||
provider +
|
||||
'.'
|
||||
);
|
||||
} else {
|
||||
this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error);
|
||||
this.displayRetryMount(
|
||||
provider,
|
||||
remote,
|
||||
s3,
|
||||
location,
|
||||
'Version check failed: ' + result.Error
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
allowAction = false;
|
||||
if (this.props.Platform === 'win32') {
|
||||
this.props.notifyError('Failed to launch repertory. Please install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019.');
|
||||
this.props.notifyError(
|
||||
'Failed to launch repertory. Please install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019.'
|
||||
);
|
||||
} else {
|
||||
this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error);
|
||||
this.displayRetryMount(
|
||||
provider,
|
||||
remote,
|
||||
s3,
|
||||
location,
|
||||
'Version check failed: ' + result.Error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,11 +284,13 @@ class MountItems extends IPCContainer {
|
||||
}
|
||||
};
|
||||
|
||||
getProviderList = providersOnly => {
|
||||
const providerList = Constants.PROVIDER_LIST.filter(i => {
|
||||
return ((i === 'Skynet') && this.props.skynetSupported) ||
|
||||
((i === 'ScPrime') && this.props.scPrimeSupported) ||
|
||||
((i === 'Sia') && this.props.siaSupported);
|
||||
getProviderList = (providersOnly) => {
|
||||
const providerList = Constants.PROVIDER_LIST.filter((i) => {
|
||||
return (
|
||||
(i === 'Skynet' && this.props.skynetSupported) ||
|
||||
(i === 'ScPrime' && this.props.scPrimeSupported) ||
|
||||
(i === 'Sia' && this.props.siaSupported)
|
||||
);
|
||||
});
|
||||
|
||||
let remoteList = [];
|
||||
@@ -240,17 +303,12 @@ class MountItems extends IPCContainer {
|
||||
s3List = [...this.props.S3Mounts];
|
||||
}
|
||||
|
||||
return [
|
||||
...providerList,
|
||||
...remoteList,
|
||||
...s3List,
|
||||
];
|
||||
return [...providerList, ...remoteList, ...s3List];
|
||||
};
|
||||
|
||||
hasActiveMount = () => {
|
||||
for (const provider of Object.keys(this.props.MountState)) {
|
||||
if (this.props.MountState[provider].Mounted)
|
||||
return true;
|
||||
if (this.props.MountState[provider].Mounted) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -259,7 +317,11 @@ class MountItems extends IPCContainer {
|
||||
onDetectMountReply = (event, arg) => {
|
||||
const provider = arg.data.Provider;
|
||||
if (!this.state.RetryItems[provider]) {
|
||||
if (arg.data.Success && (!arg.data.Active || (arg.data.Location && (arg.data.Location.length > 0)))) {
|
||||
if (
|
||||
arg.data.Success &&
|
||||
(!arg.data.Active ||
|
||||
(arg.data.Location && arg.data.Location.length > 0))
|
||||
) {
|
||||
const mountState = {
|
||||
AllowMount: true,
|
||||
DriveLetters: arg.data.DriveLetters,
|
||||
@@ -267,7 +329,12 @@ class MountItems extends IPCContainer {
|
||||
};
|
||||
this.props.setMountState(provider, mountState);
|
||||
|
||||
this.updateMountLocation(provider, arg.data.Location, mountState.Mounted, arg.data.DriveLetters);
|
||||
this.updateMountLocation(
|
||||
provider,
|
||||
arg.data.Location,
|
||||
mountState.Mounted,
|
||||
arg.data.DriveLetters
|
||||
);
|
||||
this.props.setAutoMountProcessed(provider, true);
|
||||
this.removeMountsBusy(provider);
|
||||
} else {
|
||||
@@ -284,39 +351,63 @@ class MountItems extends IPCContainer {
|
||||
};
|
||||
|
||||
onUnmountDriveReply = (event, arg) => {
|
||||
if (arg && arg.data && !arg.data.Expected && arg.data.Location && this.props.ProviderState[arg.data.Provider].AutoRestart) {
|
||||
this.displayRetryMount(arg.data.Provider, arg.data.Remote, arg.data.Location);
|
||||
if (
|
||||
arg &&
|
||||
arg.data &&
|
||||
!arg.data.Expected &&
|
||||
arg.data.Location &&
|
||||
this.props.ProviderState[arg.data.Provider].AutoRestart
|
||||
) {
|
||||
this.displayRetryMount(
|
||||
arg.data.Provider,
|
||||
arg.data.Remote,
|
||||
arg.data.Location
|
||||
);
|
||||
} else {
|
||||
this.detectMount(arg.data.Provider);
|
||||
}
|
||||
this.removeMountsBusy(arg.data.Provider);
|
||||
};
|
||||
|
||||
removeMountsBusy = provider => {
|
||||
removeMountsBusy = (provider) => {
|
||||
const idx = this.activeDetections.indexOf(provider);
|
||||
if (idx > -1) {
|
||||
this.activeDetections.splice(idx, 1);
|
||||
}
|
||||
this.props.setMountsBusy((this.activeDetections.length > 0) || this.hasActiveMount());
|
||||
this.props.setMountsBusy(
|
||||
this.activeDetections.length > 0 || this.hasActiveMount()
|
||||
);
|
||||
};
|
||||
|
||||
updateMountLocation = (provider, location, mounted, driveLetters) => {
|
||||
const providerState = this.props.ProviderState[provider];
|
||||
if (location.length === 0) {
|
||||
location = (this.props.Platform === 'win32') ?
|
||||
!providerState.MountLocation || providerState.MountLocation.trim().length === 0 ? driveLetters[0] : providerState.MountLocation :
|
||||
providerState.MountLocation;
|
||||
location =
|
||||
this.props.Platform === 'win32'
|
||||
? !providerState.MountLocation ||
|
||||
providerState.MountLocation.trim().length === 0
|
||||
? driveLetters[0]
|
||||
: providerState.MountLocation
|
||||
: providerState.MountLocation;
|
||||
}
|
||||
|
||||
if (location !== providerState.MountLocation) {
|
||||
this.handleMountLocationChanged(provider, location);
|
||||
}
|
||||
|
||||
if (!this.props.AutoMountProcessed[provider] &&
|
||||
if (
|
||||
!this.props.AutoMountProcessed[provider] &&
|
||||
this.props.ProviderState[provider].AutoMount &&
|
||||
!mounted &&
|
||||
(location.length > 0)) {
|
||||
this.handleMountUnMount(provider, this.props.RemoteMounts.includes(provider), this.props.S3Mounts.includes(provider), true, location);
|
||||
location.length > 0
|
||||
) {
|
||||
this.handleMountUnMount(
|
||||
provider,
|
||||
this.props.RemoteMounts.includes(provider),
|
||||
this.props.S3Mounts.includes(provider),
|
||||
true,
|
||||
location
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -328,104 +419,162 @@ class MountItems extends IPCContainer {
|
||||
for (const provider in this.state.RetryItems) {
|
||||
if (this.state.RetryItems.hasOwnProperty(provider)) {
|
||||
if (this.state.RetryItems[provider].RetryMessage) {
|
||||
retryList.push(<p key={'rl_' + retryList.length}>{this.state.RetryItems[provider].RetryMessage}</p>);
|
||||
retryList.push(
|
||||
<p key={'rl_' + retryList.length}>
|
||||
{this.state.RetryItems[provider].RetryMessage}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
retryList.push(<Button clicked={() => this.cancelRetryMount(provider, () => this.detectMounts())}
|
||||
key={'rl_' + retryList.length}>Cancel {provider} Remount
|
||||
({this.state.RetryItems[provider].RetrySeconds}s)</Button>);
|
||||
retryList.push(
|
||||
<Button
|
||||
clicked={() =>
|
||||
this.cancelRetryMount(provider, () => this.detectMounts())
|
||||
}
|
||||
key={'rl_' + retryList.length}
|
||||
>
|
||||
Cancel {provider} Remount (
|
||||
{this.state.RetryItems[provider].RetrySeconds}s)
|
||||
</Button>
|
||||
);
|
||||
if (++retryCount < Object.keys(this.state.RetryItems).length) {
|
||||
retryList.push(<div style={{paddingTop: 'var(--default_spacing)'}}
|
||||
key={'rl_' + retryList.length}/>);
|
||||
retryList.push(
|
||||
<div
|
||||
style={{ paddingTop: 'var(--default_spacing)' }}
|
||||
key={'rl_' + retryList.length}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retryDisplay = (
|
||||
<Modal>
|
||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)', minWidth: '70vw'}}>
|
||||
<h1 style={{
|
||||
textAlign: 'center',
|
||||
paddingBottom: 'var(--default_spacing)',
|
||||
color: 'var(--text_color_error)'
|
||||
}}>Mount Failed</h1>
|
||||
<Box
|
||||
dxDark
|
||||
dxStyle={{ padding: 'var(--default_spacing)', minWidth: '70vw' }}
|
||||
>
|
||||
<h1
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
paddingBottom: 'var(--default_spacing)',
|
||||
color: 'var(--text_color_error)',
|
||||
}}
|
||||
>
|
||||
Mount Failed
|
||||
</h1>
|
||||
{retryList}
|
||||
</Box>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
let footerItems = [];
|
||||
if (this.props.remoteSupported || this.props.s3Supported) {
|
||||
footerItems.push(<AddMount remoteSupported={this.props.remoteSupported}
|
||||
s3Supported={this.props.s3Supported}
|
||||
key={'hi_' + footerItems.length}/>);
|
||||
footerItems.push(
|
||||
<AddMount
|
||||
remoteSupported={this.props.remoteSupported}
|
||||
s3Supported={this.props.s3Supported}
|
||||
key={'hi_' + footerItems.length}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
footerItems.push(<div key={'hi_' + footerItems.length}
|
||||
style={{height: '27px'}}/>);
|
||||
footerItems.push(
|
||||
<div key={'hi_' + footerItems.length} style={{ height: '27px' }} />
|
||||
);
|
||||
}
|
||||
|
||||
let items = [];
|
||||
for (const provider of this.getProviderList(true)) {
|
||||
items.push((
|
||||
<MountItem allowRemove={false}
|
||||
browseClicked={this.handleBrowseLocation}
|
||||
changed={e => this.handleMountLocationChanged(provider, e.target.value)}
|
||||
clicked={this.handleMountUnMount}
|
||||
key={'it_' + items.length}
|
||||
provider={provider}/>
|
||||
));
|
||||
items.push(<div key={'it_' + items.length}
|
||||
style={{paddingTop: 'var(--default_spacing)'}} />)
|
||||
items.push(
|
||||
<MountItem
|
||||
allowRemove={false}
|
||||
browseClicked={this.handleBrowseLocation}
|
||||
changed={(e) =>
|
||||
this.handleMountLocationChanged(provider, e.target.value)
|
||||
}
|
||||
clicked={this.handleMountUnMount}
|
||||
key={'it_' + items.length}
|
||||
provider={provider}
|
||||
/>
|
||||
);
|
||||
items.push(
|
||||
<div
|
||||
key={'it_' + items.length}
|
||||
style={{ paddingTop: 'var(--default_spacing)' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.remoteSupported) {
|
||||
for (const provider of this.props.RemoteMounts) {
|
||||
items.push((
|
||||
<MountItem allowRemove={true}
|
||||
browseClicked={this.handleBrowseLocation}
|
||||
changed={e => this.handleMountLocationChanged(provider, e.target.value)}
|
||||
clicked={this.handleMountUnMount}
|
||||
key={'it_' + items.length}
|
||||
provider={provider}
|
||||
remote/>
|
||||
));
|
||||
items.push(<div key={'it_' + items.length}
|
||||
style={{paddingTop: 'var(--default_spacing)'}}/>)
|
||||
items.push(
|
||||
<MountItem
|
||||
allowRemove={true}
|
||||
browseClicked={this.handleBrowseLocation}
|
||||
changed={(e) =>
|
||||
this.handleMountLocationChanged(provider, e.target.value)
|
||||
}
|
||||
clicked={this.handleMountUnMount}
|
||||
key={'it_' + items.length}
|
||||
provider={provider}
|
||||
remote
|
||||
/>
|
||||
);
|
||||
items.push(
|
||||
<div
|
||||
key={'it_' + items.length}
|
||||
style={{ paddingTop: 'var(--default_spacing)' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.props.s3Supported) {
|
||||
for (const provider of this.props.S3Mounts) {
|
||||
items.push((
|
||||
<MountItem allowRemove={true}
|
||||
browseClicked={this.handleBrowseLocation}
|
||||
changed={e => this.handleMountLocationChanged(provider, e.target.value)}
|
||||
clicked={this.handleMountUnMount}
|
||||
key={'it_' + items.length}
|
||||
provider={provider}
|
||||
s3/>
|
||||
));
|
||||
items.push(<div key={'it_' + items.length}
|
||||
style={{paddingTop: 'var(--default_spacing)'}}/>)
|
||||
items.push(
|
||||
<MountItem
|
||||
allowRemove={true}
|
||||
browseClicked={this.handleBrowseLocation}
|
||||
changed={(e) =>
|
||||
this.handleMountLocationChanged(provider, e.target.value)
|
||||
}
|
||||
clicked={this.handleMountUnMount}
|
||||
key={'it_' + items.length}
|
||||
provider={provider}
|
||||
s3
|
||||
/>
|
||||
);
|
||||
items.push(
|
||||
<div
|
||||
key={'it_' + items.length}
|
||||
style={{ paddingTop: 'var(--default_spacing)' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
items.splice(items.length - 1, 1);
|
||||
|
||||
return (
|
||||
<div style={{margin: 0, padding: 0}}>
|
||||
<div style={{ margin: 0, padding: 0 }}>
|
||||
{retryDisplay}
|
||||
<div
|
||||
className={this.props.remoteSupported || this.props.s3Supported ? 'MountItemsRemote' : 'MountItems'}>
|
||||
className={
|
||||
this.props.remoteSupported || this.props.s3Supported
|
||||
? 'MountItemsRemote'
|
||||
: 'MountItems'
|
||||
}
|
||||
>
|
||||
{items}
|
||||
</div>
|
||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||
{footerItems}
|
||||
</div>);
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
AutoMountProcessed: state.mounts.AutoMountProcessed,
|
||||
InstalledVersion: state.relver.InstalledVersion,
|
||||
@@ -435,20 +584,25 @@ const mapStateToProps = state => {
|
||||
ProviderState: state.mounts.ProviderState,
|
||||
RemoteMounts: state.mounts.RemoteMounts,
|
||||
S3Mounts: state.mounts.S3Mounts,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||
notifyError: (msg, critical, callback) =>
|
||||
dispatch(notifyError(msg, critical, callback)),
|
||||
resetMountsState: () => dispatch(resetMountsState()),
|
||||
setAllowMount: (provider, allow) => dispatch(setAllowMount(provider, allow)),
|
||||
setAutoMountProcessed: (provider, processed) => dispatch(setAutoMountProcessed(provider, processed)),
|
||||
setAllowMount: (provider, allow) =>
|
||||
dispatch(setAllowMount(provider, allow)),
|
||||
setAutoMountProcessed: (provider, processed) =>
|
||||
dispatch(setAutoMountProcessed(provider, processed)),
|
||||
setMounted: (provider, mounted) => dispatch(setMounted(provider, mounted)),
|
||||
setMountsBusy: busy => dispatch(setBusy(busy)),
|
||||
setMountState: (provider, state) => dispatch(setMountState(provider, state)),
|
||||
setProviderState: (provider, state) => dispatch(setProviderState(provider, state)),
|
||||
}
|
||||
setMountsBusy: (busy) => dispatch(setBusy(busy)),
|
||||
setMountState: (provider, state) =>
|
||||
dispatch(setMountState(provider, state)),
|
||||
setProviderState: (provider, state) =>
|
||||
dispatch(setProviderState(provider, state)),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(MountItems);
|
||||
|
||||
@@ -1,180 +1,227 @@
|
||||
import React from 'react';
|
||||
import './PinnedManager.css';
|
||||
import {connect} from 'react-redux';
|
||||
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 { 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 { 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';
|
||||
|
||||
const Constants = require('../../constants');
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
||||
DisplayS3Configuration: state.mounts.DisplayS3Configuration,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
displayPinnedManager: display => dispatch(displayPinnedManager(display)),
|
||||
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
||||
displayPinnedManager: (display) => dispatch(displayPinnedManager(display)),
|
||||
notifyApplicationBusy: (busy) =>
|
||||
dispatch(notifyApplicationBusy(busy, true)),
|
||||
notifyError: (msg, cb) => dispatch(notifyError(msg, false, cb)),
|
||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCContainer {
|
||||
state = {
|
||||
active_directory: '/',
|
||||
items: [],
|
||||
previous: [],
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(
|
||||
class extends IPCContainer {
|
||||
state = {
|
||||
active_directory: '/',
|
||||
items: [],
|
||||
previous: [],
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.setRequestHandler(Constants.IPC_Get_Directory_Items_Reply, this.onGetDirectoryItemsReply);
|
||||
this.grabDirectoryItems();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
|
||||
grabDirectoryItems = () => {
|
||||
this.sendRequest(Constants.IPC_Get_Directory_Items, {
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
S3: this.props.DisplayS3Configuration,
|
||||
Version: this.props.version,
|
||||
Path: this.state.active_directory,
|
||||
});
|
||||
}
|
||||
|
||||
onGetDirectoryItemsReply = (_, {data}) => {
|
||||
if (data.Success) {
|
||||
const items = data.Items
|
||||
.filter(i => i.path !== '.' && (this.state.active_directory !== '/' || (i.path.substr(0, 1) !== '.')))
|
||||
.map(i => {
|
||||
return {
|
||||
...i,
|
||||
name: i.path === '..' ? i.path : i.path.substr(i.path.lastIndexOf('/') + 1),
|
||||
meta: {
|
||||
...i.meta,
|
||||
pinned: i.meta.pinned === '1',
|
||||
}
|
||||
}
|
||||
});
|
||||
this.setState({
|
||||
items,
|
||||
});
|
||||
} else {
|
||||
this.props.notifyError(data.Error, () => {
|
||||
this.props.displayPinnedManager(false);
|
||||
});
|
||||
componentDidMount() {
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Get_Directory_Items_Reply,
|
||||
this.onGetDirectoryItemsReply
|
||||
);
|
||||
this.grabDirectoryItems();
|
||||
}
|
||||
}
|
||||
|
||||
createDirectory = (name, path, idx, total, item_idx) => {
|
||||
const style = {}
|
||||
if (item_idx + 1 !== total) {
|
||||
style.marginBottom = '4px';
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
return (
|
||||
<div key={'dir_' + idx} style={{...style}}>
|
||||
<Button buttonStyles={{textAlign: 'left'}}
|
||||
clicked={() => {
|
||||
const previous = [...this.state.previous];
|
||||
if (path === '..') {
|
||||
path = previous.pop();
|
||||
} else {
|
||||
previous.push(this.state.active_directory);
|
||||
}
|
||||
this.setState({
|
||||
items: [],
|
||||
active_directory: path,
|
||||
previous,
|
||||
}, () => {
|
||||
this.grabDirectoryItems();
|
||||
});
|
||||
}}>
|
||||
<FontAwesomeIcon icon={faFolder}
|
||||
fixedWidth
|
||||
color={'var(--heading_text_color)'}
|
||||
style={{padding: 0, margin: 0}}/>
|
||||
{name}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
createFile = (name, path, pinned, idx, total, item_idx) => {
|
||||
const style = {textAlign: 'left'}
|
||||
if (item_idx + 1 !== total) {
|
||||
style.marginBottom = '2px';
|
||||
}
|
||||
return (
|
||||
<div key={'file_' + idx} style={{...style}}>
|
||||
<CheckBox checked={pinned}
|
||||
changed={() => {
|
||||
const items = JSON.parse(JSON.stringify(this.state.items));
|
||||
const pinned = items[item_idx].meta.pinned = !items[item_idx].meta.pinned;
|
||||
this.setState({
|
||||
items
|
||||
}, () => {
|
||||
this.sendSyncRequest(Constants.IPC_Set_Pinned, {
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
S3: this.props.DisplayS3Configuration,
|
||||
Version: this.props.version,
|
||||
Path: path,
|
||||
Pinned: pinned,
|
||||
});
|
||||
});
|
||||
}}
|
||||
label={name}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
grabDirectoryItems = () => {
|
||||
this.sendRequest(Constants.IPC_Get_Directory_Items, {
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
S3: this.props.DisplayS3Configuration,
|
||||
Version: this.props.version,
|
||||
Path: this.state.active_directory,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
let idx = 0;
|
||||
return (
|
||||
<Box dxDark dxStyle={{
|
||||
height: 'calc(100vh - (var(--default_spacing) * 4)',
|
||||
padding: 'var(--default_spacing)',
|
||||
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
||||
}}>
|
||||
<div className={'PinnedManager'}>
|
||||
<div className={'PinnedManagerHeading'}>
|
||||
<div className={'PinnedManagerClose'}>
|
||||
<a href={'#'}
|
||||
onClick={() => this.props.displayPinnedManager(false)}
|
||||
style={{cursor: 'pointer', flex: '0'}}>X</a>
|
||||
</div>
|
||||
<h1 style={{width: '100%', textAlign: 'center'}}>{'Pinned File Manager'}</h1>
|
||||
<div className={'PinnedManagerActiveDirectory'}>
|
||||
<b> {this.state.active_directory}</b>
|
||||
</div>
|
||||
</div>
|
||||
<div className={'PinnedManagerItemsOwner'}>
|
||||
<div className={'PinnedManagerItems'}>
|
||||
{
|
||||
this.state.items.map((i, k) => {
|
||||
return i.directory ?
|
||||
this.createDirectory(i.name, i.path, idx++, this.state.items.length, k) :
|
||||
this.createFile(i.name, i.path, i.meta.pinned, idx++, this.state.items.length, k);
|
||||
})
|
||||
onGetDirectoryItemsReply = (_, { data }) => {
|
||||
if (data.Success) {
|
||||
const items = data.Items.filter(
|
||||
(i) =>
|
||||
i.path !== '.' &&
|
||||
(this.state.active_directory !== '/' || i.path.substr(0, 1) !== '.')
|
||||
).map((i) => {
|
||||
return {
|
||||
...i,
|
||||
name:
|
||||
i.path === '..'
|
||||
? i.path
|
||||
: i.path.substr(i.path.lastIndexOf('/') + 1),
|
||||
meta: {
|
||||
...i.meta,
|
||||
pinned: i.meta.pinned === '1',
|
||||
},
|
||||
};
|
||||
});
|
||||
this.setState({
|
||||
items,
|
||||
});
|
||||
} else {
|
||||
this.props.notifyError(data.Error, () => {
|
||||
this.props.displayPinnedManager(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
createDirectory = (name, path, idx, total, item_idx) => {
|
||||
const style = {};
|
||||
if (item_idx + 1 !== total) {
|
||||
style.marginBottom = '4px';
|
||||
}
|
||||
return (
|
||||
<div key={'dir_' + idx} style={{ ...style }}>
|
||||
<Button
|
||||
buttonStyles={{ textAlign: 'left' }}
|
||||
clicked={() => {
|
||||
const previous = [...this.state.previous];
|
||||
if (path === '..') {
|
||||
path = previous.pop();
|
||||
} else {
|
||||
previous.push(this.state.active_directory);
|
||||
}
|
||||
this.setState(
|
||||
{
|
||||
items: [],
|
||||
active_directory: path,
|
||||
previous,
|
||||
},
|
||||
() => {
|
||||
this.grabDirectoryItems();
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faFolder}
|
||||
fixedWidth
|
||||
color={'var(--heading_text_color)'}
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
{name}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
createFile = (name, path, pinned, idx, total, item_idx) => {
|
||||
const style = { textAlign: 'left' };
|
||||
if (item_idx + 1 !== total) {
|
||||
style.marginBottom = '2px';
|
||||
}
|
||||
return (
|
||||
<div key={'file_' + idx} style={{ ...style }}>
|
||||
<CheckBox
|
||||
checked={pinned}
|
||||
changed={() => {
|
||||
const items = JSON.parse(JSON.stringify(this.state.items));
|
||||
const pinned = (items[item_idx].meta.pinned = !items[item_idx]
|
||||
.meta.pinned);
|
||||
this.setState(
|
||||
{
|
||||
items,
|
||||
},
|
||||
() => {
|
||||
this.sendSyncRequest(Constants.IPC_Set_Pinned, {
|
||||
Provider: this.props.DisplayConfiguration,
|
||||
Remote: this.props.DisplayRemoteConfiguration,
|
||||
S3: this.props.DisplayS3Configuration,
|
||||
Version: this.props.version,
|
||||
Path: path,
|
||||
Pinned: pinned,
|
||||
});
|
||||
}
|
||||
);
|
||||
}}
|
||||
label={name}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
let idx = 0;
|
||||
return (
|
||||
<Box
|
||||
dxDark
|
||||
dxStyle={{
|
||||
height: 'calc(100vh - (var(--default_spacing) * 4)',
|
||||
padding: 'var(--default_spacing)',
|
||||
width: 'calc(100vw - (var(--default_spacing) * 4)',
|
||||
}}
|
||||
>
|
||||
<div className={'PinnedManager'}>
|
||||
<div className={'PinnedManagerHeading'}>
|
||||
<div className={'PinnedManagerClose'}>
|
||||
<a
|
||||
href={'#'}
|
||||
onClick={() => this.props.displayPinnedManager(false)}
|
||||
style={{ cursor: 'pointer', flex: '0' }}
|
||||
>
|
||||
X
|
||||
</a>
|
||||
</div>
|
||||
<h1 style={{ width: '100%', textAlign: 'center' }}>
|
||||
{'Pinned File Manager'}
|
||||
</h1>
|
||||
<div className={'PinnedManagerActiveDirectory'}>
|
||||
<b> {this.state.active_directory}</b>
|
||||
</div>
|
||||
</div>
|
||||
<div className={'PinnedManagerItemsOwner'}>
|
||||
<div className={'PinnedManagerItems'}>
|
||||
{this.state.items.map((i, k) => {
|
||||
return i.directory
|
||||
? this.createDirectory(
|
||||
i.name,
|
||||
i.path,
|
||||
idx++,
|
||||
this.state.items.length,
|
||||
k
|
||||
)
|
||||
: this.createFile(
|
||||
i.name,
|
||||
i.path,
|
||||
i.meta.pinned,
|
||||
idx++,
|
||||
this.state.items.length,
|
||||
k
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
)
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
@@ -1,43 +1,50 @@
|
||||
import React from 'react';
|
||||
import './SelectAppPlatform.css';
|
||||
import axios from 'axios';
|
||||
import {connect} from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import * as Constants from '../../constants';
|
||||
import Box from '../../components/UI/Box/Box';
|
||||
import Button from '../../components/UI/Button/Button';
|
||||
import {
|
||||
downloadItem,
|
||||
setAllowDownload
|
||||
setAllowDownload,
|
||||
} from '../../redux/actions/download_actions';
|
||||
import DropDown from '../../components/UI/DropDown/DropDown';
|
||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||
import {notifyError} from '../../redux/actions/error_actions';
|
||||
import {setInstallTestActive} from '../../redux/actions/install_actions';
|
||||
import { notifyError } from '../../redux/actions/error_actions';
|
||||
import { setInstallTestActive } from '../../redux/actions/install_actions';
|
||||
|
||||
class SelectAppPlatform extends IPCContainer {
|
||||
state = {
|
||||
Selected: 0,
|
||||
};
|
||||
|
||||
grabLatestRelease = appPlatform => {
|
||||
const errorHandler = error => {
|
||||
grabLatestRelease = (appPlatform) => {
|
||||
const errorHandler = (error) => {
|
||||
this.props.notifyError(error);
|
||||
this.props.setInstallTestActive(false);
|
||||
this.props.setAllowDownload(false);
|
||||
};
|
||||
axios
|
||||
.get(Constants.RELEASES_URL)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
try {
|
||||
const releases = response.data.Versions.Release[appPlatform];
|
||||
const latestVersion = releases[releases.length - 1];
|
||||
const release = response.data.Locations[appPlatform][latestVersion];
|
||||
this.props.downloadItem(latestVersion + '.zip', Constants.INSTALL_TYPES.TestRelease, release.urls, false, latestVersion, appPlatform);
|
||||
this.props.downloadItem(
|
||||
latestVersion + '.zip',
|
||||
Constants.INSTALL_TYPES.TestRelease,
|
||||
release.urls,
|
||||
false,
|
||||
latestVersion,
|
||||
appPlatform
|
||||
);
|
||||
} catch (error) {
|
||||
errorHandler(error);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
errorHandler(error);
|
||||
});
|
||||
};
|
||||
@@ -45,10 +52,12 @@ class SelectAppPlatform extends IPCContainer {
|
||||
handleTestClicked = () => {
|
||||
this.props.setInstallTestActive(true);
|
||||
this.props.setAllowDownload(true);
|
||||
this.grabLatestRelease(Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected])
|
||||
this.grabLatestRelease(
|
||||
Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected]
|
||||
);
|
||||
};
|
||||
|
||||
handleChanged = e => {
|
||||
handleChanged = (e) => {
|
||||
this.setState({
|
||||
...this.state,
|
||||
Selected: Constants.LINUX_SELECTABLE_PLATFORMS.indexOf(e.target.value),
|
||||
@@ -57,37 +66,49 @@ class SelectAppPlatform extends IPCContainer {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
||||
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)' }}>
|
||||
<h1 className={'SAPHeading'}>Select Linux Platform</h1>
|
||||
<div className={'SAPContent'}>
|
||||
<p>Repertory was unable to detect your Linux distribution. Please select one of the following and click <b>Test</b> to continue:</p>
|
||||
<p>
|
||||
Repertory was unable to detect your Linux distribution. Please
|
||||
select one of the following and click <b>Test</b> to continue:
|
||||
</p>
|
||||
</div>
|
||||
<div className={'SAPActions'}>
|
||||
<DropDown changed={this.handleChanged}
|
||||
disabled={this.props.InstallTestActive}
|
||||
items={Constants.LINUX_SELECTABLE_PLATFORMS}
|
||||
selected={Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected]}/>
|
||||
<Button clicked={this.handleTestClicked}
|
||||
disabled={this.props.InstallTestActive}>Test</Button>
|
||||
<DropDown
|
||||
changed={this.handleChanged}
|
||||
disabled={this.props.InstallTestActive}
|
||||
items={Constants.LINUX_SELECTABLE_PLATFORMS}
|
||||
selected={Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected]}
|
||||
/>
|
||||
<Button
|
||||
clicked={this.handleTestClicked}
|
||||
disabled={this.props.InstallTestActive}
|
||||
>
|
||||
Test
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
InstallTestActive: state.install.InstallTestActive,
|
||||
}
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
downloadItem: (name, type, urls, isWinFSP, testVersion, appPlatform) => dispatch(downloadItem(name, type, urls, isWinFSP, testVersion, appPlatform)),
|
||||
notifyError: msg => dispatch(notifyError(msg)),
|
||||
setAllowDownload: allow => dispatch(setAllowDownload(allow)),
|
||||
setInstallTestActive: active => dispatch(setInstallTestActive(active)),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SelectAppPlatform);
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
downloadItem: (name, type, urls, isWinFSP, testVersion, appPlatform) =>
|
||||
dispatch(
|
||||
downloadItem(name, type, urls, isWinFSP, testVersion, appPlatform)
|
||||
),
|
||||
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||
setAllowDownload: (allow) => dispatch(setAllowDownload(allow)),
|
||||
setInstallTestActive: (active) => dispatch(setInstallTestActive(active)),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SelectAppPlatform);
|
||||
|
||||
@@ -1,59 +1,78 @@
|
||||
import React from 'react';
|
||||
import './SkynetExport.css';
|
||||
import CheckboxTree from 'react-checkbox-tree';
|
||||
import {connect} from 'react-redux';
|
||||
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 { notifyApplicationBusy } from '../../redux/actions/common_actions';
|
||||
import { notifyError, notifyInfo } from '../../redux/actions/error_actions';
|
||||
import Box from '../../components/UI/Box/Box';
|
||||
import {displaySkynetExport} from '../../redux/actions/skynet_actions';
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import { displaySkynetExport } from '../../redux/actions/skynet_actions';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faCheckSquare, faChevronDown,
|
||||
faChevronRight, faFile, faFolder, faFolderOpen,
|
||||
faHSquare, faMinusSquare, faPlusSquare,
|
||||
faSquare
|
||||
faCheckSquare,
|
||||
faChevronDown,
|
||||
faChevronRight,
|
||||
faFile,
|
||||
faFolder,
|
||||
faFolderOpen,
|
||||
faHSquare,
|
||||
faMinusSquare,
|
||||
faPlusSquare,
|
||||
faSquare,
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import Button from '../../components/UI/Button/Button';
|
||||
|
||||
const Constants = require('../../constants');
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
AppBusy: state.common.AppBusy,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
displaySkynetExport: display => dispatch(displaySkynetExport(display)),
|
||||
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
||||
notifyError: msg => dispatch(notifyError(msg)),
|
||||
displaySkynetExport: (display) => dispatch(displaySkynetExport(display)),
|
||||
notifyApplicationBusy: (busy) =>
|
||||
dispatch(notifyApplicationBusy(busy, true)),
|
||||
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCContainer {
|
||||
state = {
|
||||
checked: [],
|
||||
clicked: {},
|
||||
expanded: [],
|
||||
nodes: [],
|
||||
second_stage: false,
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(
|
||||
class extends IPCContainer {
|
||||
state = {
|
||||
checked: [],
|
||||
clicked: {},
|
||||
expanded: [],
|
||||
nodes: [],
|
||||
second_stage: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.setRequestHandler(Constants.IPC_Grab_Skynet_Tree_Reply, this.onGrabSkynetTreeReply);
|
||||
this.setRequestHandler(Constants.IPC_Export_Skylinks_Reply, this.onExportSkylinksReply);
|
||||
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {Version: this.props.version});
|
||||
}
|
||||
componentDidMount() {
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Grab_Skynet_Tree_Reply,
|
||||
this.onGrabSkynetTreeReply
|
||||
);
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Export_Skylinks_Reply,
|
||||
this.onExportSkylinksReply
|
||||
);
|
||||
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {
|
||||
Version: this.props.version,
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
|
||||
createNodes = items => {
|
||||
/*
|
||||
createNodes = (items) => {
|
||||
/*
|
||||
{
|
||||
name: '',
|
||||
path: '',
|
||||
@@ -61,175 +80,269 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCCon
|
||||
children: [],
|
||||
}
|
||||
*/
|
||||
const ret = [];
|
||||
for (const item of items) {
|
||||
const treeItem = {
|
||||
label: item.name,
|
||||
path: item.path,
|
||||
value: item.name === '/' ? 0 : item.path ? item.path : JSON.stringify(item),
|
||||
};
|
||||
const ret = [];
|
||||
for (const item of items) {
|
||||
const treeItem = {
|
||||
label: item.name,
|
||||
path: item.path,
|
||||
value:
|
||||
item.name === '/'
|
||||
? 0
|
||||
: item.path
|
||||
? item.path
|
||||
: JSON.stringify(item),
|
||||
};
|
||||
|
||||
if (item.directory) {
|
||||
treeItem.children = this.createNodes(item.children);
|
||||
if (item.directory) {
|
||||
treeItem.children = this.createNodes(item.children);
|
||||
}
|
||||
|
||||
ret.push(treeItem);
|
||||
}
|
||||
|
||||
ret.push(treeItem);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
handleNavigation = () => {
|
||||
if (this.state.second_stage) {
|
||||
this.props.notifyApplicationBusy(true);
|
||||
this.sendRequest(Constants.IPC_Export_Skylinks, {
|
||||
Version: this.props.version,
|
||||
Paths: this.state.checked,
|
||||
});
|
||||
} else {
|
||||
if (this.state.checked.length === 0) {
|
||||
this.props.notifyError('No files have been checked');
|
||||
} else {
|
||||
this.setState({
|
||||
second_stage: true,
|
||||
handleNavigation = () => {
|
||||
if (this.state.second_stage) {
|
||||
this.props.notifyApplicationBusy(true);
|
||||
this.sendRequest(Constants.IPC_Export_Skylinks, {
|
||||
Version: this.props.version,
|
||||
Paths: this.state.checked,
|
||||
});
|
||||
} else {
|
||||
if (this.state.checked.length === 0) {
|
||||
this.props.notifyError('No files have been checked');
|
||||
} else {
|
||||
this.setState({
|
||||
second_stage: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onExportSkylinksReply = (_, arg) => {
|
||||
this.props.notifyApplicationBusy(false);
|
||||
if (arg.data.Success) {
|
||||
this.setState({
|
||||
checked: [],
|
||||
clicked: {},
|
||||
expanded: [],
|
||||
nodes: [],
|
||||
second_stage: false,
|
||||
}, () => {
|
||||
this.props.notifyInfo('Skylink Exports', '!alternate!!copyable!' + JSON.stringify(arg.data.Result.success, null, 2));
|
||||
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {Version: this.props.version});
|
||||
});
|
||||
} else {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
}
|
||||
}
|
||||
|
||||
onGrabSkynetTreeReply = (_, arg) => {
|
||||
if (arg.data.Success) {
|
||||
this.setState({
|
||||
checked: [],
|
||||
expanded: [0],
|
||||
nodes: this.createNodes(arg.data.Result),
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
checked: [],
|
||||
expanded: [],
|
||||
nodes: [],
|
||||
}, () => {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.AppBusy ? (<div/>) : (
|
||||
<Box dxDark dxStyle={{
|
||||
height: '90vh',
|
||||
padding: 'var(--default_spacing)',
|
||||
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
||||
}}>
|
||||
<div
|
||||
style={{
|
||||
float: 'right',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
marginTop: '-4px',
|
||||
boxSizing: 'border-box',
|
||||
display: 'block'
|
||||
}}>
|
||||
<a href={'#'}
|
||||
onClick={() => this.props.displaySkynetExport(false)}
|
||||
style={{cursor: 'pointer'}}>X</a>
|
||||
</div>
|
||||
<h1
|
||||
className={'SkynetExportHeading'}>{this.state.second_stage ? 'Verify Exports' : 'Export Files'}</h1>
|
||||
<div className={this.state.second_stage ? 'SkynetExportList' : 'SkynetExportTree'}>
|
||||
onExportSkylinksReply = (_, arg) => {
|
||||
this.props.notifyApplicationBusy(false);
|
||||
if (arg.data.Success) {
|
||||
this.setState(
|
||||
{
|
||||
this.state.second_stage ?
|
||||
this.state.checked.map(path => {
|
||||
checked: [],
|
||||
clicked: {},
|
||||
expanded: [],
|
||||
nodes: [],
|
||||
second_stage: false,
|
||||
},
|
||||
() => {
|
||||
this.props.notifyInfo(
|
||||
'Skylink Exports',
|
||||
'!alternate!!copyable!' +
|
||||
JSON.stringify(arg.data.Result.success, null, 2)
|
||||
);
|
||||
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {
|
||||
Version: this.props.version,
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
}
|
||||
};
|
||||
|
||||
onGrabSkynetTreeReply = (_, arg) => {
|
||||
if (arg.data.Success) {
|
||||
this.setState({
|
||||
checked: [],
|
||||
expanded: [0],
|
||||
nodes: this.createNodes(arg.data.Result),
|
||||
});
|
||||
} else {
|
||||
this.setState(
|
||||
{
|
||||
checked: [],
|
||||
expanded: [],
|
||||
nodes: [],
|
||||
},
|
||||
() => {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return this.props.AppBusy ? (
|
||||
<div />
|
||||
) : (
|
||||
<Box
|
||||
dxDark
|
||||
dxStyle={{
|
||||
height: '90vh',
|
||||
padding: 'var(--default_spacing)',
|
||||
width: 'calc(100vw - (var(--default_spacing) * 4)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
float: 'right',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
marginTop: '-4px',
|
||||
boxSizing: 'border-box',
|
||||
display: 'block',
|
||||
}}
|
||||
>
|
||||
<a
|
||||
href={'#'}
|
||||
onClick={() => this.props.displaySkynetExport(false)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
X
|
||||
</a>
|
||||
</div>
|
||||
<h1 className={'SkynetExportHeading'}>
|
||||
{this.state.second_stage ? 'Verify Exports' : 'Export Files'}
|
||||
</h1>
|
||||
<div
|
||||
className={
|
||||
this.state.second_stage ? 'SkynetExportList' : 'SkynetExportTree'
|
||||
}
|
||||
>
|
||||
{this.state.second_stage ? (
|
||||
this.state.checked.map((path) => {
|
||||
return (
|
||||
<input readOnly
|
||||
className={'ConfigurationItemInput'}
|
||||
key={path}
|
||||
style={{width: '100%', marginBottom: 'var(--default_spacing)'}}
|
||||
type={'text'}
|
||||
value={path}/>
|
||||
<input
|
||||
readOnly
|
||||
className={'ConfigurationItemInput'}
|
||||
key={path}
|
||||
style={{
|
||||
width: '100%',
|
||||
marginBottom: 'var(--default_spacing)',
|
||||
}}
|
||||
type={'text'}
|
||||
value={path}
|
||||
/>
|
||||
);
|
||||
})
|
||||
: (
|
||||
<CheckboxTree checked={this.state.checked}
|
||||
expanded={this.state.expanded}
|
||||
expandOnClick
|
||||
showExpandAll
|
||||
icons={{
|
||||
check: <FontAwesomeIcon icon={faCheckSquare} fixedWidth
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
uncheck: <FontAwesomeIcon icon={faSquare} fixedWidth
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
halfCheck: <FontAwesomeIcon icon={faHSquare} fixedWidth
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
expandClose: <FontAwesomeIcon icon={faChevronRight} fixedWidth
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
expandOpen: <FontAwesomeIcon icon={faChevronDown} fixedWidth
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
expandAll: <FontAwesomeIcon icon={faPlusSquare} fixedWidth
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
collapseAll: <FontAwesomeIcon icon={faMinusSquare} fixedWidth
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
parentClose: <FontAwesomeIcon icon={faFolder}
|
||||
fixedWidth
|
||||
color={'var(--heading_text_color)'}
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
parentOpen: <FontAwesomeIcon icon={faFolderOpen}
|
||||
fixedWidth
|
||||
color={'var(--heading_text_color)'}
|
||||
style={{padding: 0, margin: 0}}/>,
|
||||
leaf: <FontAwesomeIcon icon={faFile}
|
||||
fixedWidth
|
||||
color={'var(--text_color)'}
|
||||
style={{padding: 0, margin: 0}}/>
|
||||
}}
|
||||
nodes={this.state.nodes}
|
||||
onClick={clicked => this.setState({clicked})}
|
||||
onCheck={checked => this.setState({checked})}
|
||||
onExpand={expanded => this.setState({expanded})}/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div style={{display: 'flex', justifyContent: 'flex-end'}}>
|
||||
{
|
||||
this.state.second_stage ?
|
||||
<Button buttonStyles={{
|
||||
) : (
|
||||
<CheckboxTree
|
||||
checked={this.state.checked}
|
||||
expanded={this.state.expanded}
|
||||
expandOnClick
|
||||
showExpandAll
|
||||
icons={{
|
||||
check: (
|
||||
<FontAwesomeIcon
|
||||
icon={faCheckSquare}
|
||||
fixedWidth
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
uncheck: (
|
||||
<FontAwesomeIcon
|
||||
icon={faSquare}
|
||||
fixedWidth
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
halfCheck: (
|
||||
<FontAwesomeIcon
|
||||
icon={faHSquare}
|
||||
fixedWidth
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
expandClose: (
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronRight}
|
||||
fixedWidth
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
expandOpen: (
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronDown}
|
||||
fixedWidth
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
expandAll: (
|
||||
<FontAwesomeIcon
|
||||
icon={faPlusSquare}
|
||||
fixedWidth
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
collapseAll: (
|
||||
<FontAwesomeIcon
|
||||
icon={faMinusSquare}
|
||||
fixedWidth
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
parentClose: (
|
||||
<FontAwesomeIcon
|
||||
icon={faFolder}
|
||||
fixedWidth
|
||||
color={'var(--heading_text_color)'}
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
parentOpen: (
|
||||
<FontAwesomeIcon
|
||||
icon={faFolderOpen}
|
||||
fixedWidth
|
||||
color={'var(--heading_text_color)'}
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
leaf: (
|
||||
<FontAwesomeIcon
|
||||
icon={faFile}
|
||||
fixedWidth
|
||||
color={'var(--text_color)'}
|
||||
style={{ padding: 0, margin: 0 }}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
nodes={this.state.nodes}
|
||||
onClick={(clicked) => this.setState({ clicked })}
|
||||
onCheck={(checked) => this.setState({ checked })}
|
||||
onExpand={(expanded) => this.setState({ expanded })}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||
{this.state.second_stage ? (
|
||||
<Button
|
||||
buttonStyles={{
|
||||
height: 'auto',
|
||||
marginLeft: 'var(--default_spacing)',
|
||||
marginTop: 'var(--default_spacing)',
|
||||
width: 'auto',
|
||||
}}
|
||||
clicked={() =>
|
||||
this.setState({
|
||||
second_stage: false,
|
||||
})
|
||||
}
|
||||
>
|
||||
{'Back'}
|
||||
</Button>
|
||||
) : null}
|
||||
<Button
|
||||
buttonStyles={{
|
||||
height: 'auto',
|
||||
marginLeft: 'var(--default_spacing)',
|
||||
marginTop: 'var(--default_spacing)',
|
||||
width: 'auto'
|
||||
}} clicked={() => this.setState({
|
||||
second_stage: false,
|
||||
})}>{'Back'}</Button> :
|
||||
null
|
||||
}
|
||||
<Button buttonStyles={{
|
||||
height: 'auto',
|
||||
marginLeft: 'var(--default_spacing)',
|
||||
marginTop: 'var(--default_spacing)',
|
||||
width: 'auto'
|
||||
}}
|
||||
clicked={this.handleNavigation}>{this.state.second_stage ? 'Export' : 'Next'}</Button>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
width: 'auto',
|
||||
}}
|
||||
clicked={this.handleNavigation}
|
||||
>
|
||||
{this.state.second_stage ? 'Export' : 'Next'}
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
@@ -1,30 +1,36 @@
|
||||
import React from 'react'
|
||||
import './Import.css'
|
||||
import React from 'react';
|
||||
import './Import.css';
|
||||
|
||||
const Import = ({data}) => {
|
||||
const Import = ({ data }) => {
|
||||
return (
|
||||
<div className={'ImportOwner'}>
|
||||
<input readOnly
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{
|
||||
maxWidth: 'calc(33.33% - var(--default_spacing)',
|
||||
marginRight: 'var(--default_spacing)'
|
||||
}}
|
||||
type={'text'}
|
||||
value={data.directory}/>
|
||||
<input readOnly
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))'}}
|
||||
type={'text'}
|
||||
value={data.skylink}/>
|
||||
<input readOnly
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{
|
||||
maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))',
|
||||
marginLeft: 'var(--default_spacing)'
|
||||
}}
|
||||
type={'text'}
|
||||
value={data.token}/>
|
||||
<input
|
||||
readOnly
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{
|
||||
maxWidth: 'calc(33.33% - var(--default_spacing)',
|
||||
marginRight: 'var(--default_spacing)',
|
||||
}}
|
||||
type={'text'}
|
||||
value={data.directory}
|
||||
/>
|
||||
<input
|
||||
readOnly
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{ maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))' }}
|
||||
type={'text'}
|
||||
value={data.skylink}
|
||||
/>
|
||||
<input
|
||||
readOnly
|
||||
className={'ConfigurationItemInput'}
|
||||
style={{
|
||||
maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))',
|
||||
marginLeft: 'var(--default_spacing)',
|
||||
}}
|
||||
type={'text'}
|
||||
value={data.token}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,29 +1,38 @@
|
||||
import React from 'react'
|
||||
import './ImportList.css'
|
||||
import Import from './Import/Import'
|
||||
import React from 'react';
|
||||
import './ImportList.css';
|
||||
import Import from './Import/Import';
|
||||
import Text from '../../../components/UI/Text/Text';
|
||||
|
||||
const ImportList = ({imports_array}) => {
|
||||
const ImportList = ({ imports_array }) => {
|
||||
let key = 0;
|
||||
return (
|
||||
<div>
|
||||
<div className={'ImportListHeader'}>
|
||||
<Text type={'Heading1'} text={'Directory'}
|
||||
style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
||||
<Text type={'Heading1'} text={'Skylink'} style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
||||
<Text type={'Heading1'} text={'Token'} style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
||||
<Text
|
||||
type={'Heading1'}
|
||||
text={'Directory'}
|
||||
style={{ minWidth: '33.33%', maxWidth: '33.33%' }}
|
||||
/>
|
||||
<Text
|
||||
type={'Heading1'}
|
||||
text={'Skylink'}
|
||||
style={{ minWidth: '33.33%', maxWidth: '33.33%' }}
|
||||
/>
|
||||
<Text
|
||||
type={'Heading1'}
|
||||
text={'Token'}
|
||||
style={{ minWidth: '33.33%', maxWidth: '33.33%' }}
|
||||
/>
|
||||
</div>
|
||||
<hr/>
|
||||
<hr />
|
||||
<div className={'ImportListOwner'}>
|
||||
{
|
||||
imports_array.map(data => {
|
||||
return (
|
||||
<div key={'import_' + key++}>
|
||||
<Import data={data}/>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
{imports_array.map((data) => {
|
||||
return (
|
||||
<div key={'import_' + key++}>
|
||||
<Import data={data} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,228 +1,278 @@
|
||||
import React from 'react'
|
||||
import {connect} from 'react-redux';
|
||||
import './SkynetImport.css'
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import './SkynetImport.css';
|
||||
import Box from '../../components/UI/Box/Box';
|
||||
import Button from '../../components/UI/Button/Button';
|
||||
import {displaySkynetImport} from '../../redux/actions/skynet_actions';
|
||||
import ImportList from './ImportList/ImportList'
|
||||
import { displaySkynetImport } from '../../redux/actions/skynet_actions';
|
||||
import ImportList from './ImportList/ImportList';
|
||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
||||
import {
|
||||
notifyError,
|
||||
notifyInfo
|
||||
} from '../../redux/actions/error_actions';
|
||||
import { notifyApplicationBusy } from '../../redux/actions/common_actions';
|
||||
import { notifyError, notifyInfo } from '../../redux/actions/error_actions';
|
||||
|
||||
const Constants = require('../../constants');
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
AppBusy: state.common.AppBusy,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
displaySkynetImport: display => dispatch(displaySkynetImport(display)),
|
||||
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
||||
notifyError: msg => dispatch(notifyError(msg)),
|
||||
displaySkynetImport: (display) => dispatch(displaySkynetImport(display)),
|
||||
notifyApplicationBusy: (busy) =>
|
||||
dispatch(notifyApplicationBusy(busy, true)),
|
||||
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(class SkynetImport extends IPCContainer {
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(
|
||||
class SkynetImport extends IPCContainer {
|
||||
state = {
|
||||
import_text: '',
|
||||
imports_array: [],
|
||||
second_stage: false,
|
||||
};
|
||||
|
||||
state = {
|
||||
import_text: '',
|
||||
imports_array: [],
|
||||
second_stage: false,
|
||||
};
|
||||
componentDidMount() {
|
||||
this.setRequestHandler(
|
||||
Constants.IPC_Import_Skylinks_Reply,
|
||||
this.onImportSkylinksReply
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setRequestHandler(Constants.IPC_Import_Skylinks_Reply, this.onImportSkylinksReply);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
displaySyntax = () => {
|
||||
const msg =
|
||||
'!alternate!To import Skylinks into the root directory, list each Skylink on a new line:\n' +
|
||||
' AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA\n' +
|
||||
' AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg\n' +
|
||||
'\n' +
|
||||
'To import Skylinks into new or existing directories, use the following syntax:\n' +
|
||||
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA"\n' +
|
||||
' directory="/my/sub/dir2",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg"\n' +
|
||||
'\n' +
|
||||
'You can also specify a password if this in an encrypted Repertory Skylink:\n' +
|
||||
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",token="My Password"\n' +
|
||||
' directory="/my/sub/dir",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",token="My Password"\n' +
|
||||
'\n' +
|
||||
'To import Skylinks using JSON syntax:\n' +
|
||||
' [\n' +
|
||||
' {\n' +
|
||||
' "directory": "/",\n' +
|
||||
' "skylink": "AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",\n' +
|
||||
' "token": "My Password"\n' +
|
||||
' },\n' +
|
||||
' {\n' +
|
||||
' "directory": "/my/sub/dir",\n' +
|
||||
' "skylink": "AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",\n' +
|
||||
' "token": "My Password"\n' +
|
||||
' }\n' +
|
||||
' ]';
|
||||
this.props.notifyInfo('Import Syntax', msg);
|
||||
};
|
||||
|
||||
displaySyntax = () => {
|
||||
const msg = '!alternate!To import Skylinks into the root directory, list each Skylink on a new line:\n' +
|
||||
' AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA\n' +
|
||||
' AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg\n' +
|
||||
'\n' +
|
||||
'To import Skylinks into new or existing directories, use the following syntax:\n' +
|
||||
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA"\n' +
|
||||
' directory="/my/sub/dir2",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg"\n' +
|
||||
'\n' +
|
||||
'You can also specify a password if this in an encrypted Repertory Skylink:\n' +
|
||||
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",token="My Password"\n' +
|
||||
' directory="/my/sub/dir",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",token="My Password"\n' +
|
||||
'\n' +
|
||||
'To import Skylinks using JSON syntax:\n' +
|
||||
' [\n' +
|
||||
' {\n' +
|
||||
' "directory": "/",\n' +
|
||||
' "skylink": "AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",\n' +
|
||||
' "token": "My Password"\n' +
|
||||
' },\n' +
|
||||
' {\n' +
|
||||
' "directory": "/my/sub/dir",\n' +
|
||||
' "skylink": "AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",\n' +
|
||||
' "token": "My Password"\n' +
|
||||
' }\n' +
|
||||
' ]';
|
||||
this.props.notifyInfo('Import Syntax', msg)
|
||||
}
|
||||
|
||||
handleNavigation = () => {
|
||||
if (this.state.second_stage) {
|
||||
try {
|
||||
this.props.notifyApplicationBusy(true);
|
||||
this.sendRequest(Constants.IPC_Import_Skylinks, {
|
||||
Version: this.props.version,
|
||||
JsonArray: this.state.imports_array,
|
||||
});
|
||||
} catch (e) {
|
||||
this.props.notifyApplicationBusy(false);
|
||||
this.props.notifyError(e);
|
||||
}
|
||||
} else {
|
||||
const items = this.state.import_text.split('\n');
|
||||
let importsArray = [];
|
||||
try {
|
||||
for (let item of items) {
|
||||
item = item.trim();
|
||||
if (item.startsWith('[')) {
|
||||
importsArray = JSON.parse(this.state.import_text.trim());
|
||||
break;
|
||||
} else if (item.indexOf('=') >= 0) {
|
||||
const parts = item.split(',')
|
||||
let importItem = {
|
||||
directory: '/',
|
||||
skylink: '',
|
||||
token: '',
|
||||
};
|
||||
for (let part of parts) {
|
||||
part = part.trim();
|
||||
const pair = part.split('=');
|
||||
if (pair.length !== 2) {
|
||||
throw new Error('Invalid syntax for import: directory="",skylink="",token=""');
|
||||
}
|
||||
importItem = {
|
||||
...importItem,
|
||||
[pair[0].trim()]: pair[1].trim().replace(/"/g, ''),
|
||||
handleNavigation = () => {
|
||||
if (this.state.second_stage) {
|
||||
try {
|
||||
this.props.notifyApplicationBusy(true);
|
||||
this.sendRequest(Constants.IPC_Import_Skylinks, {
|
||||
Version: this.props.version,
|
||||
JsonArray: this.state.imports_array,
|
||||
});
|
||||
} catch (e) {
|
||||
this.props.notifyApplicationBusy(false);
|
||||
this.props.notifyError(e);
|
||||
}
|
||||
} else {
|
||||
const items = this.state.import_text.split('\n');
|
||||
let importsArray = [];
|
||||
try {
|
||||
for (let item of items) {
|
||||
item = item.trim();
|
||||
if (item.startsWith('[')) {
|
||||
importsArray = JSON.parse(this.state.import_text.trim());
|
||||
break;
|
||||
} else if (item.indexOf('=') >= 0) {
|
||||
const parts = item.split(',');
|
||||
let importItem = {
|
||||
directory: '/',
|
||||
skylink: '',
|
||||
token: '',
|
||||
};
|
||||
for (let part of parts) {
|
||||
part = part.trim();
|
||||
const pair = part.split('=');
|
||||
if (pair.length !== 2) {
|
||||
throw new Error(
|
||||
'Invalid syntax for import: directory="",skylink="",token=""'
|
||||
);
|
||||
}
|
||||
importItem = {
|
||||
...importItem,
|
||||
[pair[0].trim()]: pair[1].trim().replace(/"/g, ''),
|
||||
};
|
||||
}
|
||||
if (!importItem.skylink) {
|
||||
throw new Error(
|
||||
'Invalid syntax for import: directory="",skylink="",token=""'
|
||||
);
|
||||
}
|
||||
importsArray.push(importItem);
|
||||
} else if (item.length > 0) {
|
||||
importsArray.push({
|
||||
directory: '/',
|
||||
skylink: item,
|
||||
});
|
||||
}
|
||||
if (!importItem.skylink) {
|
||||
throw new Error('Invalid syntax for import: directory="",skylink="",token=""');
|
||||
}
|
||||
importsArray.push(importItem);
|
||||
} else if (item.length > 0) {
|
||||
importsArray.push({
|
||||
directory: '/',
|
||||
skylink: item,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (importsArray.length === 0) {
|
||||
throw new Error('Nothing to import');
|
||||
if (importsArray.length === 0) {
|
||||
throw new Error('Nothing to import');
|
||||
}
|
||||
this.setState({
|
||||
imports_array: importsArray,
|
||||
second_stage: true,
|
||||
});
|
||||
} catch (e) {
|
||||
this.props.notifyError(e);
|
||||
}
|
||||
this.setState({
|
||||
imports_array: importsArray,
|
||||
second_stage: true,
|
||||
});
|
||||
} catch (e) {
|
||||
this.props.notifyError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onImportSkylinksReply = (_, arg) => {
|
||||
this.props.notifyApplicationBusy(false);
|
||||
if (arg.data.Success) {
|
||||
const failedImportsArray = this.state.imports_array.filter(i => {
|
||||
return arg.data.Result.failed.includes(i.skylink);
|
||||
});
|
||||
const count = this.state.imports_array.length;
|
||||
this.setState({
|
||||
import_text: failedImportsArray.length > 0 ? JSON.stringify(failedImportsArray, null, 2) : '',
|
||||
imports_array: [],
|
||||
second_stage: false,
|
||||
}, () => {
|
||||
if (failedImportsArray.length > 0) {
|
||||
this.props.notifyError(`Failed to import ${failedImportsArray.length} item(s)`);
|
||||
} else {
|
||||
this.props.notifyInfo('Import Result', `Successfully imported ${count} item(s)`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
}
|
||||
};
|
||||
onImportSkylinksReply = (_, arg) => {
|
||||
this.props.notifyApplicationBusy(false);
|
||||
if (arg.data.Success) {
|
||||
const failedImportsArray = this.state.imports_array.filter((i) => {
|
||||
return arg.data.Result.failed.includes(i.skylink);
|
||||
});
|
||||
const count = this.state.imports_array.length;
|
||||
this.setState(
|
||||
{
|
||||
import_text:
|
||||
failedImportsArray.length > 0
|
||||
? JSON.stringify(failedImportsArray, null, 2)
|
||||
: '',
|
||||
imports_array: [],
|
||||
second_stage: false,
|
||||
},
|
||||
() => {
|
||||
if (failedImportsArray.length > 0) {
|
||||
this.props.notifyError(
|
||||
`Failed to import ${failedImportsArray.length} item(s)`
|
||||
);
|
||||
} else {
|
||||
this.props.notifyInfo(
|
||||
'Import Result',
|
||||
`Successfully imported ${count} item(s)`
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return this.props.AppBusy ? (<div/>) : (
|
||||
<Box dxDark dxStyle={{
|
||||
height: 'auto',
|
||||
padding: 'var(--default_spacing)',
|
||||
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
||||
}}>
|
||||
<div
|
||||
style={{
|
||||
float: 'right',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
marginTop: '-4px',
|
||||
boxSizing: 'border-box',
|
||||
display: 'block'
|
||||
}}>
|
||||
<a href={'#'}
|
||||
onClick={() => this.props.displaySkynetImport(false)}
|
||||
style={{cursor: 'pointer'}}>X</a>
|
||||
</div>
|
||||
<h1
|
||||
className={'SkynetImportHeading'}>{this.state.second_stage ? 'Verify Imports' : 'Import List'}</h1>
|
||||
{
|
||||
this.state.second_stage ? (
|
||||
<ImportList imports_array={this.state.imports_array}/>
|
||||
render() {
|
||||
return this.props.AppBusy ? (
|
||||
<div />
|
||||
) : (
|
||||
<Box
|
||||
dxDark
|
||||
dxStyle={{
|
||||
height: 'auto',
|
||||
padding: 'var(--default_spacing)',
|
||||
width: 'calc(100vw - (var(--default_spacing) * 4)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
float: 'right',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
marginTop: '-4px',
|
||||
boxSizing: 'border-box',
|
||||
display: 'block',
|
||||
}}
|
||||
>
|
||||
<a
|
||||
href={'#'}
|
||||
onClick={() => this.props.displaySkynetImport(false)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
X
|
||||
</a>
|
||||
</div>
|
||||
<h1 className={'SkynetImportHeading'}>
|
||||
{this.state.second_stage ? 'Verify Imports' : 'Import List'}
|
||||
</h1>
|
||||
{this.state.second_stage ? (
|
||||
<ImportList imports_array={this.state.imports_array} />
|
||||
) : (
|
||||
<textarea autoFocus={true}
|
||||
className={'SkynetImportTextArea'}
|
||||
onChange={e => this.setState({
|
||||
import_text: e.target.value,
|
||||
})}
|
||||
value={this.state.import_text}
|
||||
rows={10}/>
|
||||
)
|
||||
}
|
||||
<div className={'SkynetImportButtons'}>
|
||||
<Button
|
||||
buttonStyles={{height: 'auto', marginTop: 'var(--default_spacing)', width: 'auto'}}
|
||||
clicked={this.displaySyntax}>Import Syntax...</Button>
|
||||
<div className={'SkynetActionButtons'}>
|
||||
{
|
||||
this.state.second_stage ?
|
||||
<Button buttonStyles={{
|
||||
<textarea
|
||||
autoFocus={true}
|
||||
className={'SkynetImportTextArea'}
|
||||
onChange={(e) =>
|
||||
this.setState({
|
||||
import_text: e.target.value,
|
||||
})
|
||||
}
|
||||
value={this.state.import_text}
|
||||
rows={10}
|
||||
/>
|
||||
)}
|
||||
<div className={'SkynetImportButtons'}>
|
||||
<Button
|
||||
buttonStyles={{
|
||||
height: 'auto',
|
||||
marginTop: 'var(--default_spacing)',
|
||||
width: 'auto',
|
||||
}}
|
||||
clicked={this.displaySyntax}
|
||||
>
|
||||
Import Syntax...
|
||||
</Button>
|
||||
<div className={'SkynetActionButtons'}>
|
||||
{this.state.second_stage ? (
|
||||
<Button
|
||||
buttonStyles={{
|
||||
height: 'auto',
|
||||
marginLeft: 'var(--default_spacing)',
|
||||
marginTop: 'var(--default_spacing)',
|
||||
width: 'auto',
|
||||
}}
|
||||
clicked={() =>
|
||||
this.setState({
|
||||
second_stage: false,
|
||||
})
|
||||
}
|
||||
>
|
||||
{'Back'}
|
||||
</Button>
|
||||
) : null}
|
||||
<Button
|
||||
buttonStyles={{
|
||||
height: 'auto',
|
||||
marginLeft: 'var(--default_spacing)',
|
||||
marginTop: 'var(--default_spacing)',
|
||||
width: 'auto'
|
||||
}} clicked={() => this.setState({
|
||||
second_stage: false,
|
||||
})}>{'Back'}</Button> :
|
||||
null
|
||||
}
|
||||
<Button buttonStyles={{
|
||||
height: 'auto',
|
||||
marginLeft: 'var(--default_spacing)',
|
||||
marginTop: 'var(--default_spacing)',
|
||||
width: 'auto'
|
||||
}}
|
||||
clicked={this.handleNavigation}>{this.state.second_stage ? 'Import' : 'Next'}</Button>
|
||||
width: 'auto',
|
||||
}}
|
||||
clicked={this.handleNavigation}
|
||||
>
|
||||
{this.state.second_stage ? 'Import' : 'Next'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, {Component} from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import './Password.css';
|
||||
import {faEye, faEyeSlash} from '@fortawesome/free-solid-svg-icons';
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
export default class Password extends Component {
|
||||
state = {
|
||||
@@ -12,14 +12,14 @@ export default class Password extends Component {
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.value || (this.props.value.length === 0)) {
|
||||
if (!this.props.value || this.props.value.length === 0) {
|
||||
this.setState({
|
||||
...this.state,
|
||||
button_text: 'set',
|
||||
password: '',
|
||||
password2: '',
|
||||
show_password: false,
|
||||
})
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
...this.state,
|
||||
@@ -27,7 +27,7 @@ export default class Password extends Component {
|
||||
password: this.props.value,
|
||||
password2: '',
|
||||
show_password: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,20 +48,26 @@ export default class Password extends Component {
|
||||
this.props.changed(this.state.password);
|
||||
this.setState({
|
||||
...this.state,
|
||||
button_text: this.state.password && this.state.password.length > 0 ? 'clear' : 'set',
|
||||
button_text:
|
||||
this.state.password && this.state.password.length > 0
|
||||
? 'clear'
|
||||
: 'set',
|
||||
password2: '',
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
...this.state,
|
||||
button_text: 'set',
|
||||
password: '',
|
||||
password2: '',
|
||||
}, () => {
|
||||
if (this.props.mismatchHandler) {
|
||||
this.props.mismatchHandler();
|
||||
this.setState(
|
||||
{
|
||||
...this.state,
|
||||
button_text: 'set',
|
||||
password: '',
|
||||
password2: '',
|
||||
},
|
||||
() => {
|
||||
if (this.props.mismatchHandler) {
|
||||
this.props.mismatchHandler();
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -79,7 +85,7 @@ export default class Password extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
handlePasswordChanged = e => {
|
||||
handlePasswordChanged = (e) => {
|
||||
if (this.state.button_text === 'set') {
|
||||
this.setState({
|
||||
...this.state,
|
||||
@@ -93,8 +99,11 @@ export default class Password extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
handlePasswordKeyUp = e => {
|
||||
if ((e.keyCode === 13) && ((this.state.button_text === 'confirm') || (this.state.button_text === 'set'))) {
|
||||
handlePasswordKeyUp = (e) => {
|
||||
if (
|
||||
e.keyCode === 13 &&
|
||||
(this.state.button_text === 'confirm' || this.state.button_text === 'set')
|
||||
) {
|
||||
this.handleActionClick();
|
||||
}
|
||||
};
|
||||
@@ -108,28 +117,41 @@ export default class Password extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={'PasswordOwner'} style={{...this.props.style}}>
|
||||
{
|
||||
this.props.readOnly ? null : <a href={'#'}
|
||||
className={'PasswordLink'}
|
||||
onClick={this.handleActionClick}>
|
||||
<div className={'PasswordOwner'} style={{ ...this.props.style }}>
|
||||
{this.props.readOnly ? null : (
|
||||
<a
|
||||
href={'#'}
|
||||
className={'PasswordLink'}
|
||||
onClick={this.handleActionClick}
|
||||
>
|
||||
<u>{this.state.button_text}</u>
|
||||
</a>
|
||||
}
|
||||
<input autoFocus={this.props.autoFocus}
|
||||
readOnly={this.props.readOnly}
|
||||
className={'PasswordInput'}
|
||||
disabled={this.props.readOnly || (this.state.button_text === 'clear')}
|
||||
onChange={this.handlePasswordChanged}
|
||||
onKeyUp={this.handlePasswordKeyUp}
|
||||
type={this.state.show_password ? 'text' : 'password'}
|
||||
value={(this.state.button_text === 'confirm') ? this.state.password2 : this.state.password}/>
|
||||
<a href={'#'}
|
||||
className={'PasswordShowHide'}
|
||||
onClick={this.handleShowHideClick}>
|
||||
<FontAwesomeIcon icon={this.state.show_password ? faEye : faEyeSlash} fixedWidth/>
|
||||
)}
|
||||
<input
|
||||
autoFocus={this.props.autoFocus}
|
||||
readOnly={this.props.readOnly}
|
||||
className={'PasswordInput'}
|
||||
disabled={this.props.readOnly || this.state.button_text === 'clear'}
|
||||
onChange={this.handlePasswordChanged}
|
||||
onKeyUp={this.handlePasswordKeyUp}
|
||||
type={this.state.show_password ? 'text' : 'password'}
|
||||
value={
|
||||
this.state.button_text === 'confirm'
|
||||
? this.state.password2
|
||||
: this.state.password
|
||||
}
|
||||
/>
|
||||
<a
|
||||
href={'#'}
|
||||
className={'PasswordShowHide'}
|
||||
onClick={this.handleShowHideClick}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={this.state.show_password ? faEye : faEyeSlash}
|
||||
fixedWidth
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user