diff --git a/www/cgi/get_user_gene_carts.cgi b/www/cgi/get_user_gene_carts.cgi index dddfa526..74d98a0d 100755 --- a/www/cgi/get_user_gene_carts.cgi +++ b/www/cgi/get_user_gene_carts.cgi @@ -59,6 +59,8 @@ lib_path = os.path.abspath(os.path.join('..', '..', 'lib')) sys.path.append(lib_path) import geardb +GENE_LIST_TYPES = ["unweighted-list", "weighted-list", "labeled-list"] + def main(): print('Content-Type: application/json\n\n') @@ -96,9 +98,8 @@ def main(): if group_by_type and not group_by_type == "false": # Group all cart results by their cart type and return - gctypes = ["unweighted-list", "weighted-list", "labeled-list"] gctypes_result = dict() - for cart_type in gctypes: + for cart_type in GENE_LIST_TYPES: subset_domain_carts = filter_by_cart_type(domain_carts, cart_type) subset_user_carts = filter_by_cart_type(user_carts, cart_type) subset_group_carts = filter_by_cart_type(group_carts, cart_type) @@ -117,13 +118,16 @@ def main(): print(json.dumps(gctypes_result, default=lambda o: o.__dict__)) sys.exit(0) - if len(str(filter_cart_type)) > 0 and filter_cart_type != 'undefined': + if filter_cart_type and filter_cart_type in GENE_LIST_TYPES: domain_carts = filter_by_cart_type(domain_carts, filter_cart_type) user_carts = filter_by_cart_type(user_carts, filter_cart_type) group_carts = filter_by_cart_type(group_carts, filter_cart_type) recent_carts = filter_by_cart_type(recent_carts, filter_cart_type) shared_carts = filter_by_cart_type(shared_carts, filter_cart_type) public_carts = filter_by_cart_type(public_carts, filter_cart_type) + elif filter_cart_type and filter_cart_type not in GENE_LIST_TYPES: + # log warning that the cart type is not valid and return all carts + print("WARNING: Invalid cart type: " + filter_cart_type, file=sys.stderr) result = { 'domain_carts':domain_carts, 'group_carts':group_carts, diff --git a/www/cgi/get_user_layouts.cgi b/www/cgi/get_user_layouts.cgi index 06eeb77c..113b1fa6 100755 --- a/www/cgi/get_user_layouts.cgi +++ b/www/cgi/get_user_layouts.cgi @@ -102,6 +102,7 @@ def main(): result['user_layouts'] = geardb.LayoutCollection(include_datasets=bool_include_members).get_by_user(user) result['group_layouts'] = geardb.LayoutCollection(include_datasets=bool_include_members).get_by_users_groups(user) + # NOTE: "null" values can happen but will be queried out in the SQL (unless there is a actual "null" share_id) if layout_share_id: result['shared_layouts'] = geardb.LayoutCollection(include_datasets=bool_include_members).get_by_share_id(layout_share_id) diff --git a/www/include/dataset-collection-selector/dataset-collection-selector.js b/www/include/dataset-collection-selector/dataset-collection-selector.js index 66d3e82a..3a4e9fd9 100644 --- a/www/include/dataset-collection-selector/dataset-collection-selector.js +++ b/www/include/dataset-collection-selector/dataset-collection-selector.js @@ -76,16 +76,17 @@ document.addEventListener('DOMContentLoaded', () => { }); /** - * Fetches dataset collections from the API. + * Fetches dataset collections. * - * @param {boolean} includeMembers - Whether to include members in the dataset collections. + * @param {string} [shareId=null] - The share ID of the dataset collection. * @returns {Promise} - A promise that resolves when the dataset collections are fetched. + * @throws {Error} - If an error occurs during the fetch. */ -const fetchDatasetCollections = async (includeMembers=false) => { - const layoutShareId = selected_dc_share_id || null; +const fetchDatasetCollections = async (shareId=null) => { + const layoutShareId = shareId || selected_dc_share_id || null; try { - dataset_collection_data = await apiCallsMixin.fetchDatasetCollections({includeMembers, layoutShareId}); + dataset_collection_data = await apiCallsMixin.fetchDatasetCollections({includeMembers: false, layoutShareId}); document.querySelector('#dropdown-dc').classList.remove('is-loading'); document.querySelector('#dropdown-dc').classList.remove('is-disabled'); diff --git a/www/include/gene-collection-selector/gene-collection-selector.js b/www/include/gene-collection-selector/gene-collection-selector.js index 812387c9..ba78776d 100644 --- a/www/include/gene-collection-selector/gene-collection-selector.js +++ b/www/include/gene-collection-selector/gene-collection-selector.js @@ -160,11 +160,13 @@ document.addEventListener('DOMContentLoaded', () => { /** * Fetches gene cart data from the server. - * @returns {Promise} A promise that resolves when the gene cart data is fetched. + * + * @param {string|null} shareId - The share ID of the gene list. Default is null. + * @returns {Promise} - A promise that resolves when the gene cart data is fetched successfully. */ -const fetchGeneCartData = async () => { +const fetchGeneCartData = async (shareId=null) => { try { - gene_cart_data = await apiCallsMixin.fetchGeneCarts({cartType: 'unweighted-list', includeMembers: false}); + gene_cart_data = await apiCallsMixin.fetchGeneCarts({gcShareId: shareId, cartType: 'unweighted-list', includeMembers: false}); document.querySelector('#dropdown-gene-lists').classList.remove('is-loading'); document.querySelector('#dropdown-gene-lists').classList.remove('is-disabled'); diff --git a/www/include/pattern-collection-selector/pattern-collection-selector.js b/www/include/pattern-collection-selector/pattern-collection-selector.js index acb1e8a8..888989af 100644 --- a/www/include/pattern-collection-selector/pattern-collection-selector.js +++ b/www/include/pattern-collection-selector/pattern-collection-selector.js @@ -246,13 +246,17 @@ const createPatternListItem = (item, cart) => { }); } + /** - * Fetches patterns data asynchronously and executes a callback function. - * @returns {Promise} - A promise that resolves when the patterns data is fetched successfully. + * Fetches patterns data. + * + * @param {string|null} shareId - The gene list (pattern) share ID. + * @returns {Promise} - A promise that resolves when the patterns data is fetched. + * @throws {Error} - If an error occurs during the fetch. */ -const fetchPatternsData = async () => { +const fetchPatternsData = async (shareId=null) => { try { - patternsCartData = await apiCallsMixin.fetchGeneCarts({includeMembers: false}); + patternsCartData = await apiCallsMixin.fetchGeneCarts({gcShareId: shareId, includeMembers: false}); flatPatternsCartData = [...patternsCartData.domain_carts, ...patternsCartData.group_carts, ...patternsCartData.public_carts, ...patternsCartData.user_carts, ...patternsCartData.shared_carts, ...patternsCartData.recent_carts] document.getElementById('dropdown-pattern-lists').classList.remove('is-loading'); diff --git a/www/js/common.v2.js b/www/js/common.v2.js index 7ecb51a0..24dfcb5d 100644 --- a/www/js/common.v2.js +++ b/www/js/common.v2.js @@ -981,7 +981,6 @@ const apiCallsMixin = { const {data} = await axios.post("cgi/get_users_layout_members.cgi", convertToFormData(payload)); return data; }, - /** * Fetches dataset collections. * @@ -991,12 +990,8 @@ const apiCallsMixin = { * @param {boolean} [options.includeMembers=true] - Whether to include collection members in output. * @returns {Promise} - A promise that resolves to the fetched dataset collections. */ - async fetchDatasetCollections({layoutShareId=null, noDomain=0, includeMembers=true}) { - const payload = {session_id: this.sessionId, layout_share_id: layoutShareId, no_domain: noDomain}; - - // is passed as string in the payload - payload.include_members = includeMembers ? 1 : 0; - + async fetchDatasetCollections({layoutShareId=null, noDomain=0, includeMembers=true}={}) { + const payload = {session_id: this.sessionId, layout_share_id: layoutShareId, no_domain: noDomain, include_members: includeMembers ? 1 : 0}; const {data} = await axios.post("cgi/get_user_layouts.cgi", convertToFormData(payload)); return data; }, @@ -1119,19 +1114,15 @@ const apiCallsMixin = { return data; }, /** - * Fetches gene carts based on the specified cart type. - * @param {string} cartType - The type of gene cart to fetch. - * @returns {Promise} - A promise that resolves to the fetched gene carts data. + * Fetches gene carts. + * @param {Object} options - The options for fetching gene carts. + * @param {string|null} options.gcShareId - The share ID of the gene cart. + * @param {string|null} options.cartType - The type of the gene cart. + * @param {boolean} [options.includeMembers=true] - Whether to include members in the gene cart. + * @returns {Promise} The fetched gene carts. */ - async fetchGeneCarts({cartType=null, includeMembers=true}) { - const payload = {session_id: this.sessionId}; - if (cartType) { - payload.cart_type = cartType; - } - - // is passed as string in the payload - payload.include_members = includeMembers ? 1 : 0; - + async fetchGeneCarts({gcShareId=null, cartType=null, includeMembers=true}) { + const payload = {session_id: this.sessionId, cart_type: cartType, share_id: gcShareId, include_members: includeMembers ? 1 : 0}; const {data} = await axios.post(`/cgi/get_user_gene_carts.cgi`, convertToFormData(payload)); return data; }, diff --git a/www/js/dataset_explorer.js b/www/js/dataset_explorer.js index aa9e4bc2..3d80b04e 100644 --- a/www/js/dataset_explorer.js +++ b/www/js/dataset_explorer.js @@ -2586,7 +2586,7 @@ const updateDatasetCollectionButtons = (collection=null) => { const updateDatasetCollections = async () => { // Fetch the dataset collections, which will update the dataset collection selector - await fetchDatasetCollections(false) + await fetchDatasetCollections() // Uses dataset-collection-selector.js variable const datasetCollectionData = dataset_collection_data; diff --git a/www/js/expression.js b/www/js/expression.js index 465bb81c..375c251b 100644 --- a/www/js/expression.js +++ b/www/js/expression.js @@ -357,11 +357,13 @@ const handlePageSpecificLoginUIUpdates = async (event) => { // Wait until all pending API calls have completed before checking if we need to search document.getElementById("submit-expression-search").classList.add("is-loading"); try { + const geneListShareId = getUrlParameter('gene_cart_share_id') + // SAdkins note - Promise.all fails fast, // but Promise.allSettled waits until all resolve/reject and lets you know which ones failed const [cart_result, dc_result, org_result] = await Promise.all([ - fetchGeneCartData(), - fetchDatasetCollections(false), + fetchGeneCartData(geneListShareId), + fetchDatasetCollections(layoutShareId), fetchOrganisms() ]); } catch (error) { diff --git a/www/js/index.js b/www/js/index.js index b18a767e..9b848020 100644 --- a/www/js/index.js +++ b/www/js/index.js @@ -162,7 +162,7 @@ const handlePageSpecificLoginUIUpdates = async (event) => { document.getElementById("submit-expression-search").classList.add("is-loading"); await Promise.all([ fetchGeneCartData(), - fetchDatasetCollections(false) + fetchDatasetCollections() ]); document.getElementById("submit-expression-search").classList.remove("is-loading"); diff --git a/www/js/projection.js b/www/js/projection.js index 7b777c76..8c45a092 100644 --- a/www/js/projection.js +++ b/www/js/projection.js @@ -137,14 +137,16 @@ const handlePageSpecificLoginUIUpdates = async (event) => { // Wait until all pending API calls have completed before checking if we need to search document.getElementById("submit-projection-search").classList.add("is-loading"); try { + const pattern = getUrlParameter('projection_source', urlParams); + // SAdkins note - Promise.all fails fast, // but Promise.allSettled waits until all resolve/reject and lets you know which ones failed const [cartResult, dcResult,] = await Promise.all([ - fetchPatternsData(), - fetchDatasetCollections(false), + fetchPatternsData(pattern), + fetchDatasetCollections(layoutShareId), ]); - await parseDatasetCollectionURLParams(); + parseDatasetCollectionURLParams(); await parsePatternCartURLParams(); // Should help with lining things up on index page