Partial import processing

This commit is contained in:
2020-06-15 12:57:00 -05:00
parent 550e936baa
commit f29ecf5d5d
3 changed files with 111 additions and 47 deletions

View File

@@ -61,9 +61,9 @@ class App extends IPCContainer {
(prevProps.ReleaseVersion !== this.props.ReleaseVersion) ||
(prevProps.VersionLookup !== this.props.VersionLookup)) {
this.props.saveState();
} else if (Object.keys(this.props.ProviderState).filter(k=> {
return this.props.ProviderState[k] !== prevProps.ProviderState[k];
}).length > 0) {
} else if (Object.keys(this.props.ProviderState).filter(k => {
return this.props.ProviderState[k] !== prevProps.ProviderState[k];
}).length > 0) {
this.props.saveState();
}
}
@@ -105,7 +105,7 @@ class App extends IPCContainer {
!missingDependencies &&
!this.props.InstallActive;
const remoteSupported = this.props.LocationsLookup[selectedVersion] &&
const remoteSupported = this.props.LocationsLookup[selectedVersion] &&
this.props.LocationsLookup[selectedVersion].supports_remote;
const gooboxS3Supported = this.props.LocationsLookup[selectedVersion] &&
@@ -155,23 +155,24 @@ class App extends IPCContainer {
const showSkynetImport = !showConfig &&
!showDependencies &&
!this.props.DownloadActive &&
!this.props.DisplayError &&
!this.props.DisplayInfo &&
!showNewReleases &&
!this.props.RebootRequired &&
!this.props.DisplaySelectAppPlatform &&
!showUpgrade &&
this.props.DisplayImport;
const configDisplay = createModalConditionally(showConfig, <Configuration version={selectedVersion} remoteSupported={remoteSupported} />);
const configDisplay = createModalConditionally(showConfig, <Configuration version={selectedVersion}
remoteSupported={remoteSupported}/>);
const confirmDisplay = createModalConditionally(this.props.DisplayConfirmYesNo, <YesNo/>);
const dependencyDisplay = createModalConditionally(showDependencies, <DependencyList/>, false, this.props.InstallActive);
const downloadDisplay = createModalConditionally(this.props.DownloadActive, <DownloadProgress />, false, true);
const dependencyDisplay = createModalConditionally(showDependencies,
<DependencyList/>, false, this.props.InstallActive);
const downloadDisplay = createModalConditionally(this.props.DownloadActive, <DownloadProgress/>, false, true);
const errorDisplay = createModalConditionally(this.props.DisplayError, <ErrorDetails/>, true);
const infoDisplay = createModalConditionally(this.props.DisplayInfo, <InfoDetails/>, true);
const newReleasesDisplay = createModalConditionally(showNewReleases, <NewReleases/>);
const rebootDisplay = createModalConditionally(this.props.RebootRequired, <Reboot />);
const selectAppPlatformDisplay = createModalConditionally(this.props.DisplaySelectAppPlatform, <SelectAppPlatform/>);
const rebootDisplay = createModalConditionally(this.props.RebootRequired, <Reboot/>);
const selectAppPlatformDisplay = createModalConditionally(this.props.DisplaySelectAppPlatform,
<SelectAppPlatform/>);
const upgradeDisplay = createModalConditionally(showUpgrade, <UpgradeUI/>);
const importDisplay = createModalConditionally(showSkynetImport, <SkynetImport/>);
@@ -233,7 +234,7 @@ class App extends IPCContainer {
col={dimensions => dimensions.columns - 6}
colSpan={5}
row={1}
rowSpan={remain=>remain - 1}/>
rowSpan={remain => remain - 1}/>
</Grid>
</Box>
</div>
@@ -294,7 +295,7 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
displaySelectAppPlatform: display => dispatch(displaySelectAppPlatform(display)),
loadReleases: ()=> dispatch(loadReleases()),
loadReleases: () => dispatch(loadReleases()),
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
saveState: () => dispatch(saveState()),
setDismissNewReleasesAvailable: dismiss => dispatch(setDismissNewReleasesAvailable),

View File

@@ -20,7 +20,7 @@ const mapDispatchToProps = dispatch => {
export default connect(mapStateToProps, mapDispatchToProps)(props => {
let msg = props.InfoMessage.message;
const classes = ['InfoDetailsContent'];
if (props.InfoMessage.message.startsWith("!alternate!")) {
if (props.InfoMessage.message.startsWith('!alternate!')) {
classes.push('Alternate');
msg = props.InfoMessage.message.substr('!alternate!'.length)
}

View File

@@ -5,12 +5,16 @@ 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 {notifyInfo} from '../../redux/actions/error_actions';
import {
notifyError,
notifyInfo
} from '../../redux/actions/error_actions';
const mapDispatchToProps = dispatch => {
return {
displaySkynetImport: display => dispatch(displaySkynetImport(display)),
notifyInfo: msg => dispatch(notifyInfo("Import Syntax", msg)),
notifyInfo: msg => dispatch(notifyInfo('Import Syntax', msg)),
notifyError: msg => dispatch(notifyError(msg)),
}
};
@@ -21,40 +25,93 @@ export default connect(null, mapDispatchToProps)(class extends Component {
};
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 to 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 JSON Skylinks, use the following 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" +
" ]";
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 to 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 JSON Skylinks, use the following 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(msg)
}
processNext = () => {
const items = this.state.import_list.split('\n');
let jsonItems = [];
try {
for (let item of items) {
item = item.trim();
if (item.startsWith('[')) {
jsonItems = JSON.parse(this.state.import_list.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=""');
}
jsonItems.push(importItem);
} else if (item.length > 0) {
jsonItems.push({
directory: '/',
skylink: item,
});
}
}
if (jsonItems.length === 0) {
throw new Error('Nothing to import');
}
console.log(jsonItems);
} catch (e) {
this.props.notifyError(e);
}
}
render() {
return (
<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'}}>
<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)}
onClick={() => this.props.displaySkynetImport(false)}
style={{cursor: 'pointer'}}>X</a>
</div>
<h1 className={'SkynetImportHeading'}>Import List</h1>
@@ -65,11 +122,17 @@ export default connect(null, mapDispatchToProps)(class extends Component {
import_list: e.target.value,
})}
value={this.state.import_list}
rows={10} />
rows={10}/>
<div className={'SkynetImportButtons'}>
<Button buttonStyles={{height: 'auto', marginTop: 'var(--default_spacing)', width: 'auto'}} clicked={this.displaySyntax}>Import Syntax...</Button>
<Button buttonStyles={{height: 'auto', marginLeft: 'var(--default_spacing)', marginTop: 'var(--default_spacing)', width: 'auto'}}>Next</Button>
<Button buttonStyles={{height: 'auto', marginTop: 'var(--default_spacing)', width: 'auto'}}
clicked={this.displaySyntax}>Import Syntax...</Button>
<Button buttonStyles={{
height: 'auto',
marginLeft: 'var(--default_spacing)',
marginTop: 'var(--default_spacing)',
width: 'auto'
}} clicked={this.processNext}>Next</Button>
</div>
</Box>
);