Skip to content

Commit

Permalink
adding URL history for expression/projection pages. Also renamed "sel…
Browse files Browse the repository at this point in the history
…ected_carts" param to be more specific (refresh cache in browser)
  • Loading branch information
adkinsrs committed Apr 24, 2024
1 parent 2e07b39 commit b430841
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
This creates the following top-level variables:
- selected_carts: The selected carts - An array of select cart share ids.
- selected_gene_lists: The selected carts - An array of select cart share ids.
- selected_genes: The selected individal genes, unique merge of all genes in carts and manually entered.
- gene_cart_data: The output of the apiCallsMixin.fetchGeneCartData() call, which needs to
happen in the login UI handler of the page.
Expand Down
22 changes: 11 additions & 11 deletions www/include/gene-collection-selector/gene-collection-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let gene_cart_label_index = {};
// Build this where key is share_id and values are arrays of gene symbols
let gene_cart_genes = {};

let selected_carts = new Set();
let selected_gene_lists = new Set();
let selected_genes = new Set();

document.addEventListener('DOMContentLoaded', () => {
Expand Down Expand Up @@ -98,7 +98,7 @@ document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#dropdown-gene-list-selector-label').innerHTML = 'Quick search using Gene Lists';

// and finally the related gene lists and genes
selected_carts.clear();
selected_gene_lists.clear();
selected_genes.clear();
});

