493 lines
15 KiB
JavaScript
493 lines
15 KiB
JavaScript
import React from 'react';
|
|
import './Configuration.css';
|
|
import { connect } from 'react-redux';
|
|
import { createDismissDisplay } from '../../utils.jsx';
|
|
import Box from '../../components/UI/Box/Box';
|
|
import Button from '../../components/UI/Button/Button';
|
|
import ConfigurationItem from './ConfigurationItem/ConfigurationItem';
|
|
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';
|
|
|
|
const Constants = require('../../constants');
|
|
|
|
class Configuration extends IPCContainer {
|
|
_isMounted = false;
|
|
|
|
state = {
|
|
ChangedItems: [],
|
|
ChangedObjectLookup: null,
|
|
ObjectLookup: {},
|
|
OriginalItemList: [],
|
|
OriginalObjectLookup: {},
|
|
IsRemoteMount: false,
|
|
ItemList: [],
|
|
Saving: false,
|
|
ShowAdvanced: false,
|
|
Template: {},
|
|
};
|
|
|
|
checkItemChanged = (itemA, itemB) => {
|
|
if (itemA.type === 'string_array') {
|
|
if (itemA.value.length !== itemB.value.length) {
|
|
return true;
|
|
}
|
|
return itemA.value.filter((i) => !itemB.value.includes(i)).length !== 0;
|
|
}
|
|
if (itemA.type === 'host_list') {
|
|
if (itemA.value.length !== itemB.value.length) {
|
|
return true;
|
|
}
|
|
return (
|
|
itemA.value.filter((i) =>
|
|
itemB.value.find(
|
|
(j) =>
|
|
j.HostNameOrIp === i.HostNameOrIp &&
|
|
j.ApiPort === i.ApiPort &&
|
|
j.Protocol === i.Protocol &&
|
|
j.TimeoutMs === i.TimeoutMs &&
|
|
j.AgentString === i.AgentString &&
|
|
j.ApiPassword === i.ApiPassword &&
|
|
j.AuthURL === i.AuthURL &&
|
|
j.AuthUser === i.AuthUser &&
|
|
j.AuthPassword === i.AuthPassword
|
|
)
|
|
).length === 0
|
|
);
|
|
}
|
|
return itemA.value !== itemB.value;
|
|
};
|
|
|
|
checkSaveRequired = () => {
|
|
const changedItems = [];
|
|
let i = 0;
|
|
for (const item of this.state.ItemList) {
|
|
if (this.checkItemChanged(this.state.OriginalItemList[i++], item)) {
|
|
changedItems.push(item);
|
|
}
|
|
}
|
|
|
|
let changedObjectLookup = null;
|
|
for (const key of Object.keys(this.state.ObjectLookup)) {
|
|
const changedObjectItems = [];
|
|
let j = 0;
|
|
for (const item of this.state.ObjectLookup[key]) {
|
|
if (
|
|
this.checkItemChanged(this.state.OriginalObjectLookup[key][j++], item)
|
|
) {
|
|
changedObjectItems.push(item);
|
|
}
|
|
}
|
|
|
|
if (changedObjectItems.length > 0) {
|
|
if (changedObjectLookup === null) {
|
|
changedObjectLookup = {};
|
|
}
|
|
changedObjectLookup[key] = changedObjectItems;
|
|
}
|
|
}
|
|
|
|
if (changedItems.length > 0 || changedObjectLookup) {
|
|
this.setState({
|
|
ChangedItems: changedItems,
|
|
ChangedObjectLookup: changedObjectLookup,
|
|
});
|
|
} else {
|
|
this.props.hideConfiguration();
|
|
}
|
|
};
|
|
|
|
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.sendRequest(Constants.IPC_Get_Config_Template, {
|
|
Provider: this.props.DisplayConfiguration,
|
|
Remote: this.props.DisplayRemoteConfiguration,
|
|
S3: this.props.DisplayS3Configuration,
|
|
Version: this.props.version,
|
|
});
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this._isMounted = false;
|
|
super.componentWillUnmount();
|
|
}
|
|
|
|
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 === 'string_array' ||
|
|
template[key].type === 'object')
|
|
? config[key]
|
|
: template[key] && template[key].type === 'host_list'
|
|
? 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.type === 'host_list'
|
|
? target.value
|
|
: target.value.toString();
|
|
this.setState({
|
|
ItemList: itemList,
|
|
});
|
|
};
|
|
|
|
handleObjectItemChanged = (target, name, idx) => {
|
|
const itemList = [...this.state.ObjectLookup[name]];
|
|
const objectLookup = {
|
|
...this.state.ObjectLookup,
|
|
};
|
|
|
|
itemList[idx].value =
|
|
target.type === 'textarea'
|
|
? target.string_array
|
|
: target.type === 'host_list'
|
|
? target.value
|
|
: target.value.toString();
|
|
objectLookup[name] = itemList;
|
|
this.setState({
|
|
ObjectLookup: objectLookup,
|
|
});
|
|
};
|
|
|
|
onGetConfigReply = (_, arg) => {
|
|
if (arg.data.Success) {
|
|
const list = this.createItemList(arg.data.Config, this.state.Template);
|
|
const itemListCopy = JSON.parse(JSON.stringify(list.ItemList));
|
|
|
|
let objectLookup = {};
|
|
for (const obj of list.ObjectList) {
|
|
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
|
|
);
|
|
if (isRemoteMount) {
|
|
for (const obj of list.ObjectList) {
|
|
if (obj.hide_remote) {
|
|
delete objectLookup[obj.label];
|
|
}
|
|
}
|
|
}
|
|
|
|
const objectLookupCopy = JSON.parse(JSON.stringify(objectLookup));
|
|
this.setState(
|
|
{
|
|
IsRemoteMount: isRemoteMount,
|
|
ItemList: list.ItemList,
|
|
ObjectLookup: objectLookup,
|
|
OriginalItemList: itemListCopy,
|
|
OriginalObjectLookup: objectLookupCopy,
|
|
},
|
|
() => {}
|
|
);
|
|
} else {
|
|
this.props.notifyError(arg.data.Error);
|
|
}
|
|
};
|
|
|
|
onGetConfigTemplateReply = (_, 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,
|
|
});
|
|
}
|
|
);
|
|
} else {
|
|
this.props.notifyError(arg.data.Error, false, () => {
|
|
if (this._isMounted) {
|
|
this.props.hideConfiguration();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
onSetConfigValuesReply = () => {
|
|
this.props.hideConfiguration();
|
|
};
|
|
|
|
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.type === 'host_list'
|
|
? JSON.stringify(item.value)
|
|
: 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.type === 'host_list'
|
|
? JSON.stringify(item.value)
|
|
: 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,
|
|
});
|
|
}
|
|
);
|
|
};
|
|
|
|
showRemoteConfigItem = (item, itemList) => {
|
|
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;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
render() {
|
|
let confirmSave = null;
|
|
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%">
|
|
<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>
|
|
</tbody>
|
|
</table>
|
|
</Box>
|
|
</Modal>
|
|
);
|
|
}
|
|
|
|
let autoFocus = true;
|
|
const getAutoFocus = () => {
|
|
return autoFocus;
|
|
};
|
|
const setAutoFocus = (value) => {
|
|
autoFocus = value;
|
|
};
|
|
|
|
let objectItems = [];
|
|
for (const key of Object.keys(this.state.ObjectLookup)) {
|
|
objectItems.push(
|
|
<div key={key}>
|
|
<h2>{key}</h2>
|
|
<div>
|
|
{this.state.ObjectLookup[key].map((k, i) => {
|
|
const shouldFocus = getAutoFocus();
|
|
setAutoFocus(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 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 (
|
|
<div className={'Configuration'}>
|
|
{confirmSave}
|
|
<Box dxDark dxStyle={{ padding: '5px' }}>
|
|
{createDismissDisplay(this.checkSaveRequired)}
|
|
<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' }} />
|
|
{objectItems}
|
|
{configurationItems.length > 0 ? <h2>Settings</h2> : null}
|
|
{configurationItems}
|
|
</div>
|
|
</Box>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
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) => {
|
|
return {
|
|
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);
|