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

Connects to #366. DEA search by protein names. #380

Merged
merged 22 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9979663
Change 'keys' data type from string to array
jimmyzhen Aug 22, 2024
05e218e
Change 'keys' prop type from string to array
jimmyzhen Aug 22, 2024
bb6487e
Implement support for search by protein names and remove support for …
jimmyzhen Aug 22, 2024
c912f23
Merge branch 'dev' of github.com:MoTrPAC/motrpac-frontend into 366_JZ…
jimmyzhen Dec 1, 2024
fae82c3
Update search radio buttons' label text
jimmyzhen Dec 1, 2024
060f835
Reinstall dependencies
jimmyzhen Dec 1, 2024
c1addce
Add table display for proteomics DEA specific data
jimmyzhen Dec 5, 2024
1942bdd
Add params to receive formatted assay and tissue names in query response
jimmyzhen Dec 5, 2024
9f3e9c4
Add support for 'is_meta' flag in searching metabolite DEA data
jimmyzhen Dec 5, 2024
e971023
Refactor code to support table display for proteomics specific DEA da…
jimmyzhen Dec 5, 2024
1da03ec
Add support to handle server-side pagination and manual pagination co…
jimmyzhen Dec 5, 2024
64a5702
Add support to handle server-side pagination and manual pagination co…
jimmyzhen Dec 5, 2024
2026a96
Remove client-side assay and tissue value processing because the form…
jimmyzhen Dec 5, 2024
bb6b33d
Add props for receiving formatted assay and tissue names from query r…
jimmyzhen Dec 5, 2024
34d8dc8
Remove no longer used global filter components function
jimmyzhen Dec 5, 2024
13e0071
Update NCBI search query to include 'rat'
jimmyzhen Dec 5, 2024
601d6ea
Merge branch 'dev' of github.com:MoTrPAC/motrpac-frontend into 366_JZ…
jimmyzhen Dec 5, 2024
a6ab608
Revert size change of server-side pagination
jimmyzhen Dec 11, 2024
553800c
Roll back server-side pagination implementation (needs further testin…
jimmyzhen Dec 11, 2024
f3abf79
Fix typo
jimmyzhen Dec 12, 2024
771fc63
Revert to prior revision
jimmyzhen Dec 12, 2024
ee8715d
Remove commented-out code per Copilot suggestion
jimmyzhen Dec 12, 2024
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
20 changes: 20 additions & 0 deletions src/Search/searchActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,26 @@ function handleSearch(params, inputValue, scope) {
p_value: { min: '', max: '' },
};
}
// insert 'is_meta" field to fields array if ktype is 'metab'
// and delete 'protein_name' field if it exists
if (params.ktype === 'metab') {
if (!params.fields.includes('is_meta')) {
params.fields = ['is_meta', ...params.fields];
}
if (params.fields.includes('protein_name')) {
const index = params.fields.indexOf('protein_name');
params.fields.splice(index, 1);
}
}
// delete 'is_meta' flag from fields array (if it exists)
// if ktype is 'protein' or 'gene'
if (params.ktype === 'protein' || params.ktype === 'gene') {
if (params.fields.includes('is_meta')) {
const index = params.fields.indexOf('is_meta');
params.fields.splice(index, 1);
}
}

