From 5afeec60e1286d6cb3b0ec4ae593e546d3527982 Mon Sep 17 00:00:00 2001 From: Gordon Krieger Date: Tue, 17 Dec 2024 15:22:21 -0500 Subject: [PATCH] first pass at adding scoping to beacon UI --- .../Beacon/BeaconCommon/BeaconQueryFormUi.tsx | 21 +++++++++++++------ src/js/features/beacon/beacon.store.ts | 8 ++++--- src/js/features/beacon/utils.ts | 9 +++++++- src/js/types/beacon.ts | 2 ++ 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/js/components/Beacon/BeaconCommon/BeaconQueryFormUi.tsx b/src/js/components/Beacon/BeaconCommon/BeaconQueryFormUi.tsx index 2e92b6f2..06ee10f8 100644 --- a/src/js/components/Beacon/BeaconCommon/BeaconQueryFormUi.tsx +++ b/src/js/components/Beacon/BeaconCommon/BeaconQueryFormUi.tsx @@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { Button, Card, Col, Form, Row } from 'antd'; import { useIsAuthenticated } from 'bento-auth-js'; import { useAppDispatch, useQueryWithAuthIfAllowed, useTranslationFn } from '@/hooks'; +import { useSelectedScope } from '@/features/metadata/hooks'; import VariantsForm from './VariantsForm'; import Filters from './Filters'; import SearchToolTip from './ToolTips/SearchToolTip'; @@ -55,6 +56,8 @@ const BeaconQueryFormUi = ({ const dispatch = useAppDispatch(); const isAuthenticated = useIsAuthenticated(); + const { scope } = useSelectedScope(); + const formInitialValues = useMemo( () => ({ 'Assembly ID': beaconAssemblyIds.length === 1 && beaconAssemblyIds[0], @@ -67,12 +70,18 @@ const BeaconQueryFormUi = ({ const showError = hasError && !errorAlertClosed; const requestPayload = useCallback( - (query: PayloadVariantsQuery, payloadFilters: PayloadFilter[]): BeaconQueryPayload => ({ - meta: { apiVersion: '2.0.0' }, - query: { requestParameters: { g_variant: query }, filters: payloadFilters }, - bento: { showSummaryStatistics: true }, - }), - [] + (query: PayloadVariantsQuery, payloadFilters: PayloadFilter[]): BeaconQueryPayload => { + const payload: BeaconQueryPayload = { + meta: { apiVersion: '2.0.0' }, + query: { requestParameters: { g_variant: query }, filters: payloadFilters }, + bento: { showSummaryStatistics: true }, + }; + if (scope.dataset) { + payload['datasets'] = { datasetIds: [scope.dataset] }; + } + return payload; + }, + [scope] ); const launchEmptyQuery = useCallback( diff --git a/src/js/features/beacon/beacon.store.ts b/src/js/features/beacon/beacon.store.ts index 55e84691..d17b4bb1 100644 --- a/src/js/features/beacon/beacon.store.ts +++ b/src/js/features/beacon/beacon.store.ts @@ -3,15 +3,16 @@ import axios from 'axios'; import { makeAuthorizationHeader } from 'bento-auth-js'; import { EMPTY_DISCOVERY_RESULTS } from '@/constants/searchConstants'; -import { BEACON_INDIVIDUALS_ENDPOINT, BEACON_INFO_ENDPOINT } from '@/features/beacon/constants'; +import { BEACON_INFO_ENDPOINT } from '@/features/beacon/constants'; import type { RootState } from '@/store'; import type { BeaconConfigResponse, BeaconAssemblyIds, BeaconQueryResponse, BeaconQueryPayload } from '@/types/beacon'; import type { DiscoveryResults } from '@/types/data'; import { beaconApiError, errorMsgOrDefault } from '@/utils/beaconApiError'; import { printAPIError } from '@/utils/error.util'; -import { extractBeaconDiscoveryOverview } from './utils'; +import { extractBeaconDiscoveryOverview, scopedBeaconIndividualsUrl } from './utils'; +// config response is not scoped export const getBeaconConfig = createAsyncThunk( 'beacon/getBeaconConfig', (_, { rejectWithValue }) => { @@ -33,9 +34,10 @@ export const makeBeaconQuery = createAsyncThunk< { state: RootState; rejectValue: string } >('beacon/makeBeaconQuery', async (payload, { getState, rejectWithValue }) => { const token = getState().auth.accessToken; + const projectId = getState().metadata.selectedScope.scope.project; const headers = makeAuthorizationHeader(token); return axios - .post(BEACON_INDIVIDUALS_ENDPOINT, payload, { headers: headers as Record }) + .post(scopedBeaconIndividualsUrl(projectId), payload, { headers: headers as Record }) .then((res) => res.data) .catch(beaconApiError(rejectWithValue)); }); diff --git a/src/js/features/beacon/utils.ts b/src/js/features/beacon/utils.ts index 87e2a698..d282977e 100644 --- a/src/js/features/beacon/utils.ts +++ b/src/js/features/beacon/utils.ts @@ -1,7 +1,9 @@ -import { BEACON_NETWORK_URL } from '@/config'; +import { BEACON_URL, BEACON_NETWORK_URL } from '@/config'; +import { BEACON_INDIVIDUALS_PATH } from './constants'; import type { BeaconAssemblyIds, BeaconNetworkResponses, BeaconQueryResponse } from '@/types/beacon'; import type { ChartData, DiscoveryResults, OptionalDiscoveryResults } from '@/types/data'; import type { NetworkBeacon } from '@/types/beaconNetwork'; +import type { Project } from '@/types/metadata'; import { serializeChartData } from '@/utils/chart'; type TempChartObject = Record; @@ -84,3 +86,8 @@ export const extractBeaconDiscoveryOverview = (response: BeaconQueryResponse): O export const atLeastOneNetworkResponseIsPending = (responses: BeaconNetworkResponses) => Object.values(responses).some((r) => r.isFetchingQueryResponse); + +export const scopedBeaconIndividualsUrl = (projectId: Project['identifier'] | undefined): string => { + const projectPath: string = projectId ? '/' + projectId : ''; + return BEACON_URL + projectPath + BEACON_INDIVIDUALS_PATH; +}; diff --git a/src/js/types/beacon.ts b/src/js/types/beacon.ts index 92a03a5d..1dbdda35 100644 --- a/src/js/types/beacon.ts +++ b/src/js/types/beacon.ts @@ -4,6 +4,7 @@ import type { Datum } from '@/types/overviewResponse'; import type { makeBeaconQuery } from '@/features/beacon/beacon.store'; import type { beaconNetworkQuery } from '@/features/beacon/network.store'; import type { OptionalDiscoveryResults } from '@/types/data'; +import type { Dataset } from '@/types/metadata'; // ---------------------------- // form handling @@ -74,6 +75,7 @@ export interface BeaconQueryPayload { meta: { apiVersion: string }; query: { requestParameters: { g_variant: PayloadVariantsQuery }; filters: PayloadFilter[] }; bento?: { showSummaryStatistics: boolean }; + datasets?: { datasetIds: Dataset['identifier'][] }; } export type BeaconQueryAction = ActionCreator<