Skip to content

Commit 52286be

Browse files
authored
Merge pull request #47 from legumeinfo/gene-search
Support for gene search component
2 parents 0718238 + 540d66d commit 52286be

File tree

13 files changed

+739
-16
lines changed

13 files changed

+739
-16
lines changed

dep/web-components

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<!DOCTYPE html>
2+
3+
<html>
4+
5+
<head>
6+
<meta charset="utf-8" />
7+
<title>LIS Web-Components - &lt;lis-gene-search-element&gt;</title>
8+
<!-- CSS framework -->
9+
<link rel="stylesheet" type="text/css" href="../node_modules/uikit/dist/css/uikit.min.css">
10+
<script src="../node_modules/uikit/dist/js/uikit.min.js"></script>
11+
<!-- web components polyfills -->
12+
<script src="../node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
13+
<script src="../node_modules/lit/polyfill-support.js"></script>
14+
<!-- web components -->
15+
<script type="module" src="../node_modules/@legumeinfo/web-components/dist/web-components.min.js"></script>
16+
<!-- GraphQL -->
17+
<script type="importmap">
18+
{
19+
"imports": {
20+
"lis-graphql": "../dist/web-components-graphql.min.js"
21+
}
22+
}
23+
</script>
24+
</head>
25+
26+
<body>
27+
<div class="uk-container uk-container-expand">
28+
<h1>&lt;lis-gene-search-element&gt;</h1>
29+
<!-- the custom gene search element -->
30+
<lis-gene-search-element
31+
id="gene-search"
32+
identifierExample="Glyma.13G357700"
33+
descriptionExample="protein disulfide isomerase-like protein"
34+
familyExample="L_HZ6G4Z"
35+
></lis-gene-search-element>
36+
<lis-modal-element modalId="modal">
37+
<lis-linkout-element id="linkouts"></lis-linkout-element>
38+
</lis-modal-element>
39+
</div>
40+
41+
<!-- set the search function by property because functions can't be set as attributes -->
42+
<script type="module">
43+
44+
import { LisGraphqlWebComponents } from 'lis-graphql';
45+
46+
// instantiate the LIS GraphQL class
47+
const uri = 'https://graphql.lis.ncgr.org/';
48+
const graphql = new LisGraphqlWebComponents(uri);
49+
50+
// bind the form data function
51+
const geneSearchElement = document.getElementById('gene-search');
52+
geneSearchElement.formDataFunction = graphql.geneSearchFormDataFactory();
53+
54+
// bind the search function with middleware
55+
//const modalId = 'test';
56+
//const middleware = [
57+
// LisGraphqlWebComponents.middleware.geneSearch.geneIdentifierModalLinkFactory(modalId),
58+
// LisGraphqlWebComponents.middleware.geneSearch.locationModalLinkFactory(modalId),
59+
// LisGraphqlWebComponents.middleware.geneSearch.geneFamilyAssignmentsModalLinkFactory(modalId),
60+
// LisGraphqlWebComponents.middleware.geneSearch.panGeneSetsModalLinkFactory(modalId),
61+
// ];
62+
const middleware =
63+
LisGraphqlWebComponents.middleware.geneSearch.allModalLinksFactory('modal');
64+
geneSearchElement.searchFunction = graphql.geneSearchFunctionFactory(...middleware);
65+
66+
// bind the linkout function
67+
const linkoutElement = document.getElementById('linkouts');
68+
linkoutElement.linkoutFunction = graphql.linkoutFunctionFactory();
69+
70+
// wait for the modal slot to load before adding an event listener
71+
window.onload = (event) => {
72+
const modal = document.getElementById('modal');
73+
modal.addEventListener('toggle', (event) => {
74+
const [{$el: link}, ...uikitComponents] = event.detail;
75+
const {type, ...linkoutData} = link.dataset;
76+
linkoutElement.getLinkouts({type, linkoutData});
77+
});
78+
};
79+
80+
</script>
81+
82+
</body>
83+
84+
</html>

index.html

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,23 @@
44

55
<head>
66
<meta charset="utf-8" />
7-
<title>@legumeinfo/web-component-graphql</title>
7+
<title>@legumeinfo/web-components-graphql</title>
8+
<!-- CSS framework -->
9+
<link rel="stylesheet" type="text/css" href="node_modules/uikit/dist/css/uikit.min.css">
10+
<script src="node_modules/uikit/dist/js/uikit.min.js"></script>
811
</head>
912