return (dispatch) => {
dispatch(searchSubmit(params, scope));
return axios
Expand Down
157 changes: 81 additions & 76 deletions src/Search/searchPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import IconSet from '../lib/iconSet';
import { trackEvent } from '../GoogleAnalytics/googleAnalytics';
import { genes } from '../data/genes';
import { metabolites } from '../data/metabolites';
import { proteins } from '../data/proteins';
import searchStructuredData from '../lib/searchStructuredData/search';
import UserSurveyModal from '../UserSurvey/userSurveyModal';

Expand Down Expand Up @@ -110,50 +111,61 @@ export function SearchPage({
return null;
}

// get options based on selected search context
function getOptions() {
switch (searchParams.ktype) {
case 'gene':
return genes;
case 'metab':
return metabolites;
case 'protein':
return proteins;
default:
return [];
}
}

// render placeholder text in primary search input field
function renderPlaceholder() {
if (searchParams.ktype === 'protein') {
return 'Example: NP_001000006.1, NP_001001508.2, NP_001005898.3';
return 'Example: "atpase inhibitor, mitochondrial", "global ischemia-induced protein 11"';
}
if (searchParams.ktype === 'metab') {
return 'Example: 8,9-EpETrE, C18:1 LPC plasmalogen B';
return 'Example: "amino acids and peptides", "c10:2 carnitine"';
}
return 'Example: BRD2, SMAD3, ID1';
return 'Example: brd2, smad3, vegfa';
}

const inputEl = document.querySelector('.rbt-input-main');

// FIXME: transform react-bootstrap-typeahead state from array to string
// Transform input values
// Keep react-bootstrap-typeahead state array as is
// Convert manually entered gene/protein/metabolite string input to array
function formatSearchInput() {
const newArr = [];
// react-bootstrap-typeahead state array has values
if (multiSelections.length) {
multiSelections.forEach((item) => newArr.push(item.id));
return newArr.join(', ');
return newArr;
}
// Handle manually entered gene/metabolite input
// Handle manually entered gene/protein/metabolite string input
// convert formatted string to array
if (inputEl.value && inputEl.value.length) {
const str = inputEl.value;
if (searchParams.ktype === 'gene') {
const arr = str.split(',').map((s) => s.trim());
return arr.join(', ');
}
return str;
const inputStr = inputEl.value;
// Match terms enclosed in double quotes or not containing commas
const terms = inputStr.match(/("[^"]+"|[^, ]+)/g);
// Remove double quotes from terms that are enclosed and trim any extra spaces
return terms.map((term) => term.replace(/"/g, '').trim());
}
return '';
return newArr;
}

// Clear manually entered gene/protein/metabolite input
function clearGeneInput(ktype) {
const inputElProtein = document.querySelector('.search-input-kype');

if (ktype && ktype === 'protein') {
if (inputElProtein && inputElProtein.value && inputElProtein.value.length) {
inputElProtein.value = '';
}
} else if (inputEl && inputEl.value && inputEl.value.length) {
const clearSearchTermInput = () => {
if (inputEl && inputEl.value && inputEl.value.length) {
inputRef.current.clear();
}
}
};

return (
<div className="searchPage px-3 px-md-4 mb-3">
Expand All @@ -167,78 +179,71 @@ export function SearchPage({
<form id="searchForm" name="searchForm">
<PageTitle title="Search differential abundance data" />
<div className="search-content-container">
<div className="search-summary-container row mb-4 pb-2">
<div className="search-summary-container row mb-4">
<div className="lead col-12">
Search by gene symbol, protein ID or metabolite name to examine the
Search by gene symbol, protein name or metabolite name to examine the
timewise endurance training response over 8 weeks of training in
young adult rats.
{' '}
<span className="font-weight-bold">
Multiple search terms MUST be separated by comma and space.
Examples: "NP_001000006.1, NP_001001508.2, NP_001005898.3" or
"8,9-EpETrE, C18:1 LPC plasmalogen B".
</span>
{' '}
young adult rats. To ensure the best search results, please use the
following guidelines:
<ol>
<li>
Use
{' '}
<span className="font-weight-bold">
auto-suggested search terms
</span>
{' '}
by typing the first few
characters of the gene symbol, protein or metabolite names.
</li>
<li>
Separate multiple search terms using a comma followed by a space. For example:
{' '}
<code>brd2, smad3, vegfa</code>
</li>
<li>
Use double quotes to enclose search terms containing commas,
spaces or commas followed by spaces. For example:
{' '}
<code>"tca acids", "8,9-epetre", "coa(3:0, 3-oh)"</code>
</li>
</ol>
<p>
The endurance trained young adult rats dataset is made available
under the
{' '}
<Link to="/license">CC BY 4.0 license</Link>
.
</p>
</div>
</div>
<div className="es-search-ui-container d-flex align-items-center w-100 pb-2">
<RadioButton
changeParam={changeParam}
ktype={searchParams.ktype}
resetSearch={resetSearch}
clearInput={clearSearchTermInput}
setMultiSelections={setMultiSelections}
inputEl={inputEl}
/>
<div className="search-box-input-group d-flex align-items-center flex-grow-1">
{/*
<input
type="text"
id="keys"
name="keys"
className="form-control search-input-kype flex-grow-1"
placeholder={renderPlaceholder()}
value={searchParams.keys}
onChange={(e) => changeParam('keys', e.target.value)}
/>
*/}
<div className="input-group">
<div className="input-group-prepend">
<span className="input-group-text material-icons">
pest_control_rodent
</span>
</div>
{searchParams.ktype === 'gene' ||
searchParams.ktype === 'metab' ? (
<Typeahead
id="dea-search-typeahead-multiple"
labelKey="id"
multiple
onChange={setMultiSelections}
options={
searchParams.ktype === 'gene' ? genes : metabolites
}
placeholder={renderPlaceholder()}
selected={multiSelections}
minLength={2}
ref={inputRef}
/>
) : null}
{searchParams.ktype === 'protein' && (
<input
type="text"
id="keys"
name="keys"
className="form-control search-input-kype flex-grow-1"
placeholder={renderPlaceholder()}
value={searchParams.keys}
onChange={(e) => changeParam('keys', e.target.value)}
/>
)}
<Typeahead
id="dea-search-typeahead-multiple"
labelKey="id"
multiple
onChange={setMultiSelections}
options={getOptions()}
placeholder={renderPlaceholder()}
selected={multiSelections}
minLength={2}
ref={inputRef}
/>
</div>
<PrimaryOmicsFilter
omics={searchParams.omics}
Expand Down Expand Up @@ -280,9 +285,7 @@ export function SearchPage({
type="button"
className="btn btn-secondary search-reset ml-2"
onClick={() => {
clearGeneInput(
searchParams.ktype === 'protein' ? 'protein' : null
);
clearSearchTermInput();
resetSearch('all');
setMultiSelections([]);
}}
Expand Down Expand Up @@ -472,29 +475,31 @@ function RadioButton({
changeParam,
ktype,
resetSearch,
clearInput,
setMultiSelections,
inputEl,
}) {
const radioButtons = [
{
keyType: 'gene',
id: 'inlineRadioGene',
label: 'Gene Symbol',
label: 'Gene symbol',
},
{
keyType: 'protein',
id: 'inlineRadioProtein',
label: 'Protein ID',
label: 'Protein name',
},
{
keyType: 'metab',
id: 'inlineRadioMetab',
label: 'Metabolite',
label: 'Metabolite name',
},
];

const handleRadioChange = (e) => {
resetSearch('all');
clearInput();
setMultiSelections([]);
changeParam('ktype', e.target.value);
if (inputEl && inputEl.value && inputEl.value.length) {
Expand Down
24 changes: 15 additions & 9 deletions src/Search/searchReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const defaultSearchState = {
searchResults: {},
searchParams: {
ktype: 'gene',
keys: '',
keys: [],
omics: 'all',
analysis: 'all',
filters: {
Expand Down Expand Up @@ -42,9 +42,11 @@ export const defaultSearchState = {
'p_value_female',
],
unique_fields: ['tissue', 'assay', 'sex', 'comparison_group'],
size: 25000,
size: 10000,
start: 0,
save: false,
convert_assay_code: 1,
convert_tissue_code: 1,
},
scope: 'all',
searching: false,
Expand Down Expand Up @@ -121,6 +123,7 @@ export function SearchReducer(state = { ...defaultSearchState }, action) {
fields,
unique_fields,
size,
start,
} = action.params;
return {
...state,
Expand All @@ -134,8 +137,11 @@ export function SearchReducer(state = { ...defaultSearchState }, action) {
fields,
unique_fields,
size,
start,
debug: true,
save: false,
convert_assay_code: 1,
convert_tissue_code: 1,
},
scope: action.scope,
searching: true,
Expand All @@ -157,9 +163,9 @@ export function SearchReducer(state = { ...defaultSearchState }, action) {
searchResults:
action.searchResults.message || action.searchResults.errors
? {
errors:
errors:
action.searchResults.message || action.searchResults.errors,
}
}
: action.searchResults,
searching: false,
hasResultFilters:
Expand Down Expand Up @@ -189,7 +195,7 @@ export function SearchReducer(state = { ...defaultSearchState }, action) {
}

const defaultParams = { ...defaultSearchState.searchParams };
defaultParams.keys = '';
defaultParams.keys = [];
defaultParams.filters = {
tissue: [],
assay: [],
Expand Down Expand Up @@ -229,10 +235,10 @@ export function SearchReducer(state = { ...defaultSearchState }, action) {
downloadResults:
action.downloadResults.message || action.downloadResults.errors
? {
errors:
action.downloadResults.message ||
action.downloadResults.errors,
}
errors:
action.downloadResults.message
|| action.downloadResults.errors,
}
: action.downloadResults,
downloading: false,
};
Expand Down
Loading
Loading