199 lines
7.0 KiB
TypeScript
199 lines
7.0 KiB
TypeScript
import React, { Component } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useAppDispatch } from "../../app/hooks";
|
|
import DataUtils, { SearchResults } from "../data/DataUtils";
|
|
import { setTitle } from "../page-title/pageTitleSlice";
|
|
import { setResults } from "../search-results/searchResultsSlice";
|
|
import styles from "./SearchForm.module.css";
|
|
|
|
interface FCProps {}
|
|
|
|
interface Props extends FCProps {
|
|
navigate: any;
|
|
dispatch: any;
|
|
}
|
|
|
|
interface State {
|
|
pdStart: string;
|
|
pdEnd: string;
|
|
widthMin: string;
|
|
widthMax: string;
|
|
depthMin: string;
|
|
depthMax: string;
|
|
cellType: string;
|
|
area: string;
|
|
geneType: string;
|
|
keyword: string;
|
|
}
|
|
|
|
class SearchForm extends Component<Props, State> {
|
|
constructor(props: Props) {
|
|
super(props);
|
|
this.state = {
|
|
pdStart: "44",
|
|
pdEnd: "100",
|
|
widthMin: "317",
|
|
widthMax: "512",
|
|
depthMin: "90",
|
|
depthMax: "230",
|
|
cellType: "any",
|
|
area: "all",
|
|
geneType: "all",
|
|
keyword: "",
|
|
};
|
|
this.handleInputChange = this.handleInputChange.bind(this);
|
|
this.handleSelectChange = this.handleSelectChange.bind(this);
|
|
this.handleSubmit = this.handleSubmit.bind(this);
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.props.dispatch(setTitle("Database Search"));
|
|
}
|
|
|
|
doSearch(): SearchResults {
|
|
const toNumber = (v: string): number => parseInt(v.trim(), 10);
|
|
const params = {
|
|
pdStart: toNumber(this.state.pdStart),
|
|
pdEnd: toNumber(this.state.pdEnd),
|
|
widthMin: toNumber(this.state.widthMin),
|
|
widthMax: toNumber(this.state.widthMax),
|
|
depthMin: toNumber(this.state.depthMin),
|
|
depthMax: toNumber(this.state.depthMax),
|
|
cellType: this.state.cellType.trim(),
|
|
area: this.state.area.trim(),
|
|
geneType: this.state.geneType.trim(),
|
|
keyword: this.state.keyword.trim(),
|
|
};
|
|
return DataUtils.search(params);
|
|
}
|
|
|
|
handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const target = event.target;
|
|
const value = target.value;
|
|
const name = target.name;
|
|
switch (name) {
|
|
case "pdStart":
|
|
this.setState({ pdStart: value });
|
|
break;
|
|
case "pdEnd":
|
|
this.setState({ pdStart: value });
|
|
break;
|
|
case "widthMin":
|
|
this.setState({ widthMin: value });
|
|
break;
|
|
case "widthMax":
|
|
this.setState({ widthMax: value });
|
|
break;
|
|
case "depthMin":
|
|
this.setState({ depthMin: value });
|
|
break;
|
|
case "depthMax":
|
|
this.setState({ depthMax: value });
|
|
break;
|
|
case "cellType":
|
|
this.setState({ cellType: value });
|
|
break;
|
|
case "keyword":
|
|
this.setState({ keyword: value });
|
|
break;
|
|
}
|
|
};
|
|
|
|
handleSelectChange: React.ChangeEventHandler<HTMLSelectElement> = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
|
const target = event.target;
|
|
const value = target.value;
|
|
const name = target.name;
|
|
switch (name) {
|
|
case "area":
|
|
this.setState({ area: value });
|
|
break;
|
|
case "geneType":
|
|
this.setState({ geneType: value });
|
|
break;
|
|
}
|
|
};
|
|
|
|
handleSubmit: React.FormEventHandler<HTMLFormElement> = (event: React.FormEvent) => {
|
|
event.preventDefault();
|
|
const results = this.doSearch();
|
|
this.props.dispatch(setResults(results));
|
|
this.props.navigate("/search/results");
|
|
};
|
|
|
|
render() {
|
|
return (
|
|
<form onSubmit={this.handleSubmit}>
|
|
<div className={styles.formGroup}>
|
|
<label htmlFor="pdStart">Postnatal Days</label>
|
|
<div className={styles.value}>
|
|
<input type="number" name="pdStart" className={styles.txtParam} value={this.state.pdStart} onChange={this.handleInputChange} />
|
|
<span className={styles.range}>-</span>
|
|
<input type="number" name="pdEnd" className={styles.txtParam} value={this.state.pdEnd} onChange={this.handleInputChange} />
|
|
</div>
|
|
</div>
|
|
<div className={styles.formGroup}>
|
|
<label htmlFor="widthMin">Recording volume width (height)</label>
|
|
<div className={styles.value}>
|
|
<input type="number" name="widthMin" className={styles.txtParam} value={this.state.widthMin} onChange={this.handleInputChange} />
|
|
<span className={styles.range}>-</span>
|
|
<input type="number" name="widthMax" className={styles.txtParam} value={this.state.widthMax} onChange={this.handleInputChange} />
|
|
</div>
|
|
</div>
|
|
<div className={styles.formGroup}>
|
|
<label htmlFor="depthMin">Recording volume depth</label>
|
|
<div className={styles.value}>
|
|
<input type="number" name="depthMin" className={styles.txtParam} value={this.state.depthMin} onChange={this.handleInputChange} />
|
|
<span className={styles.range}>-</span>
|
|
<input type="number" name="depthMax" className={styles.txtParam} value={this.state.depthMax} onChange={this.handleInputChange} />
|
|
</div>
|
|
</div>
|
|
<div className={styles.formGroup}>
|
|
<label htmlFor="cellType">Cell type (E, I, G, P, S, or "any")</label>
|
|
<div className={styles.value}>
|
|
<input type="text" name="cellType" className={styles.txtParamStr} value={this.state.cellType} onChange={this.handleInputChange} />
|
|
</div>
|
|
</div>
|
|
<div className={styles.formGroup}>
|
|
<label htmlFor="area">Target area</label>
|
|
<div className={styles.value}>
|
|
<select name="area" className={styles.selParam} value={this.state.area} onChange={this.handleSelectChange}>
|
|
<option value="all">All</option>
|
|
<option value="L2/3, V1">L2/3 in the visual cortex</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div className={styles.formGroup}>
|
|
<label htmlFor="geneType">Mouse line</label>
|
|
<div className={styles.value}>
|
|
<select name="geneType" className={styles.selParam} value={this.state.geneType} onChange={this.handleSelectChange}>
|
|
<option value="all">All</option>
|
|
<option value="VGAT-Venus">VGAT-Venus</option>
|
|
<option value="PV/myrGFP-LDLRct">PV/myrGFP-LDLRct</option>
|
|
<option value="Dlx5/6-GCaMP3">Dlx5/6-GCaMP3</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div className={styles.formGroup}>
|
|
<label htmlFor="keyword">Keyword Search</label>
|
|
<div className={styles.value}>
|
|
<input type="text" name="keyword" className={styles.txtKeyword} value={this.state.keyword} onChange={this.handleInputChange} />
|
|
</div>
|
|
</div>
|
|
<div className={styles.formGroup}>
|
|
<div className={styles.submit}>
|
|
<input type="submit" value="Search" />
|
|
</div>
|
|
</div>
|
|
</form>
|
|
);
|
|
}
|
|
}
|
|
|
|
const SearchFormFC: React.FC<FCProps> = (props: FCProps) => {
|
|
const navigate = useNavigate();
|
|
const dispatch = useAppDispatch();
|
|
return <SearchForm navigate={navigate} dispatch={dispatch} />;
|
|
};
|
|
|
|
export default SearchFormFC;
|