Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/1143 - Circuit browser autocomplete fixes and term info links too #1150

Merged
merged 4 commits into from
Jul 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 40 additions & 15 deletions components/interface/VFBCircuitBrowser/Controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ class AutocompleteResults extends Component {
*/
handleResults (status, data, value){
let results = {};
console.log("Status ", status)
console.log("Data ", data)
console.log("Value ", value)
data?.map(result => {
// Match results by short_form id
if ( result?.short_form?.toLowerCase().includes(value?.toLowerCase()) ){
Expand All @@ -151,6 +154,8 @@ class AutocompleteResults extends Component {
results[result?.label] = result;
}
});

console.log("Results ", results)

this.setState({ filteredResults : results });
}
Expand Down Expand Up @@ -181,6 +186,7 @@ class AutocompleteResults extends Component {
key={this.props.field.id}
className={label.replace(/ +/g, "").toLowerCase()}
onChange={this.props.neuronTextfieldModified}
onDelete={this.props.neuronTextfieldModified}
inputProps={{ ...params.inputProps, id: this.props.index, style: { height : "20px", color: "white" ,paddingLeft : "10px", border : "none", backgroundColor: "#80808040" } }}
InputLabelProps={{ ...params.inputProps,style: { color: "white", paddingLeft : "10px" } }}
/>
Expand Down Expand Up @@ -315,7 +321,6 @@ class Controls extends Component {
neurons.push({ id : target.value, label : target.value });
}

// this.props.vfbCircuitBrowser(UPDATE_CIRCUIT_QUERY, neurons);
this.neuronFields = neurons;
getResultsSOLR( target.value, this.autocompleteRef[this.setInputValue].current.handleResults,searchConfiguration.sorter,datasourceConfiguration );
}
Expand All @@ -324,25 +329,42 @@ class Controls extends Component {
* Neuron text field has been modified.
*/
neuronTextfieldModified (event) {
console.log(event.key);
this.resultsHeight = event.target.offsetTop + 15;
// Remove old typing timeout interval
if (this.state.typingTimeout) {
clearTimeout(this.typingTimeout);
}
// Create a setTimeout interval, to avoid performing searches on every stroke
setTimeout(this.typingTimeout, 10, event.target);

this.setInputValue = event.target.id;
if ( event.target.id.id === "" ) {
this.setInputValue = event.target.parentElement.id;
}
let neurons = this.neuronFields;

if ( neurons[parseInt(event.target.id)] ) {
neurons[parseInt(event.target.id)] = { id : event.target.value, label : event.target.value };
} else {
neurons.push({ id : event.target.value, label : event.target.value });
}

if ( event?.nativeEvent?.inputType === "deleteContentBackward" && neurons?.find( (neuron, index) => neuron.id === "" && index.toString() === event.target.id )){
this.props.vfbCircuitBrowser(UPDATE_CIRCUIT_QUERY, neurons);
} else {
getResultsSOLR( event.target.value, this.autocompleteRef[this.setInputValue].current.handleResults,searchConfiguration.sorter,datasourceConfiguration );
}
this.neuronFields = neurons;
}

/**
* Handle SOLR result selection, activated by selecting from drop down menu under textfield
*/
resultSelectedChanged (event, value) {
resultSelectedChanged (event, value, index) {
// Copy neurons and add selection to correct array index
let neurons = this.neuronFields;
let textFieldId = event.target.id.toString().split("-")[0];
let shortForm = this.autocompleteRef[textFieldId].current.getFilteredResults()[value] && this.autocompleteRef[textFieldId].current.getFilteredResults()[value].short_form;
let index = neurons.findIndex(neuron => neuron.id === shortForm);
index > -1 ? neurons[index] = { id : shortForm, label : value } : null
neurons[index] = { id : shortForm, label : value };

// Keep track of query selected, and send an event to redux store that circuit has been updated
this.circuitQuerySelected = neurons;
Expand Down Expand Up @@ -370,6 +392,7 @@ class Controls extends Component {
while (this?.props?.circuitQuerySelected.length > 0) {
this?.props?.circuitQuerySelected.pop();
}
this.props.vfbCircuitBrowser(UPDATE_CIRCUIT_QUERY, [])
this.setState({ key: Math.random() });
}
/**
Expand All @@ -384,17 +407,19 @@ class Controls extends Component {
);

if ( !fieldExists) {
for ( var j = 0 ; j < neuronFields.length ; j++ ) {
if ( neuronFields?.[j].id === "" ) {
neuronFields[j] = { id : this.props.circuitQuerySelected[i].id ? this.props.circuitQuerySelected[i].id : this.props.circuitQuerySelected[i], label : this.props.circuitQuerySelected[i].label ? this.props.circuitQuerySelected[i].label : this.props.circuitQuerySelected[i] };
added = true;
fieldExists = true;
break;
}
const emptyIndex = neuronFields.findIndex( field => field.id === "");
if ( emptyIndex >= 0 ) {
neuronFields[emptyIndex] = { id : this.props.circuitQuerySelected[i].id ? this.props.circuitQuerySelected[i].id : this.props.circuitQuerySelected[i], label : this.props.circuitQuerySelected[i].label ? this.props.circuitQuerySelected[i].label : this.props.circuitQuerySelected[i] };
added = true;
fieldExists = true;
break;
} else {
neuronFields.pop();
neuronFields.push({ id : this.props.circuitQuerySelected[i].id ? this.props.circuitQuerySelected[i].id : this.props.circuitQuerySelected[i], label : this.props.circuitQuerySelected[i].label ? this.props.circuitQuerySelected[i].label : this.props.circuitQuerySelected[i] })
}

if ( this.props.circuitQuerySelected.length > neuronFields.length && !fieldExists && this.props.circuitQuerySelected?.[i]?.id != "") {
if ( neuronFields.length < configuration.maxNeurons && this.props.circuitQuerySelected !== "" ) {
if ( this.props.circuitQuerySelected !== "" ) {
neuronFields.push({ id : this.props.circuitQuerySelected[i].id ? this.props.circuitQuerySelected[i].id : this.props.circuitQuerySelected[i], label : this.props.circuitQuerySelected[i].label ? this.props.circuitQuerySelected[i].label : this.props.circuitQuerySelected[i] });
}
}
Expand Down Expand Up @@ -467,7 +492,7 @@ class Controls extends Component {
field={field}
index={index}
neuronTextfieldModified={this.neuronTextfieldModified}
resultSelectedChanged={this.resultSelectedChanged}
resultSelectedChanged={(event, value) => this.resultSelectedChanged(event, value, index)}
ref={this.autocompleteRef[index.toString()]}
/>
</Grid>
Expand Down
5 changes: 3 additions & 2 deletions components/interface/VFBCircuitBrowser/VFBCircuitBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ class VFBCircuitBrowser extends Component {
this.circuitQuerySelected = circuitQuerySelected;

let errorMessage = "Not enough input queries to create a graph, needs 2.";
if ( this.state.neurons?.[0].id != "" && this.state.neurons?.[1].id != "" ){
if ( this.state.neurons?.[0]?.id != "" && this.state.neurons?.[1]?.id != "" ){
errorMessage = "Graph not available for " + this.state.neurons.map(a => `'${a.id}'`).join(",");
}
return (
Expand All @@ -321,11 +321,12 @@ class VFBCircuitBrowser extends Component {
resetCamera={self.resetCamera}
zoomIn={self.zoomIn}
zoomOut={self.zoomOut}
circuitQuerySelected={this.circuitQuerySelected}
circuitQuerySelected={circuitQuerySelected}
datasource="SOLR"
legend = {self.state.legend}
ref={self.controlsRef}
clearGraph={self.clearGraph}
key="controls"
/>
</div>
: <GeppettoGraphVisualization
Expand Down
2 changes: 1 addition & 1 deletion components/interface/VFBTermInfo/VFBTermInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ class VFBTermInfo extends React.Component {
let graphs = new Array();
for (var j = 0; j < values.length; j++) {
graphs.push(<div><i className="popup-icon-link fa fa-cogs" ></i>
<a style={{ cursor: "pointer" }} data-instancepath={ CIRCUIT_BROWSER + "," + values[j].instance.parent.name + "," + values[j].instance.parent.id + "," + values[j].index }>
<a id="circuitBrowserLink" style={{ cursor: "pointer" }} data-instancepath={ CIRCUIT_BROWSER + "," + values[j].instance.parent.name + "," + values[j].instance.parent.id + "," + values[j].index }>
{ "Show Circuit Browser for " + values[j].instance.parent.name }
</a>
<br/>
Expand Down
19 changes: 17 additions & 2 deletions reducers/generals.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from '../actions/generals';

const componentsMap = require('../components/configuration/VFBLoader/VFBLoaderConfiguration').componentsMap;
const configuration = require('../components/configuration/VFBCircuitBrowser/circuitBrowserConfiguration').configuration;

export const GENERAL_DEFAULT_STATE = {
error: undefined,
Expand All @@ -42,7 +43,7 @@ export const GENERAL_DEFAULT_STATE = {
termInfo : { termInfoVisible : false },
layers : { listViewerInfoVisible : true },
circuitBrowser : {
circuitQuerySelected : [],
circuitQuerySelected : [{ id : "", label : "" } , { id : "", label : "" }],
visible : true
},
layout: {
Expand Down Expand Up @@ -248,7 +249,21 @@ function generalReducer (state, action) {
newQueryMap = action.data.instance;
} else {
// Instance is object
!state.ui.circuitBrowser.circuitQuerySelected.includes(action.data.instance) ? newQueryMap = [...state.ui.circuitBrowser.circuitQuerySelected, action.data.instance] : newQueryMap = [...state.ui.circuitBrowser.circuitQuerySelected];
let match = state.ui.circuitBrowser.circuitQuerySelected?.find( query => query.id === action.data.instance.id );
if ( match ) {
newQueryMap = [...state.ui.circuitBrowser.circuitQuerySelected]
} else {
const maxedOut = state.ui.circuitBrowser?.circuitQuerySelected?.find( query => query.id === "" );
const emptyIndex = state.ui.circuitBrowser?.circuitQuerySelected?.findIndex( field => field.id === "");
if ( emptyIndex >= 0 ) {
newQueryMap = [...state.ui.circuitBrowser.circuitQuerySelected]
newQueryMap[emptyIndex] = action.data.instance;
} else {
newQueryMap = [...state.ui.circuitBrowser.circuitQuerySelected];
newQueryMap.pop();
newQueryMap.push(action.data.instance);
}
}
}

ui.circuitBrowser.circuitQuerySelected = newQueryMap;
Expand Down
28 changes: 19 additions & 9 deletions tests/jest/vfb/review/circuit-browser-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { wait4selector, click, testLandingPage, flexWindowClick, findElementByTe
import * as ST from '../selectors';

const baseURL = process.env.url || 'http://localhost:8080/org.geppetto.frontend';
const projectURL = baseURL + "/geppetto";
const projectURL = baseURL + "/geppetto?id=VFB_jrchjrch";

const ONE_SECOND = 1000;

Expand All @@ -19,14 +19,13 @@ describe('VFB Circuit Browser Tests', () => {
//increases timeout to ~8 minutes
jest.setTimeout(60 * ONE_SECOND);
await page.goto(projectURL);

});

//Tests opening term context and clicking on row buttons
describe('Test Circuit Browser Component', () => {
//Tests components in landing page are present
it('Test Landing Page', async () => {
await testLandingPage(page, 'VFB_00101567');
await testLandingPage(page, 'VFB_jrchjrch');
})

it('Open Circuit Browser', async () => {
Expand All @@ -36,13 +35,22 @@ describe('VFB Circuit Browser Tests', () => {
await wait4selector(page, 'div#VFBCircuitBrowser', { visible: true, timeout : 90 * ONE_SECOND });
})

it('Set Neuron 1 , VFB_jrchjrch', async () => {
await page.waitFor(5 * ONE_SECOND);
await setTextFieldValue(".neuron1 input", "VFB_jrchjrch")

await wait4selector(page, 'ul.MuiAutocomplete-listbox', { visible: true, timeout : 90 * ONE_SECOND });
it('Open Term Info', async () => {
await selectTab(page, "Term Info");

// Check that the Tree Browser is visible
await wait4selector(page, 'div#vfbterminfowidget', { visible: true, timeout : 90 * ONE_SECOND });
})

it('Open Circuit Browser from Term Info with ID : VFB_jrchjrch', async () => {
await page.click("#circuitBrowserLink");

// Check that the Tree Browser is visible
await wait4selector(page, 'div#VFBCircuitBrowser', { visible: true, timeout : 90 * ONE_SECOND });

await page.click('ul.MuiAutocomplete-listbox li');
await page.waitFor(ONE_SECOND);
const neuron1Input = await page.evaluate( () => document.querySelector(".neuron1 input").value)
expect(neuron1Input).toBe("5-HTPLP01_R (FlyEM-HB:1324365879)(VFB_jrchjrch)");
})

it('Set Neuron 2, VFB_jrchjsfu', async () => {
Expand All @@ -69,6 +77,7 @@ describe('VFB Circuit Browser Tests', () => {
await page.waitFor(ONE_SECOND);

await page.click('#refreshCircuitBrowser');
await wait4selector(page, '.MuiCircularProgress-svg', { visible: true, timeout : 10 * ONE_SECOND });
await page.waitFor(10 * ONE_SECOND);
await wait4selector(page, '#circuitBrowserLegend', { visible: true, timeout : 240 * ONE_SECOND });

Expand All @@ -82,6 +91,7 @@ describe('VFB Circuit Browser Tests', () => {
await page.waitFor(ONE_SECOND);

await page.click('#refreshCircuitBrowser');
await wait4selector(page, '.MuiCircularProgress-svg', { visible: true, timeout : 10 * ONE_SECOND });
await page.waitFor(10 * ONE_SECOND);
await wait4selector(page, '#circuitBrowserLegend', { visible: true, timeout : 240 * ONE_SECOND });

Expand Down