Expand Down Expand Up @@ -140,7 +140,7 @@ document.addEventListener('DOMContentLoaded', () => {
row.querySelector('.ul-li').dataset.shareId = cart.share_id;
row.querySelector('.ul-li').dataset.genes = gene_cart_genes[cart.share_id].join(',');

if (selected_carts.has(cart.share_id)) {
if (selected_gene_lists.has(cart.share_id)) {
row.querySelector('i.toggler').classList.remove('mdi-plus');
row.querySelector('i.toggler').classList.add('mdi-check');
row.querySelector('.ul-li').classList.add('is-selected');
Expand Down Expand Up @@ -200,10 +200,10 @@ const setActiveGeneCart = (cart_row, mode) => {

// if adding or removing, update the inventory
if (mode === 'add') {
selected_carts.add(cart_row.dataset.shareId);
selected_gene_lists.add(cart_row.dataset.shareId);
selected_genes = new Set([...selected_genes, ...genes]);
} else if (mode === 'remove') {
selected_carts.delete(cart_row.dataset.shareId);
selected_gene_lists.delete(cart_row.dataset.shareId);

for (const gene of genes) {
selected_genes.delete(gene);
Expand Down Expand Up @@ -284,7 +284,7 @@ const setActiveGeneCartCategory = (category) => {
row.querySelector('.ul-li').dataset.genes = gene_cart_genes[entry.share_id].join(',');


if (selected_carts.has(entry.share_id)) {
if (selected_gene_lists.has(entry.share_id)) {
row.querySelector('i.toggler').classList.remove('mdi-plus');
row.querySelector('i.toggler').classList.add('mdi-check');
row.querySelector('.ul-li').classList.add('is-selected');
Expand All @@ -302,7 +302,7 @@ const selectGeneLists = (share_ids) => {
// reads the gene list share_ids passed and handles any UI and data updates to make
// them preselected
for (const share_id of share_ids) {
selected_carts.add(share_id);
selected_gene_lists.add(share_id);
selected_genes = new Set([...selected_genes, ...gene_cart_genes[share_id]]);
}

Expand All @@ -315,18 +315,18 @@ const updateGeneListSelectionPanel = () => {
// first empty it out, then populate it
selection_box.innerHTML = '';

for (const cart_share_id of selected_carts) {
for (const cart_share_id of selected_gene_lists) {
selection_box.innerHTML += `<span class="tag is-info is-light is-small m-1">${gene_cart_label_index[cart_share_id]}</span>`;
}
}

const updateGeneListSelectorLabel = () => {
// Updates the gene list select drop down label based on the current state of the selected_carts array
const selected_cart_count = selected_carts.size;
// Updates the gene list select drop down label based on the current state of the selected_gene_lists array
const selected_cart_count = selected_gene_lists.size;

if (selected_cart_count === 1) {
// It's the only one
const only_cart_id = Array.from(selected_carts)[0];
const only_cart_id = Array.from(selected_gene_lists)[0];
document.querySelector('#dropdown-gene-list-selector-label').innerHTML = gene_cart_label_index[only_cart_id];
} else if (selected_cart_count > 1) {
document.querySelector('#dropdown-gene-list-selector-label').innerHTML = `${selected_cart_count} gene lists selected`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
This creates the following top-level variables:
- selected_carts: The selected carts - An array of select cart share ids.
- selected_patterns: The selected individal patterns, unique merge of all patterns in carts and manually entered.
- pattern_cart_data: The output of the apiCallsMixin.fetchpatternCartData() call, which needs to
happen in the login UI handler of the page.
Expand Down
54 changes: 53 additions & 1 deletion www/js/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,14 @@ document.addEventListener('DOMContentLoaded', () => {

} catch (error) {
logErrorInConsole(error);
return;
}

const url = buildStateURL();

// add to state history
history.pushState(null, '', url);

});

// handle when the organism-selector select box is changed
Expand Down Expand Up @@ -176,6 +183,51 @@ document.addEventListener('DOMContentLoaded', () => {
});
});

/**
* Builds the URL for a GET request based on the current state.
* @returns {string} The URL string.
*/
const buildStateURL = () => {

// Create a new URL object (with no search params)
const url = new URL('/expression.html', window.location.origin);

// add the manually-entered genes
// TODO: need to combine selected_genes here to accommodate the case where a gene cart
// chosen but the individual genes removed.

const manuallyEnteredGenes = Array.from(manually_entered_genes);
if (manuallyEnteredGenes.length > 0) {
url.searchParams.append('gene_symbol', manuallyEnteredGenes.join(','));
}

// are we doing exact matches?
if (document.querySelector('#gene-search-exact-match').checked) {
url.searchParams.append('gene_symbol_exact_match', '1');
}

// get the value of the single-multi radio box
const singleMulti = document.querySelector('input[name="single-multi"]:checked').value;
url.searchParams.append('is_multigene', singleMulti === 'single' ? '0' : '1');

// add the gene lists
// TODO: This will only be for labeling purposes, since individual genes could have been
// deselected within
if (selected_gene_lists.size > 0) {
const geneCartShareIds = Array.from(selected_gene_lists);
url.searchParams.append('gene_lists', geneCartShareIds.join(','));
}

// add the dataset collections
if (datasetShareId) {
url.searchParams.append('share_id', datasetShareId);
} else if (selected_dc_share_id) {
url.searchParams.append('layout_id', selected_dc_share_id);
}

return url.toString();
}

/**
* Fetches gene annotations.
* @param {Function} callback - The callback function to be executed after fetching gene annotations.
Expand Down Expand Up @@ -284,7 +336,7 @@ const handlePageSpecificLoginUIUpdates = async (event) => {
// Now, if URL params were passed and we have both genes and a dataset collection,
// run the search
if (urlParamsPassed) {
if (selected_dc_share_id && selected_genes.size > 0) {
if ((datasetShareId || selected_dc_share_id) && selected_genes.size > 0) {
document.querySelector('#submit-expression-search').click();
}
}
Expand Down
9 changes: 5 additions & 4 deletions www/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ document.addEventListener('DOMContentLoaded', () => {
// add the manually-entered genes
// TODO: need to combine selected_genes here to accommodate the case where a gene cart
// chosen but the individual genes removed.
if (manually_entered_genes.length > 0) {
url.searchParams.append('gene_symbol', manually_entered_genes.join(','));
const manuallyEnteredGenes = Array.from(manually_entered_genes);
if (manuallyEnteredGenes.length > 0) {
url.searchParams.append('gene_symbol', manuallyEnteredGenes.join(','));
}

// are we doing exact matches?
Expand All @@ -63,8 +64,8 @@ document.addEventListener('DOMContentLoaded', () => {
// add the gene lists
// TODO: This will only be for labeling purposes, since individual genes could have been
// deselected within
if (selected_carts.size > 0) {
const geneCartShareIds = Array.from(selected_carts);
if (selected_gene_lists.size > 0) {
const geneCartShareIds = Array.from(selected_gene_lists);
url.searchParams.append('gene_lists', geneCartShareIds.join(','));
}

Expand Down
42 changes: 41 additions & 1 deletion www/js/projection.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,13 @@ const handlePageSpecificLoginUIUpdates = async (event) => {

} catch (error) {
logErrorInConsole(error);
return;
}

const url = buildStateUrl();
// add to state history
history.pushState(null, '', url);

});

// Change the svg scoring method when select element is changed
Expand Down Expand Up @@ -152,7 +158,7 @@ const handlePageSpecificLoginUIUpdates = async (event) => {
// Now, if URL params were passed and we have both patterns and a dataset collection,
// run the search
if (urlParamsPassed) {
if (selected_dc_share_id && selectedPattern.shareId !== null && selectedPattern.selectedWeights.length > 0) {
if ((datasetShareId || selected_dc_share_id) && selectedPattern.shareId !== null && selectedPattern.selectedWeights.length > 0) {
document.querySelector('#submit-projection-search').click();
}
}
Expand All @@ -170,6 +176,40 @@ const handlePageSpecificLoginUIUpdates = async (event) => {
observer.observe(document.getElementById("dropdown-dc-selector-label"), { childList: true });
}

/**
* Builds the state URL with the selected parameters.
* @returns {string} The state URL.
*/
const buildStateUrl = () => {

// Create a new URL object (with no search params)
const url = new URL('/projection.html', window.location.origin);

// Add the projection algorithm to the URL
const algorithm = document.getElementById('algorithm').value;
url.searchParams.set('projection_algorithm', algorithm);

// Add the multipattern_plots value to the URL
const multipatternPlots = document.querySelector('#single-multi-multi').checked ? 1 : 0;
url.searchParams.set('multipattern_plots', multipatternPlots);

// Add the pattern source to the URL
url.searchParams.set('projection_source', selectedPattern.shareId);

// Add the dataset collection to the URL
if (datasetShareId) {
url.searchParams.append('share_id', datasetShareId);
} else if (selected_dc_share_id) {
url.searchParams.append('layout_id', selected_dc_share_id);
}

// Add the selected pattern weights to the URL
const weights = selectedPattern.selectedWeights.map((w) => w.label);
url.searchParams.set('projection_patterns', weights.join(','));

return url.toString();
}

/**
* Sorts an array of strings in ascending order based on the numeric value at the end of each string. (i.e. PC1, PC2, etc.)
*
Expand Down

0 comments on commit b430841

Please sign in to comment.