1013
<body>
11-
12-
<script type="module">
13-
14-
</script>
15-
14+
<div class="uk-container">
15+
<h1>@legumeinfo/web-components-graphql</h1>
16+
<p>
17+
<code>@legumeinfo/web-components-graphql</code> is a library that provides methods for loading data from the <a href="https://github.com/legumeinfo/graphql-server">LIS GraphQL Server</a> into the <a href="https://github.com/legumeinfo/web-components">LIS Web Components</a>.
18+
Below are links to examples of how to use the library with specific components.
19+
</p>
20+
<ul class="uk-list uk-list-disc">
21+
<li><a href="/examples/lis-gene-search-element.html">&lt;lis-gene-search-element&gt;</a></li>
22+
</ul>
23+
</div>
1624
</body>
1725

1826
</html>

rollup.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import replace from '@rollup/plugin-replace';
1111
export default {
1212
input: 'lib/index.js',
1313
output: {
14-
file: 'dist/web-component-graphql.min.js',
14+
file: 'dist/web-components-graphql.min.js',
1515
format: 'esm',
1616
},
1717
onwarn(warning) {

scripts/build-dependencies.cjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ const execSync = require('child_process').execSync;
88
const commands = [
99
'npm install --only=dev',
1010
'npm install',
11-
'npm run build'
11+
'npm run build',
12+
'npm run bundle',
1213
];
1314
const build_dir = path.resolve('./dep/web-components');
1415
const options = {cwd: build_dir};

src/web-components/graphql-web-components.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
import {LisGraphql, LisGraphqlConstructor} from '../graphql';
22
import {
3+
GeneSearchMiddleware,
34
geneSearchFormData,
45
geneSearchFunction,
5-
} from './lis-gene-search-element/queries';
6+
geneSearchMiddleware,
7+
} from './lis-gene-search-element';
8+
import {
9+
linkoutFunction,
10+
linkoutFunctionGene,
11+
linkoutFunctionGeneFamily,
12+
linkoutFunctionGwas,
13+
linkoutFunctionLocation,
14+
linkoutFunctionPanGeneSet,
15+
linkoutFunctionQtlStudy,
16+
} from './lis-linkout-element';
617

718
/**
819
* A mixin that adds Web Component queries to the `LisGraphql` base class.
@@ -13,14 +24,56 @@ export function LisGraphqlWebComponentsMixin<
1324
TBase extends LisGraphqlConstructor,
1425
>(Base: TBase) {
1526
return class LisGraphqlWebComponents extends Base {
27+
static readonly middleware = {
28+
geneSearch: geneSearchMiddleware,
29+
};
30+
1631
// LisGeneSearchElement
1732
geneSearchFormData = geneSearchFormData;
1833
geneSearchFormDataFactory = (): typeof geneSearchFormData => {
1934
return (...args) => this.geneSearchFormData(...args);
2035
};
2136
geneSearchFunction = geneSearchFunction;
22-
geneSearchFunctionFactory = (): typeof geneSearchFunction => {
23-
return (...args) => this.geneSearchFunction(...args);
37+
geneSearchFunctionFactory = (
38+
...middleware: GeneSearchMiddleware[]
39+
): typeof geneSearchFunction => {
40+
return (...args) => {
41+
let promise = this.geneSearchFunction(...args);
42+
middleware.forEach((m) => {
43+
promise = promise.then(m);
44+
});
45+
return promise;
46+
};
47+
};
48+
49+
// LisLinkoutElement
50+
linkoutFunction = linkoutFunction;
51+
linkoutFunctionFactory = (): typeof linkoutFunction => {
52+
return (...args) => this.linkoutFunction(...args);
53+
};
54+
linkoutFunctionGene = linkoutFunctionGene;
55+
linkoutFunctionGeneFactory = (): typeof linkoutFunctionGene => {
56+
return (...args) => this.linkoutFunctionGene(...args);
57+
};
58+
linkoutFunctionGeneFamily = linkoutFunctionGeneFamily;
59+
linkoutFunctionGeneFamilyFactory = (): typeof linkoutFunctionGeneFamily => {
60+
return (...args) => this.linkoutFunctionGeneFamily(...args);
61+
};
62+
linkoutFunctionGwas = linkoutFunctionGwas;
63+
linkoutFunctionGwasFactory = (): typeof linkoutFunctionGwas => {
64+
return (...args) => this.linkoutFunctionGwas(...args);
65+
};
66+
linkoutFunctionLocation = linkoutFunctionLocation;
67+
linkoutFunctionLocationFactory = (): typeof linkoutFunctionLocation => {
68+
return (...args) => this.linkoutFunctionLocation(...args);
69+
};
70+
linkoutFunctionPanGeneSet = linkoutFunctionPanGeneSet;
71+
linkoutFunctionPanGeneSetFactory = (): typeof linkoutFunctionPanGeneSet => {
72+
return (...args) => this.linkoutFunctionPanGeneSet(...args);
73+
};
74+
linkoutFunctionQtlStudy = linkoutFunctionQtlStudy;
75+
linkoutFunctionQtlStudyFactory = (): typeof linkoutFunctionQtlStudy => {
76+
return (...args) => this.linkoutFunctionQtlStudy(...args);
2477
};
2578
};
2679
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './middleware';
2+
export * from './queries';
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import {modalLink} from '../lis-modal-element';
2+
import {LisGeneSearchResults} from '@legumeinfo/web-components';
3+
4+
/** The signature of a middleware function for the `LisGeneSearchElement` component. */
5+
export type GeneSearchMiddleware = (
6+
results: LisGeneSearchResults,
7+
) => LisGeneSearchResults;
8+
9+
/**
10+
* Creates a middleware function that can be used with the `geneSearchFunctionFactory` function
11+
* to convert `identifiers` in `LisGeneSearchResults` into links that open a modal with the given
12+
* `modalId`.
13+
* @param {string} modalId - The HTML `id` of the target modal element.
14+
* @returns {GeneSearchMiddleware} The created middleware function.
15+
*/
16+
export function geneIdentifierModalLinkFactory(
17+
modalId: string,
18+
): GeneSearchMiddleware {
19+
return ({results: oldResults, ...pageInfo}) => {
20+
const results = oldResults.map(({identifier, ...geneInfo}) => {
21+
const data = {identifier, type: 'gene'};
22+
return {
23+
...geneInfo,
24+
identifier: modalLink(modalId, identifier, data),
25+
};
26+
});
27+
return {...pageInfo, results};
28+
};
29+
}
30+
31+
/**
32+
* Creates a middleware function that can be used with the `geneSearchFunctionFactory` function
33+
* to convert `locations` in `LisGeneSearchResults` into links that open a modal with the given
34+
* `modalId`.
35+
* @param {string} modalId - The HTML `id` of the target modal element.
36+
* @returns {GeneSearchMiddleware} The created middleware function.
37+
*/
38+
export function locationModalLinkFactory(
39+
modalId: string,
40+
): GeneSearchMiddleware {
41+
return ({results: oldResults, ...pageInfo}) => {
42+
const results = oldResults.map(({locations: oldLocations, ...geneInfo}) => {
43+
const locations = oldLocations.map((location) => {
44+
// extract the data from the location string made by genesDataToSearchResults
45+
const re = /(?<identifier>.+):(?<start>\d+)-(?<end>\d+)/;
46+
const data = location.match(re)?.groups;
47+
// NOTE: block will not execute unless shim is out of sync with regexp
48+
if (data === undefined) {
49+
return location;
50+
}
51+
data.type = 'location';
52+
return modalLink(modalId, location, data);
53+
});
54+
return {...geneInfo, locations};
55+
});
56+
return {...pageInfo, results};
57+
};
58+
}
59+
60+
/**
61+
* Creates a middleware function that can be used with the `geneSearchFunctionFactory` function
62+
* to convert `geneFamilyAssignments` in `LisGeneSearchResults` into links that open a modal with
63+
* the given `modalId`.
64+
* @param {string} modalId - The HTML `id` of the target modal element.
65+
* @returns {GeneSearchMiddleware} The created middleware function.
66+
*/
67+
export function geneFamilyAssignmentsModalLinkFactory(
68+
modalId: string,
69+
): GeneSearchMiddleware {
70+
return ({results: oldResults, ...pageInfo}) => {
71+
const results = oldResults.map(
72+
({geneFamilyAssignments: oldGeneFamilyAssignments, ...geneInfo}) => {
73+
const geneFamilyAssignments = oldGeneFamilyAssignments.map(
74+
(identifier) => {
75+
const data = {identifier, type: 'geneFamily'};
76+
return modalLink(modalId, identifier, data);
77+
},
78+
);
79+
return {
80+
...geneInfo,
81+
geneFamilyAssignments,
82+
};
83+
},
84+
);
85+
return {...pageInfo, results};
86+
};
87+
}
88+
89+
/**
90+
* Creates a middleware function that can be used with the `geneSearchFunctionFactory` function
91+
* to convert `panGeneSets` in `LisGeneSearchResults` into links that open a modal with the given
92+
* `modalId`.
93+
* @param {string} modalId - The HTML `id` of the target modal element.
94+
* @returns {GeneSearchMiddleware} The created middleware function.
95+
*/
96+
export function panGeneSetsModalLinkFactory(
97+
modalId: string,
98+
): GeneSearchMiddleware {
99+
return ({results: oldResults, ...pageInfo}) => {
100+
const results = oldResults.map(
101+
({panGeneSets: oldPanGeneSets, ...geneInfo}) => {
102+
const panGeneSets = oldPanGeneSets.map((identifier) => {
103+
const data = {identifier, type: 'panGeneSet'};
104+
return modalLink(modalId, identifier, data);
105+
});
106+
return {
107+
...geneInfo,
108+
panGeneSets,
109+
};
110+
},
111+
);
112+
return {...pageInfo, results};
113+
};
114+
}
115+
116+
/**
117+
* Creates all middleware functions that can be used with the `geneSearchFunctionFactory` function
118+
* to add modal links to `LisGeneSearchResults`.
119+
* @param {string} modalId - The HTML `id` of the target modal element.
120+
* @returns {GeneSearchMiddleware[]} The created middleware functions.
121+
*/
122+
export function allModalLinksFactory(modalId: string): GeneSearchMiddleware[] {
123+
return [
124+
geneIdentifierModalLinkFactory(modalId),
125+
locationModalLinkFactory(modalId),
126+
geneFamilyAssignmentsModalLinkFactory(modalId),
127+
panGeneSetsModalLinkFactory(modalId),
128+
];
129+
}
130+
131+
/** The geneSearch portion of `LisGraphqlWebComponents.middleware`. */
132+
export const geneSearchMiddleware = {
133+
geneIdentifierModalLinkFactory,
134+
geneFamilyAssignmentsModalLinkFactory,
135+
locationModalLinkFactory,
136+
panGeneSetsModalLinkFactory,
137+
allModalLinksFactory,
138+
};

src/web-components/lis-gene-search-element/queries.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type GetOrganismsData = {
4040
};
4141

4242
/**
43-
* Converts GraphQL `GetOrganismsData` into `LisGeneSearchFormData`.
43+
* Shims GraphQL `GetOrganismsData` into `LisGeneSearchFormData`.
4444
* @param {GetOrganismsData} data - The data portion of the `GraphqlResponse` for the `getOrganismsQuery`.
4545
* @returns {LisGeneSearchFormData} The data to be used by the `LisGeneSearchElement` Web Component.
4646
*/
@@ -83,7 +83,7 @@ function organismsDataToFormData(
8383
}
8484

8585
/**
86-
* Queries the GraphQL server for form data and converts the result into Web Component data.
86+
* Queries the GraphQL server for form data and shims the result into Web Component data.
8787
* This function should only be used as a method of `LisGraphqlWebComponentsMixin`.
8888
* @param {LisGeneSearchFormDataOptions} options - `LisGeneSearchFormDataFunction` options.
8989
* @returns {Promise<LisGeneSearchFormData>} A `Promise` that resolves to `LisGeneSearchFormData`.
@@ -172,7 +172,7 @@ type SearchGenesData = {
172172
};
173173

174174
/**
175-
* Converts GraphQL `SearchGenesData` into `LisGeneSearchResults`.
175+
* Shims GraphQL `SearchGenesData` into `LisGeneSearchResults`.
176176
* @param {SearchGenesData} data - The data portional of the `GraphqlResponse` for the `searchGenesQuery`.
177177
* @returns {LisGeneSearchResults} The data to be used by the `LisGeneSearchElement` Web Component.
178178
*/
@@ -220,7 +220,7 @@ function genesDataToSearchResults(data: SearchGenesData): LisGeneSearchResults {
220220
}
221221

222222
/**
223-
* Queries the GraphQL server for gene data and converts the result into Web Component data.
223+
* Queries the GraphQL server for gene data and shims the result into Web Component data.
224224
* This function should only be used as a method of `LisGraphqlWebComponentsMixin`.
225225
* @param {LisGeneSearchData} queryData - The data from which GraphQL query variables will be derived.
226226
* @param {LisGeneSearchOptions} options - `LisGeneSearchFunction` options.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './queries';

0 commit comments

Comments
 (0)