Skip to content

Commit

Permalink
Merge pull request #785 from MetaCell/feature/188-range-fields-fix
Browse files Browse the repository at this point in the history
Feature/188 range fields fix
  • Loading branch information
ddelpiano authored Nov 28, 2023
2 parents f899b70 + 55e4da2 commit b444bab
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 55 deletions.
2 changes: 1 addition & 1 deletion webapp/components/general/AdapterComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default class AdapterComponent extends Component {

// Call to conversion function
const newValue = this.props.convertToPython(this.state);
if (newValue != undefined && this.state.value != newValue) {
if (newValue != undefined && this.state.value != newValue && this.props.onChange) {
this.props.onChange(null, null, newValue);
}
}
Expand Down
165 changes: 111 additions & 54 deletions webapp/components/general/NetPyNECoordsRange.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,29 @@ import Utils from '../../Utils';
export default class NetPyNECoordsRange extends Component {
constructor (props) {
super(props);
this.state = { rangeType: undefined };
this.state = { rangeType: undefined, rangeValue: [undefined, undefined] };

this._isMounted = false;
}

triggerUpdate (updateMethod) {
// common strategy when triggering processing of a value change, delay it, every time there is a change we reset
if (this.updateTimer != undefined) {
clearTimeout(this.updateTimer);
}
this.updateTimer = setTimeout(updateMethod, 1000);
}

componentDidMount () {
this._isMounted = true;
this.updateLayout();
}

componentDidUpdate (prevProps, prevState) {
if (this.props.name != prevProps.name) {
this.triggerUpdate(() => {
const message = `netpyne_geppetto.${this.props.model}['${this.props.name}']${(this.props.conds != undefined) ? `['${this.props.conds}']` : ''}`;
Utils
.evalPythonMessage(`[key in ${message} for key in ['${this.props.items[0].value}', '${this.props.items[1].value}']]`)
.then((response) => {
if (response[0] && this._isMounted === true) {
this.setState({ rangeType: this.props.items[0].value });
} else if (response[1] && this._isMounted === true) {
this.setState({ rangeType: this.props.items[1].value });
} else if (this._isMounted === true) {
this.setState({ rangeType: undefined });
}
});
const message = `netpyne_geppetto.${this.props.model}['${this.props.name}']${(this.props.conds != undefined) ? `['${this.props.conds}']` : ''}`;
Utils
.evalPythonMessage(`[key in ${message} for key in ['${this.props.items[0].value}', '${this.props.items[1].value}']]`)
.then((response) => {
if (response[0] && this._isMounted === true) {
this.setState({ rangeType: this.props.items[0].value });
} else if (response[1] && this._isMounted === true) {
this.setState({ rangeType: this.props.items[1].value });
} else if (this._isMounted === true) {
this.setState({ rangeType: undefined });
}
});
} else if (this.props.conds != prevProps.conds) {
this.updateLayout();
Expand All @@ -58,17 +48,34 @@ export default class NetPyNECoordsRange extends Component {

const message = `netpyne_geppetto.${model}['${name}']${(conds !== undefined)
? `['${conds}']` : ''}`;
const evalMessage = `[key in ${message} for key in ['${items[0].value}', '${items[1].value}']]` ;

Utils
.evalPythonMessage(`[key in ${message} for key in ['${items[0].value}', '${items[1].value}']]`)
.then((response) => {
if (response[0] && this._isMounted === true) {
this.setState({ rangeType: items[0].value });
} else if (response[1] && this._isMounted === true) {
this.setState({ rangeType: items[1].value });
} else if (this._isMounted === true) {
this.setState({ rangeType: undefined });
}
});
.evalPythonMessage(evalMessage)
.then((response) => {

let rangeType = undefined ;

if (response[0] && this._isMounted === true) {
rangeType = items[0].value ;
} else if (response[1] && this._isMounted === true) {
rangeType = items[1].value ;
}

this.setState({ rangeType });

if (rangeType)
{
const pythonMessage = `netpyne_geppetto.${model}['${name}']['${conds}']['${this.state.rangeType}']` ;

Utils
.evalPythonMessage(pythonMessage)
.then((response) => {
if (response && response.length > 0 ) {
this.setState({ rangeValue: response });
}});
}
});
}

createMenuItems = () => this.props.items.map((obj) => (
Expand All @@ -85,6 +92,71 @@ export default class NetPyNECoordsRange extends Component {
this._isMounted = false;
}

handleRangeTypeChange(event) {
const {
model,
conds,
name,
} = this.props;

const rangeType = event.target.value ;

const pythonMessageDelAll = `netpyne_geppetto.${model}['${name}']['${conds}'] = {}`;
Utils.execPythonMessage(
pythonMessageDelAll
);

const rangeValue = this.state.rangeValue ;

if (!rangeValue.some(e => e === undefined))
{
const pythonMessage = `netpyne_geppetto.${model}['${name}']['${conds}']['${rangeType}'] = [${rangeValue}]` ;
Utils.execPythonMessage(
pythonMessage
);
}

this.setState({ rangeType})
}

//preConds: pop, cellType, cellModel, x, y, z, xnorm, ynorm, znorm
handleCoordParamChange(index, newValue) {
const {
model,
conds,
name,
} = this.props;

function getOppositeObject(list, givenValue) {
const index = list.findIndex(obj => obj.value === givenValue);

if (index === -1 || list.length !== 2) {
return null;
}
return list[1 - index];
}

if (newValue === '' || (/^\d+$/.test(newValue))) {
const opossiteRangeType = getOppositeObject(this.props.items, this.state.rangeType) ;

if (opossiteRangeType)
{
const pythonMessageDelOpposite = `netpyne_geppetto.${model}['${name}']['${conds}'].pop('${opossiteRangeType.value}', None)`;
Utils.execPythonMessage(
pythonMessageDelOpposite
);
}

const rangeValue = this.state.rangeValue ;
rangeValue[index] = newValue ;
const pythonMessage = `netpyne_geppetto.${model}['${name}']['${conds}']['${this.state.rangeType}'] = [${rangeValue}]` ;
Utils.execPythonMessage(
pythonMessage
);
this.setState({ rangeValue })
}
}

render () {
if (this.props.conds != undefined) {
var meta = `${this.props.model}.${this.props.conds}.${this.props.items[0].value}`;
Expand All @@ -95,42 +167,27 @@ export default class NetPyNECoordsRange extends Component {
}
const min = `${this.props.id}MinRange`;
const max = `${this.props.id}MaxRange`;

const minVal = this.state.rangeValue[0];
const maxVal = this.state.rangeValue[1];

return (
<div>
<NetPyNEField id={meta}>
<SelectField
id={`${this.props.id}Select`}
label="Range type"
value={this.state.rangeType || ''}
onChange={(event) => this.setState({ rangeType: event.target.value })}
onChange={(event) => { this.handleRangeTypeChange(event); }}
>
{this.createMenuItems()}
</SelectField>
</NetPyNEField>
{(this.state.rangeType != undefined)
? (
<Box width="100%" p={1}>
<AdapterComponent
model={path}
convertToPython={(state) => {
if (!state[state.lastUpdated].toString()
.endsWith('.')
&& ((!isNaN(parseFloat(state[min]))) && (!isNaN(parseFloat(state[max]))))) {
return [parseFloat(state[min]), parseFloat(state[max])];
}
}}
convertFromPython={(prevProps, prevState, value) => {
if (value != undefined && prevProps.value != value && value != '') {
const output = {};
output[min] = value[0];
output[max] = value[1];
return output;
}
}}
>
<TextField label="Minimum" id={min} variant="filled" fullWidth />
<TextField label="Maximum" id={max} variant="filled" fullWidth />
</AdapterComponent>
<TextField label="Minimum" id={min} variant="filled" value={minVal} fullWidth onChange={ (e) => { this.handleCoordParamChange(0, parseInt(e.target.value)) } } />
<TextField label="Maximum" id={max} variant="filled" value={maxVal} fullWidth onChange={ (e) => { this.handleCoordParamChange(1, parseInt(e.target.value)) } } />
</Box>
)
: null}
Expand Down

0 comments on commit b444bab

Please sign in to comment.