-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #267 from legumeinfo/lis-association-search-element2
Trait association search
- Loading branch information
Showing
63 changed files
with
6,974 additions
and
3,957 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
<!DOCTYPE html> | ||
|
||
<html> | ||
|
||
<head> | ||
<meta charset="utf-8" /> | ||
<title>LIS Web-Components - <lis-trait-association-search-element></title> | ||
<!-- CSS framework --> | ||
<link rel="stylesheet" type="text/css" href="../node_modules/uikit/dist/css/uikit.min.css"> | ||
<script src="../node_modules/uikit/dist/js/uikit.min.js"></script> | ||
<!-- web components polyfills --> | ||
<script src="../node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script> | ||
<script src="../node_modules/lit/polyfill-support.js"></script> | ||
<!-- GraphQL --> | ||
<script type="text/javascript" src="./graphql.js"></script> | ||
<!-- web components --> | ||
<script type="module" src="../lib/index.js"></script> | ||
</head> | ||
|
||
<body> | ||
|
||
<div class="uk-container"> | ||
<h1><lis-trait-association-search-element></h1> | ||
<p> | ||
The <code><lis-trait-association-search-element></code> provides a form for performing trait association searches of GWAS/QTL studies and displays the results in a paginated view. | ||
The search is performed using an external function provided to the component when it is added to the page. | ||
In this example, the component performs a search for legume trait associations using the LIS GraphQL API query <code>traits</code>. | ||
The form's genus and species selectors are also populated from this API. | ||
See the source code for details. | ||
Note that the form's input and page values are kept up to date in the URL query string parameters. | ||
This allows users to share specific pages from a search via the URL and for the search history to be navigated via the Web browser's forward and back buttons. | ||
If the query string parameters are present when the component loads then a search will be automatically performed with the query string parameter values. | ||
</p> | ||
<p> | ||
Optionally, all searches can be limited to a specific genus by setting the <code>genus</code> attribute/property. | ||
This will cause the genus field of the search form to be automatically set and disabled so that users cannot change it. | ||
Similarly, all searches can be limited to a specific species by setting the <code>species</code> attribute/property in conjunction with the <code>genus</code> attribute/property. | ||
You can try setting the <code>genus</code> and <code>species</code> properties in this example using the <code>traitAssociationSearchElement</code> variable in the Web console. | ||
</p> | ||
|
||
<hr> | ||
|
||
<!-- the custom trait association search element --> | ||
<lis-trait-association-search-element id="trait-association-search"></lis-trait-association-search-element> | ||
|
||
</div> | ||
|
||
<!-- set the search function by property because functions can't be set as attributes --> | ||
<script type="text/javascript"> | ||
|
||
// uses the LIS GraphQL API to get data used to construct the search form | ||
const formDataQuery = ` | ||
query FormDataQuery { | ||
organisms { | ||
results { | ||
genus | ||
species | ||
} | ||
} | ||
} | ||
`; | ||
|
||
function getFormData({abortSignal}) { | ||
return graphqlQuery(uri, formDataQuery, {}, abortSignal) | ||
.then(({data}) => { | ||
// bin the strains by genus then species | ||
const binnedFormData = {}; | ||
data.organisms.results.forEach(({genus, species}) => { | ||
if (!(genus in binnedFormData)) { | ||
binnedFormData[genus] = []; | ||
} | ||
binnedFormData[genus].push(species); | ||
}); | ||
// collapse the bins into arrays of objects | ||
const genuses = | ||
Object.entries(binnedFormData).map(([genus, binnedSpecies]) => { | ||
const species = binnedSpecies.map((species) => { | ||
return {species}; | ||
}); | ||
return {genus, species}; | ||
}); | ||
// return the expected form data object | ||
return {genuses}; | ||
}); | ||
} | ||
|
||
const traitQuery = ` | ||
query TraitQuery($pageSize: Int, $page: Int, $name: String, $studyType: String, $publicationId: String, $author: String) { | ||
traits(pageSize: $pageSize, page: $page, name: $name, studyType: $studyType, publicationId: $publicationId, author: $author) { | ||
results { | ||
name | ||
qtlStudy { | ||
identifier | ||
synopsis | ||
description | ||
genotypes | ||
organism { | ||
genus | ||
species | ||
} | ||
dataSet { | ||
publication { | ||
firstAuthor | ||
pubMedId | ||
doi | ||
} | ||
} | ||
} | ||
gwas { | ||
identifier | ||
synopsis | ||
description | ||
genotypes | ||
organism { | ||
genus | ||
species | ||
} | ||
dataSet { | ||
publication { | ||
firstAuthor | ||
pubMedId | ||
doi | ||
} | ||
} | ||
} | ||
} | ||
pageInfo { | ||
currentPage | ||
pageSize | ||
numResults | ||
pageCount | ||
hasPreviousPage | ||
hasNextPage | ||
} | ||
} | ||
} | ||
`; | ||
|
||
// search function | ||
function getTraits(searchData, page,{abortSignal}) { | ||
const genus = searchData['genus']; | ||
const species = searchData['species']; | ||
let studyType = searchData['type']; | ||
if (studyType === 'QTL') { | ||
studyType = 'QTLStudy'; | ||
} | ||
const name = searchData['traits']; | ||
const publicationId = searchData['pubId']; | ||
const author = searchData['author']; | ||
const variables = { | ||
genus, | ||
species, | ||
studyType, | ||
name, | ||
publicationId, | ||
author, | ||
page, | ||
pageSize: 10, | ||
}; | ||
|
||
// shim the results for the Web Component | ||
return graphqlQuery(uri, traitQuery, variables, abortSignal) | ||
.then(({data}) => { | ||
// extract the page info | ||
const {hasNextPage: hasNext, numResults, pageSize, pageCount: numPages} | ||
= data.traits.pageInfo; | ||
|
||
// flatten results | ||
const results = | ||
data.traits.results.map(({name, ...trait}) => { | ||
const type = trait.qtlStudy ? 'QTL' : 'GWAS'; | ||
const study = trait.qtlStudy || trait.gwas; | ||
const {identifier, synopsis, description, genotypes} = study; | ||
return { | ||
identifier, | ||
type, | ||
synopsis, | ||
description, | ||
name, | ||
genotypes | ||
}; | ||
}); | ||
// construct the expected paginated results object | ||
const paginatedResults = {hasNext, numResults, pageSize, numPages, results}; | ||
return paginatedResults; | ||
}); | ||
} | ||
|
||
// bind component properties | ||
const traitAssociationSearchElement = document.getElementById('trait-association-search'); | ||
traitAssociationSearchElement.formDataFunction = getFormData; | ||
traitAssociationSearchElement.searchFunction = getTraits; | ||
|
||
</script> | ||
|
||
</body> | ||
|
||
</html> |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.