ProxyEditorWidget

Source

index.js
import React from 'react';
import PropTypes from 'prop-types';

import style from 'PVWStyle/ReactWidgets/ProxyEditorWidget.mcss';
import PropertyGroup from '../ProxyPropertyGroupWidget';

// --------------------------------------------------------------------------
// Helper methods to update the proxy jsons with the appropriate collapsed
// state of any groups they contain, as it is the reponsibility of the user
// of the the ProxyEditorWidget to provide the complete proxy state.
// --------------------------------------------------------------------------

function checkPropertyList(propList, uiList, nameToToggle) {
propList.forEach((prop, idx) => {
const ui = uiList[idx];
const id = [prop.id, prop.name].join(':');
if (id === nameToToggle) {
prop.value = !prop.value;
}

if (prop.children) {
checkPropertyList(prop.children, ui.children, nameToToggle);
}
});
}

// --------------------------------------------------------------------------

function updateCollapsibleGroups(proxy, nameToToggle) {
checkPropertyList(proxy.properties, proxy.ui, nameToToggle);
}

// --------------------------------------------------------------------------

export default class ProxyEditorWidget extends React.Component {
constructor(props) {
super(props);
this.state = {
advanced: props.advanced,
changeSet: {},
filter: null,
};

// Callback binding
this.toggleAdvanced = this.toggleAdvanced.bind(this);
this.updateFilter = this.updateFilter.bind(this);
this.updateChangeSet = this.updateChangeSet.bind(this);
this.applyChanges = this.applyChanges.bind(this);
this.onCollapseChange = this.onCollapseChange.bind(this);
}

onCollapseChange(name, isOpen, collapseType) {
if (this.props.onCollapseChange) {
this.props.onCollapseChange(name, isOpen, collapseType);
this.setState({ sections: null });
return;
}
const newSections = [];
const sections = this.state.sections || this.props.sections;
for (let i = 0; i < sections.length; i += 1) {
updateCollapsibleGroups(sections[i], name);
newSections[i] = Object.assign({}, sections[i]);
}
this.setState({ sections: newSections });
}

toggleAdvanced() {
const advanced = !this.state.advanced;
this.setState({ advanced });
}

updateFilter(event) {
const filter = event.target.value;
this.setState({ filter });
}

updateChangeSet(change) {
const changeSet = Object.assign({}, this.state.changeSet, change);
if (this.props.autoApply) {
if (this.props.onApply) {
this.props.onApply(changeSet);
}
this.setState({ changeSet: {} });
} else {
this.setState({ changeSet });
}
}

applyChanges() {
if (this.props.onApply) {
this.props.onApply(this.state.changeSet);
}
// Reset changeSet
this.setState({ changeSet: {} });
}

render() {
const changeCount = Object.keys(this.state.changeSet).length;
return (
<div className={style.container}>
<div className={style.toolbar}>
<i
className={
this.state.advanced
? style.activeAdvancedButton
: style.advancedButton
}
onClick={this.toggleAdvanced}
/>
<input
type="text"
placeholder="filter properties..."
onChange={this.updateFilter}
className={style.filter}
/>
{this.props.autoApply ? null : (
<i
className={
changeCount ? style.validateButtonOn : style.validateButton
}
onClick={this.applyChanges}
/>
)}
</div>
<div className={style.contentContainer}>
{this.props.children}
{(this.state.sections || this.props.sections).map((section) => (
<PropertyGroup
key={section.name}
proxy={section}
filter={this.state.filter}
collapsed={section.collapsed}
advanced={this.state.advanced}
onChange={this.updateChangeSet}
onCollapseChange={this.onCollapseChange}
/>
))}
</div>
</div>
);
}
}

ProxyEditorWidget.propTypes = {
advanced: PropTypes.bool,
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
onApply: PropTypes.func,
sections: PropTypes.array,
onCollapseChange: PropTypes.func,
autoApply: PropTypes.bool,
};

ProxyEditorWidget.defaultProps = {
advanced: false,
autoApply: false,
children: null,
onApply: undefined,
onCollapseChange: undefined,
sections: [],
};