Commit bbd42e2a authored by Jaden DIEFENBAUGH's avatar Jaden DIEFENBAUGH
Browse files

[js][exp] refactor exp editor and tests

parent 1dbb4ab7
...@@ -34,6 +34,7 @@ import type { BeatObject, ParameterValue, BeatEnvironment } from '@helpers/beat' ...@@ -34,6 +34,7 @@ import type { BeatObject, ParameterValue, BeatEnvironment } from '@helpers/beat'
import { changeObjFieldName, sortObject, jsonClone } from '@helpers'; import { changeObjFieldName, sortObject, jsonClone } from '@helpers';
import * as Selectors from '@store/selectors.js'; import * as Selectors from '@store/selectors.js';
import * as Actions from '@store/actions.js';
import ValidSchemaBadge from '../ValidSchemaBadge.jsx'; import ValidSchemaBadge from '../ValidSchemaBadge.jsx';
import CacheInput from '../CacheInput.jsx'; import CacheInput from '../CacheInput.jsx';
...@@ -55,10 +56,10 @@ type Props = { ...@@ -55,10 +56,10 @@ type Props = {
toolchain: BeatObject, toolchain: BeatObject,
environments: { [string]: BeatEnvironment }, environments: { [string]: BeatEnvironment },
saveFunc: (BeatObject) => any, saveFunc: (BeatObject) => any,
updateFunc: (BeatObject) => any,
}; };
type State = { type State = {
cache: any,
/* LockMap: map of which blocks are used in the type inference /* LockMap: map of which blocks are used in the type inference
* This is a per-block mapping of which blocks are used for type inference. * This is a per-block mapping of which blocks are used for type inference.
* There are more references (including some commented-out buttons & such) to * There are more references (including some commented-out buttons & such) to
...@@ -324,7 +325,6 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -324,7 +325,6 @@ export class ExperimentEditor extends React.Component<Props, State> {
} }
state = { state = {
cache: getValidObj(this.props.data, this.props.toolchain, [...this.props.normalBlocks, ...this.props.analyzerBlocks]),
lockMap: genLockMap(this.props.toolchain), lockMap: genLockMap(this.props.toolchain),
activeBlockInfo: { activeBlockInfo: {
name: undefined, name: undefined,
...@@ -333,22 +333,12 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -333,22 +333,12 @@ export class ExperimentEditor extends React.Component<Props, State> {
disableTypeInference: false, disableTypeInference: false,
} }
componentWillReceiveProps (nextProps: Props) {
this.setState({
...this.state,
cache: getValidObj(nextProps.data, nextProps.toolchain, [...this.props.normalBlocks, ...this.props.analyzerBlocks]),
lockMap: genLockMap(nextProps.toolchain),
});
}
setContents = (newContents: any) => { setContents = (newContents: any) => {
this.setState({ this.props.updateFunc({
cache: { ...this.props.data,
...this.state.cache, contents: {
contents: { 'description': this.props.data.contents['description'],
'description': this.state.cache.contents['description'], ...newContents,
...newContents,
}
} }
}); });
} }
...@@ -360,7 +350,6 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -360,7 +350,6 @@ export class ExperimentEditor extends React.Component<Props, State> {
name: blockName name: blockName
}; };
this.setState({ this.setState({
...this.state,
activeBlockInfo: newMBI, activeBlockInfo: newMBI,
}); });
...@@ -385,7 +374,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -385,7 +374,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
// gets parameter data for all the blocks with selected algorithms // gets parameter data for all the blocks with selected algorithms
getParameterObjs = (): any[] => { getParameterObjs = (): any[] => {
const algs = [...this.props.normalBlocks, ...this.props.analyzerBlocks]; const algs = [...this.props.normalBlocks, ...this.props.analyzerBlocks];
return Object.entries({...this.state.cache.contents.blocks, ...this.state.cache.contents.analyzers}) return Object.entries({...this.props.data.contents.blocks, ...this.props.data.contents.analyzers})
.map(([bName, block]) => algs.find(a => a.name === block.algorithm)) .map(([bName, block]) => algs.find(a => a.name === block.algorithm))
.filter(a => a !== null && a !== undefined && a.contents.parameters !== undefined && Object.keys(a.contents.parameters).length > 0) .filter(a => a !== null && a !== undefined && a.contents.parameters !== undefined && Object.keys(a.contents.parameters).length > 0)
.map(a => [a.name, a.contents.parameters]) .map(a => [a.name, a.contents.parameters])
...@@ -399,7 +388,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -399,7 +388,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
getConnectionInferredTypes = (): any => { getConnectionInferredTypes = (): any => {
const isLocked = (name) => !this.state.disableTypeInference && this.state.lockMap[name]; const isLocked = (name) => !this.state.disableTypeInference && this.state.lockMap[name];
const dsTypes = Object.entries(this.state.cache.contents.datasets) const dsTypes = Object.entries(this.props.data.contents.datasets)
.reduce((o, [name, ds]) => { .reduce((o, [name, ds]) => {
const d = this.props.datasets.find(pds => datasetFieldToString(pds) === datasetFieldToString(ds)); const d = this.props.datasets.find(pds => datasetFieldToString(pds) === datasetFieldToString(ds));
const outputs = d ? d.outputs : {}; const outputs = d ? d.outputs : {};
...@@ -409,14 +398,14 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -409,14 +398,14 @@ export class ExperimentEditor extends React.Component<Props, State> {
}; };
}, {}); }, {});
const nTypes = Object.entries(this.state.cache.contents.blocks) const nTypes = Object.entries(this.props.data.contents.blocks)
.filter(([name, block]) => isLocked(name)) .filter(([name, block]) => isLocked(name))
.reduce((o, [name, block]) => ({ .reduce((o, [name, block]) => ({
...o, ...o,
[name]: getBlockIOTypes(block, this.props.normalBlocks), [name]: getBlockIOTypes(block, this.props.normalBlocks),
}), {}); }), {});
const aTypes = Object.entries(this.state.cache.contents.analyzers) const aTypes = Object.entries(this.props.data.contents.analyzers)
.filter(([name, block]) => isLocked(name)) .filter(([name, block]) => isLocked(name))
.reduce((o, [name, block]) => ({ .reduce((o, [name, block]) => ({
...o, ...o,
...@@ -431,8 +420,8 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -431,8 +420,8 @@ export class ExperimentEditor extends React.Component<Props, State> {
}), {}); }), {});
const missingBlocks = Object.entries({ const missingBlocks = Object.entries({
...this.state.cache.contents.blocks, ...this.props.data.contents.blocks,
...this.state.cache.contents.analyzers ...this.props.data.contents.analyzers
}) })
.filter(([name, block]) => !nTypes.hasOwnProperty(name) && !aTypes.hasOwnProperty(name)) .filter(([name, block]) => !nTypes.hasOwnProperty(name) && !aTypes.hasOwnProperty(name))
.reduce((o, [name, block]) => ({...o, [name]: getBlockIOTypes(block, [...this.props.normalBlocks, ...this.props.analyzerBlocks])}), {}); .reduce((o, [name, block]) => ({...o, [name]: getBlockIOTypes(block, [...this.props.normalBlocks, ...this.props.analyzerBlocks])}), {});
...@@ -497,21 +486,21 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -497,21 +486,21 @@ export class ExperimentEditor extends React.Component<Props, State> {
algorithmMissing: string[], algorithmMissing: string[],
ioMissing: string[], ioMissing: string[],
} => { } => {
const dataSourceMissing = Object.entries(this.state.cache.contents.datasets) const dataSourceMissing = Object.entries(this.props.data.contents.datasets)
.filter(([name, ds]) => ds.set === '') .filter(([name, ds]) => ds.set === '')
.map(([name, b]) => name) .map(([name, b]) => name)
; ;
const algorithmMissing = [ const algorithmMissing = [
...Object.entries(this.state.cache.contents.blocks), ...Object.entries(this.props.data.contents.blocks),
...Object.entries(this.state.cache.contents.analyzers), ...Object.entries(this.props.data.contents.analyzers),
].filter(([name, b]) => b.algorithm === '') ].filter(([name, b]) => b.algorithm === '')
.map(([name, b]) => name) .map(([name, b]) => name)
; ;
const ioMissing = [ const ioMissing = [
...Object.entries(this.state.cache.contents.blocks), ...Object.entries(this.props.data.contents.blocks),
...Object.entries(this.state.cache.contents.analyzers), ...Object.entries(this.props.data.contents.analyzers),
].filter(([name, b]) => { ].filter(([name, b]) => {
if(b.algorithm === '') if(b.algorithm === '')
return false; return false;
...@@ -528,7 +517,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -528,7 +517,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
.map(([name, b]) => name) .map(([name, b]) => name)
; ;
const dsTypes = Object.entries(this.state.cache.contents.datasets) const dsTypes = Object.entries(this.props.data.contents.datasets)
.reduce((o, [name, ds]) => { .reduce((o, [name, ds]) => {
const d = this.props.datasets.find(pds => datasetFieldToString(pds) === datasetFieldToString(ds)); const d = this.props.datasets.find(pds => datasetFieldToString(pds) === datasetFieldToString(ds));
const outputs = d ? d.outputs : {}; const outputs = d ? d.outputs : {};
...@@ -538,13 +527,13 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -538,13 +527,13 @@ export class ExperimentEditor extends React.Component<Props, State> {
}; };
}, {}); }, {});
const nTypes = Object.entries(this.state.cache.contents.blocks) const nTypes = Object.entries(this.props.data.contents.blocks)
.reduce((o, [name, block]) => ({ .reduce((o, [name, block]) => ({
...o, ...o,
[name]: getBlockIOTypes(block, this.props.normalBlocks), [name]: getBlockIOTypes(block, this.props.normalBlocks),
}), {}); }), {});
const aTypes = Object.entries(this.state.cache.contents.analyzers) const aTypes = Object.entries(this.props.data.contents.analyzers)
.reduce((o, [name, block]) => ({ .reduce((o, [name, block]) => ({
...o, ...o,
[name]: getBlockIOTypes(block, this.props.analyzerBlocks), [name]: getBlockIOTypes(block, this.props.analyzerBlocks),
...@@ -593,15 +582,15 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -593,15 +582,15 @@ export class ExperimentEditor extends React.Component<Props, State> {
<Input <Input
type='select' type='select'
className='custom-select' className='custom-select'
value={JSON.stringify(sortObject(this.state.cache.contents.datasets))} value={JSON.stringify(sortObject(this.props.data.contents.datasets))}
onChange={e => { onChange={e => {
const str = e.target.value; const str = e.target.value;
//Object.keys(this.state.cache.contents.datasets).map(dsName //Object.keys(this.props.data.contents.datasets).map(dsName
const newDs = JSON.parse(str); const newDs = JSON.parse(str);
console.log(newDs); console.log(newDs);
this.setContents({...this.state.cache.contents, datasets: newDs}); this.setContents({...this.props.data.contents, datasets: newDs});
for(const dataset in this.state.cache.contents.datasets){ for(const dataset in this.props.data.contents.datasets){
this.setLockMap(dataset, true); this.setLockMap(dataset, true);
} }
}} }}
...@@ -622,7 +611,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -622,7 +611,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
}, {}) }, {})
) )
.map(([dbProtStr, sets]) => { .map(([dbProtStr, sets]) => {
const enoughSets = sets.length == Object.keys(this.state.cache.contents.datasets).length; const enoughSets = sets.length == Object.keys(this.props.data.contents.datasets).length;
if(!enoughSets) if(!enoughSets)
return [dbProtStr, false]; return [dbProtStr, false];
...@@ -656,7 +645,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -656,7 +645,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
</Input> </Input>
</FormGroup> </FormGroup>
{ {
(Object.entries(this.state.cache.contents.datasets): [string, any][]) (Object.entries(this.props.data.contents.datasets): [string, any][])
.sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1) .sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1)
.map(([name, dataset], i, dEntries) => { .map(([name, dataset], i, dEntries) => {
const inferredTypes = this.getConnectionInferredTypes(); const inferredTypes = this.getConnectionInferredTypes();
...@@ -701,8 +690,8 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -701,8 +690,8 @@ export class ExperimentEditor extends React.Component<Props, State> {
database: res[3] || '', database: res[3] || '',
}; };
const newDs = {...this.state.cache.contents.datasets, [name]: ds}; const newDs = {...this.props.data.contents.datasets, [name]: ds};
this.setContents({...this.state.cache.contents, datasets: newDs}); this.setContents({...this.props.data.contents, datasets: newDs});
this.setLockMap(name, true); this.setLockMap(name, true);
}} }}
> >
...@@ -750,22 +739,22 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -750,22 +739,22 @@ export class ExperimentEditor extends React.Component<Props, State> {
return isValidEntity(blockName, tcBlock, {inputs: iAlg, outputs: oAlg}, inferredTypes); return isValidEntity(blockName, tcBlock, {inputs: iAlg, outputs: oAlg}, inferredTypes);
}); });
const updateBlock = (newBlock, globals = this.state.cache.contents.globals, newName = blockName) => { const updateBlock = (newBlock, globals = this.props.data.contents.globals, newName = blockName) => {
if(isAnalyzer) if(isAnalyzer)
delete newBlock.outputs; delete newBlock.outputs;
const bKey = isAnalyzer ? 'analyzers' : 'blocks'; const bKey = isAnalyzer ? 'analyzers' : 'blocks';
const newBlocks = changeObjFieldName(this.state.cache.contents[bKey], blockName, newName); const newBlocks = changeObjFieldName(this.props.data.contents[bKey], blockName, newName);
newBlocks[newName] = newBlock; newBlocks[newName] = newBlock;
this.setContents({ this.setContents({
...this.state.cache.contents, ...this.props.data.contents,
[bKey]: newBlocks, [bKey]: newBlocks,
globals, globals,
}); });
}; };
const envInfo = block.environment || this.state.cache.contents.globals.environment; const envInfo = block.environment || this.props.data.contents.globals.environment;
const queue = block.queue || this.state.cache.contents.globals.queue; const queue = block.queue || this.props.data.contents.globals.queue;
const envDisabled = !block.hasOwnProperty('environment'); const envDisabled = !block.hasOwnProperty('environment');
return ( return (
...@@ -881,14 +870,14 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -881,14 +870,14 @@ export class ExperimentEditor extends React.Component<Props, State> {
thisBlock.outputs = levMapStrings(Object.keys(outputs), tcBlock.outputs); thisBlock.outputs = levMapStrings(Object.keys(outputs), tcBlock.outputs);
const globals = { const globals = {
...this.state.cache.contents.globals, ...this.props.data.contents.globals,
}; };
if(alg.contents.parameters && Object.keys(alg.contents.parameters).length > 0) if(alg.contents.parameters && Object.keys(alg.contents.parameters).length > 0)
globals[alg.name] = { globals[alg.name] = {
...Object.entries(alg.contents.parameters || {}) ...Object.entries(alg.contents.parameters || {})
.map(([pName, param]) => ({[pName]: getDefaultParameterValue(param)})) .map(([pName, param]) => ({[pName]: getDefaultParameterValue(param)}))
.reduce((o, p) => ({...o, ...p}), {}), .reduce((o, p) => ({...o, ...p}), {}),
...this.state.cache.contents.globals[alg.name], ...this.props.data.contents.globals[alg.name],
}; };
if(globals.hasOwnProperty(block.algorithm) && if(globals.hasOwnProperty(block.algorithm) &&
...@@ -914,7 +903,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -914,7 +903,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
{ {
Object.entries(alg.contents.parameters || {}).map(([pName, paramObj], i) => { Object.entries(alg.contents.parameters || {}).map(([pName, paramObj], i) => {
const isTethered = !block.parameters.hasOwnProperty(pName); const isTethered = !block.parameters.hasOwnProperty(pName);
const globalParams = this.state.cache.contents.globals[alg.name]; const globalParams = this.props.data.contents.globals[alg.name];
const currVal = block.parameters[pName] || globalParams[pName]; const currVal = block.parameters[pName] || globalParams[pName];
const deleteParam = () => { const deleteParam = () => {
...@@ -1055,7 +1044,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -1055,7 +1044,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
renderBlocks = () => this.state.activeBlockInfo.set === 'blocks' && ( renderBlocks = () => this.state.activeBlockInfo.set === 'blocks' && (
<FormGroup> <FormGroup>
{ {
(Object.entries(this.state.cache.contents.blocks): [string, any][]) (Object.entries(this.props.data.contents.blocks): [string, any][])
.filter(([n, b]) => n === this.state.activeBlockInfo.name) .filter(([n, b]) => n === this.state.activeBlockInfo.name)
.sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1) .sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1)
.map(([name, blk], i) => .map(([name, blk], i) =>
...@@ -1069,7 +1058,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -1069,7 +1058,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
<FormGroup> <FormGroup>
<h3>Analyzers</h3> <h3>Analyzers</h3>
{ {
(Object.entries(this.state.cache.contents.analyzers): [string, any][]) (Object.entries(this.props.data.contents.analyzers): [string, any][])
.filter(([n, b]) => n === this.state.activeBlockInfo.name) .filter(([n, b]) => n === this.state.activeBlockInfo.name)
.sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1) .sort(([n1, ds1], [n2, ds2]) => n1 > n2 ? 1 : -1)
.map(([name, blk], i) => .map(([name, blk], i) =>
...@@ -1092,15 +1081,15 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -1092,15 +1081,15 @@ export class ExperimentEditor extends React.Component<Props, State> {
</InfoTooltip> </InfoTooltip>
</h3> </h3>
<EnvironmentConfig <EnvironmentConfig
envInfo={this.state.cache.contents.globals.environment} envInfo={this.props.data.contents.globals.environment}
queue={this.state.cache.contents.globals.queue} queue={this.props.data.contents.globals.queue}
availableEnvs={this.props.environments} availableEnvs={this.props.environments}
updateEnvInfo={(name, version) => this.setContents({ updateEnvInfo={(name, version) => this.setContents({
...this.state.cache.contents, ...this.props.data.contents,
globals: { globals: {
...this.state.cache.contents.globals, ...this.props.data.contents.globals,
environment: { environment: {
...this.state.cache.contents.globals.environment, ...this.props.data.contents.globals.environment,
name, name,
version, version,
}, },
...@@ -1108,9 +1097,9 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -1108,9 +1097,9 @@ export class ExperimentEditor extends React.Component<Props, State> {
} }
})} })}
updateQueue={queue => this.setContents({ updateQueue={queue => this.setContents({
...this.state.cache.contents, ...this.props.data.contents,
globals: { globals: {
...this.state.cache.contents.globals, ...this.props.data.contents.globals,
queue, queue,
} }
})} })}
...@@ -1131,17 +1120,17 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -1131,17 +1120,17 @@ export class ExperimentEditor extends React.Component<Props, State> {
<ParameterConsume <ParameterConsume
name={`${ algName }/${ pName }`} name={`${ algName }/${ pName }`}
parameter={paramObj} parameter={paramObj}
currVal={this.state.cache.contents.globals[algName][pName]} currVal={this.props.data.contents.globals[algName][pName]}
updateFunc={(val: ParameterValue) => { updateFunc={(val: ParameterValue) => {
const globals = { const globals = {
...this.state.cache.contents.globals, ...this.props.data.contents.globals,
[algName]: { [algName]: {
...this.state.cache.contents.globals[algName], ...this.props.data.contents.globals[algName],
[pName]: val [pName]: val
} }
}; };
this.setContents({ this.setContents({
...this.state.cache.contents, ...this.props.data.contents,
globals globals
}); });
}} }}
...@@ -1161,11 +1150,11 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -1161,11 +1150,11 @@ export class ExperimentEditor extends React.Component<Props, State> {
const {representation, blocks, datasets, analyzers, connections} = tc.contents; const {representation, blocks, datasets, analyzers, connections} = tc.contents;
const groups = tc.extraContents ? tc.extraContents.groups : []; const groups = tc.extraContents ? tc.extraContents.groups : [];
const expData = [ const expData = [
...Object.entries(this.state.cache.contents.datasets) ...Object.entries(this.props.data.contents.datasets)
.map(([name, ds]) => ({ [name]: datasetFieldToString(ds) })), .map(([name, ds]) => ({ [name]: datasetFieldToString(ds) })),
...Object.entries(this.state.cache.contents.blocks) ...Object.entries(this.props.data.contents.blocks)
.map(([name, b]) => ({ [name]: b.algorithm })), .map(([name, b]) => ({ [name]: b.algorithm })),
...Object.entries(this.state.cache.contents.analyzers) ...Object.entries(this.props.data.contents.analyzers)
.map(([name, a]) => ({ [name]: a.algorithm })), .map(([name, a]) => ({ [name]: a.algorithm })),
].reduce((o, data) => ({ ...o, ...data }), {}); ].reduce((o, data) => ({ ...o, ...data }), {});
const errorMap = this.getErrorMap(); const errorMap = this.getErrorMap();
...@@ -1238,9 +1227,9 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -1238,9 +1227,9 @@ export class ExperimentEditor extends React.Component<Props, State> {
className='mx-auto' className='mx-auto'
outline outline
color='secondary' color='secondary'
onClick={() => this.props.saveFunc(this.state.cache)} onClick={() => this.props.saveFunc(this.props.data)}
> >
Save Changes (Changes are <ValidSchemaBadge entity='experiment' obj={this.state.cache} />) Save Changes (Changes are <ValidSchemaBadge entity='experiment' obj={this.props.data} />)
</Button> </Button>
</div> </div>
<Form onSubmit={(e) => e.preventDefault()}> <Form onSubmit={(e) => e.preventDefault()}>
...@@ -1251,8 +1240,8 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -1251,8 +1240,8 @@ export class ExperimentEditor extends React.Component<Props, State> {
type='text' type='text'
className='expDescription' className='expDescription'
placeholder='Experiment description...' placeholder='Experiment description...'
value={this.state.cache.contents['description']} value={this.props.data.contents['description']}
onChange={e => this.setContents({ ...this.state.cache.contents, 'description': e.target.value})} onChange={e => this.setContents({ ...this.props.data.contents, 'description': e.target.value})}
/> />
</FormGroup> </FormGroup>
</FormGroup> </FormGroup>
...@@ -1289,12 +1278,17 @@ const mapStateToProps = (state, ownProps) => { ...@@ -1289,12 +1278,17 @@ const mapStateToProps = (state, ownProps) => {
datasets: [], datasets: [],
} }
}; };
const exps = Selectors.experimentGet(state);
const normalBlocks = Selectors.normalBlocks(state);
const analyzerBlocks = Selectors.analyzerBlocks(state);
const obj = { const obj = {
experiments: Selectors.experimentGet(state), experiments: exps,
data: exps[ownProps.index] || getValidObj({name: '', contents: {}}, tc, [normalBlocks, ...analyzerBlocks]),
// algorithms for normal blocks // algorithms for normal blocks
normalBlocks: Selectors.normalBlocks(state), normalBlocks,
// algorithms for analyzer blocks // algorithms for analyzer blocks
analyzerBlocks: Selectors.analyzerBlocks(state), analyzerBlocks,