236 lines
8.5 KiB
JavaScript
236 lines
8.5 KiB
JavaScript
import React from 'react';
|
|
import './SkynetExport.css';
|
|
import CheckboxTree from 'react-checkbox-tree';
|
|
import {connect} from 'react-redux';
|
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
|
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
|
import {notifyError, notifyInfo} from '../../redux/actions/error_actions';
|
|
import Box from '../../components/UI/Box/Box';
|
|
import {displaySkynetExport} from '../../redux/actions/skynet_actions';
|
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
|
import {
|
|
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 => {
|
|
return {
|
|
AppBusy: state.common.AppBusy,
|
|
};
|
|
};
|
|
|
|
const mapDispatchToProps = dispatch => {
|
|
return {
|
|
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,
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
createNodes = items => {
|
|
/*
|
|
{
|
|
name: '',
|
|
path: '',
|
|
directory: true/false,
|
|
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),
|
|
};
|
|
|
|
if (item.directory) {
|
|
treeItem.children = this.createNodes(item.children);
|
|
}
|
|
|
|
ret.push(treeItem);
|
|
}
|
|
|
|
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,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
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 style={{overflowX: 'auto', overflowY: 'auto', height: 'calc(90vh - 80px)'}}>
|
|
{
|
|
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}/>
|
|
);
|
|
})
|
|
: (
|
|
<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.handleNavigation}>{this.state.second_stage ? 'Export' : 'Next'}</Button>
|
|
</div>
|
|
</Box>
|
|
);
|
|
}
|
|
});
|