From d2afa2005616d8076b074b044b0e74de7642382d Mon Sep 17 00:00:00 2001 From: Julian Date: Tue, 10 Oct 2023 08:37:56 -0400 Subject: [PATCH 01/48] temporal changes --- main.go | 83 ++++++++++++++++++++ src/js/components/Overview/LastIngestion.tsx | 2 +- src/js/components/TabbedDashboard.tsx | 4 + src/js/constants/configConstants.ts | 2 + src/js/features/datasets/datasets.store.ts | 52 ++++++++++++ src/js/features/ingestion/ingestion.store.ts | 2 + src/js/store.ts | 2 + 7 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/js/features/datasets/datasets.store.ts diff --git a/main.go b/main.go index 85c30d7f..8392816e 100644 --- a/main.go +++ b/main.go @@ -24,6 +24,7 @@ const ConfigLogTemplate = `Config -- Client Name: %s Katsu URL: %v WES URL: %v + Gohan URL: %v Bento Portal Url: %s Port: %d Translated: %t @@ -38,6 +39,7 @@ type BentoConfig struct { ClientName string `envconfig:"BENTO_PUBLIC_CLIENT_NAME"` KatsuUrl string `envconfig:"BENTO_PUBLIC_KATSU_URL"` WesUrl string `envconfig:"BENTO_PUBLIC_WES_URL"` + GohanUrl string `envconfig:"BENTO_PUBLIC_GOHAN_URL"` BentoPortalUrl string `envconfig:"BENTO_PUBLIC_PORTAL_URL"` Port int `envconfig:"INTERNAL_PORT" default:"8090"` Translated bool `envconfig:"BENTO_PUBLIC_TRANSLATED" default:"true"` @@ -115,6 +117,7 @@ func main() { cfg.ClientName, cfg.KatsuUrl, cfg.WesUrl, + cfg.GohanUrl, cfg.BentoPortalUrl, cfg.Port, cfg.Translated, @@ -131,6 +134,8 @@ func main() { var req *http.Request var err error + fmt.Println("urlXXXXX: ", url) + if qs != nil { req, err = http.NewRequest("GET", fmt.Sprintf("%s?%s", url, qs.Encode()), nil) if err != nil { @@ -184,6 +189,14 @@ func main() { return c.JSON(http.StatusOK, result) } + gohanRequest := func(path string, qs url.Values, c echo.Context, rf responseFormatterFunc) error { + result, err := genericRequestJsonOnly(fmt.Sprintf("%s%s", cfg.GohanUrl, path), qs, c, rf) + if err != nil { + return err + } + return c.JSON(http.StatusOK, result) + } + katsuRequestBasic := func(path string, c echo.Context) error { return katsuRequest(path, nil, c, jsonDeserialize) } @@ -208,6 +221,28 @@ func main() { return wesRequest("/runs", qs, c, jsonDeserialize) } + gohanRequestPublic := func(c echo.Context) error { + + // Construct the path using the extracted dataset ID. + path := fmt.Sprintf("/data-types") + + // Debug print statements to verify the constructed path and the GohanUrl. + fmt.Fprintf(os.Stderr, "pathCFCFCFCF: %s\n", path) + fmt.Println("DEBUG: cfg.GohanUrl =", cfg.GohanUrl) + + // Make a request to the Gohan service and deserialize the response. + err := gohanRequest(path, nil, c, jsonDeserialize) + if err != nil { + // Return the error if there is one. + return err + } + + // If everything is successful, return a success status to the caller. + return c.JSON(http.StatusOK, map[string]string{ + "message": "Success", + }) + } + fetchAndSetKatsuPublic := func(c echo.Context, katsuCache *cache.Cache) (JsonLike, error) { fmt.Println("'publicOverview' not found or expired in 'katsuCache' - fetching") publicOverviewInterface, err := genericRequestJsonOnly( @@ -361,6 +396,8 @@ func main() { e.GET("/wes-runs", wesRequestWithDetailsAndPublic) + e.GET("/gohan/data-types", gohanRequestPublic) + e.GET("/provenance", func(c echo.Context) error { // Query Katsu for datasets provenance return katsuRequestBasic("/api/public_dataset", c) @@ -382,6 +419,52 @@ func main() { return c.String(http.StatusOK, string(data)) }) + e.GET("/datasets", func(c echo.Context) error { + data, err := katsuRequestFormattedData("/api/datasets", c) + if err != nil { + return err + } + + fmt.Println("FFFFF") + fmt.Println("data: ", string(data)) + fmt.Println("FFFFF") + + return c.String(http.StatusOK, string(data)) + + }) + + e.GET("/datasets/:id/data-types/:data-type/public", func(c echo.Context) error { + id := c.Param("id") + dataType := c.Param("data-type") + relativeUrl := fmt.Sprintf("/datasets/%s/data-types/%s/public", id, dataType) + + data, err := katsuRequestFormattedData(relativeUrl, c) + if err != nil { + return err + } + + fmt.Println("XXXXXXX") + + fmt.Println("data: ", string(data)) + + fmt.Println("XXXXXXX") + + return c.String(http.StatusOK, string(data)) + }) + + e.GET("/katsu-data-types", func(c echo.Context) error { + data, err := katsuRequestFormattedData("/data-types", c) + if err != nil { + return err + } + + fmt.Println("XXXXXXX") + fmt.Println("data: ", string(data)) + fmt.Println("XXXXXXX") + + return c.String(http.StatusOK, string(data)) + }) + // Run e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.Port))) } diff --git a/src/js/components/Overview/LastIngestion.tsx b/src/js/components/Overview/LastIngestion.tsx index ccb01c37..46ed6b03 100644 --- a/src/js/components/Overview/LastIngestion.tsx +++ b/src/js/components/Overview/LastIngestion.tsx @@ -32,7 +32,7 @@ const LastIngestionInfo: React.FC = () => { return ( - {t('Latest Data Ingestion')} + {t('Latest Data IngestionX')} {hasData ? ( Object.entries(lastEndTimesByDataType).map(([dataType, endTime]) => ( diff --git a/src/js/components/TabbedDashboard.tsx b/src/js/components/TabbedDashboard.tsx index 3a1f8a6e..a23bd2b7 100644 --- a/src/js/components/TabbedDashboard.tsx +++ b/src/js/components/TabbedDashboard.tsx @@ -10,8 +10,10 @@ import { makeGetAboutRequest } from '@/features/content/content.store'; import { makeGetDataRequestThunk } from '@/features/data/data.store'; import { makeGetSearchFields } from '@/features/search/query.store'; import { makeGetProvenanceRequest } from '@/features/provenance/provenance.store'; +import {fetchDatasets } from '@/features/datasets/datasets.store'; import { makeGetIngestionDataRequest } from '@/features/ingestion/ingestion.store'; import { getBeaconConfig } from '@/features/beacon/beaconConfig.store'; +import {makeGetDataTypes } from '@/features/dataTypes/dataTypes.store'; import Loader from './Loader'; import PublicOverview from './Overview/PublicOverview'; @@ -36,6 +38,8 @@ const TabbedDashboard = () => { dispatch(makeGetSearchFields()); dispatch(makeGetProvenanceRequest()); dispatch(makeGetIngestionDataRequest()); + dispatch(fetchDatasets()); + dispatch(makeGetDataTypes()); }, []); const isFetchingOverviewData = useAppSelector((state) => state.data.isFetchingData); diff --git a/src/js/constants/configConstants.ts b/src/js/constants/configConstants.ts index b59e6650..f3eb98af 100644 --- a/src/js/constants/configConstants.ts +++ b/src/js/constants/configConstants.ts @@ -6,6 +6,8 @@ export const searchFieldsUrl = '/fields'; export const katsuUrl = '/katsu'; export const provenanceUrl = '/provenance'; export const lastIngestionsUrl = '/wes-runs'; +export const datasetsUrl = '/datasets'; +export const datasetDataTypePublicUrl = '/datasets/:id/data-types/:data-type/public'; export const DEFAULT_TRANSLATION = 'default_translation'; export const NON_DEFAULT_TRANSLATION = 'translation'; diff --git a/src/js/features/datasets/datasets.store.ts b/src/js/features/datasets/datasets.store.ts new file mode 100644 index 00000000..5ccfb31a --- /dev/null +++ b/src/js/features/datasets/datasets.store.ts @@ -0,0 +1,52 @@ +import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; +import axios from 'axios'; +import { datasetsUrl } from '@/constants/configConstants'; +import { printAPIError } from '@/utils/error.util'; + +// Type definition for Dataset response. You need to define this according to the response structure +interface DatasetResponse { + // Define the structure based on the response of the /datasets endpoint. + // Here's a placeholder type; replace with actual fields + id: string; + name: string; + description: string; +} + +export const fetchDatasets = createAsyncThunk( + 'datasets/fetchDatasets', + (_, { rejectWithValue }) => + axios + .get(datasetsUrl) + .then((res) => res.data) + .catch(printAPIError(rejectWithValue)) +); + +export interface DatasetsState { + isFetchingDatasets: boolean; + datasets: DatasetResponse[]; +} + +const initialState: DatasetsState = { + isFetchingDatasets: false, + datasets: [], +}; + +const DatasetsStore = createSlice({ + name: 'datasets', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(fetchDatasets.pending, (state) => { + state.isFetchingDatasets = true; + }); + builder.addCase(fetchDatasets.fulfilled, (state, { payload }: PayloadAction) => { + state.datasets = payload; + state.isFetchingDatasets = false; + }); + builder.addCase(fetchDatasets.rejected, (state) => { + state.isFetchingDatasets = false; + }); + }, +}); + +export default DatasetsStore.reducer; diff --git a/src/js/features/ingestion/ingestion.store.ts b/src/js/features/ingestion/ingestion.store.ts index 2ce4d686..0fb8964f 100644 --- a/src/js/features/ingestion/ingestion.store.ts +++ b/src/js/features/ingestion/ingestion.store.ts @@ -39,6 +39,8 @@ const IngestionDataStore = createSlice({ state.ingestionData = payload; payload.forEach((ingestion) => { const dataType = ingestion.details.request.tags.workflow_metadata.data_type; + console.log("losDATATipes",dataType); + //// here use dataType const endTime = ingestion.details.run_log.end_time; const previousEndTime = state.lastEndTimesByDataType[dataType]; if (!previousEndTime || new Date(endTime) > new Date(previousEndTime)) { diff --git a/src/js/store.ts b/src/js/store.ts index 313180b1..6ef8adbb 100644 --- a/src/js/store.ts +++ b/src/js/store.ts @@ -4,6 +4,7 @@ import configReducer from '@/features/config/config.store'; import contentReducer from '@/features/content/content.store'; import dataReducer from '@/features/data/data.store'; import queryReducer from '@/features/search/query.store'; +import datasetsReducer from '@/features/datasets/datasets.store'; import ingestionDataReducer from '@/features/ingestion/ingestion.store'; import provenanceReducer from '@/features/provenance/provenance.store'; import beaconConfigReducer from './features/beacon/beaconConfig.store'; @@ -16,6 +17,7 @@ export const store = configureStore({ data: dataReducer, query: queryReducer, provenance: provenanceReducer, + datasets: datasetsReducer, ingestionData: ingestionDataReducer, beaconConfig: beaconConfigReducer, beaconQuery: beaconQueryReducer, From 89ee9bf0430ea1ebdd7b142295bc6e41b0431857 Mon Sep 17 00:00:00 2001 From: Julian Date: Tue, 10 Oct 2023 14:39:29 -0400 Subject: [PATCH 02/48] remove logs --- main.go | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/main.go b/main.go index 8392816e..b5b5ea3b 100644 --- a/main.go +++ b/main.go @@ -134,8 +134,6 @@ func main() { var req *http.Request var err error - fmt.Println("urlXXXXX: ", url) - if qs != nil { req, err = http.NewRequest("GET", fmt.Sprintf("%s?%s", url, qs.Encode()), nil) if err != nil { @@ -224,11 +222,7 @@ func main() { gohanRequestPublic := func(c echo.Context) error { // Construct the path using the extracted dataset ID. - path := fmt.Sprintf("/data-types") - - // Debug print statements to verify the constructed path and the GohanUrl. - fmt.Fprintf(os.Stderr, "pathCFCFCFCF: %s\n", path) - fmt.Println("DEBUG: cfg.GohanUrl =", cfg.GohanUrl) + path := fmt.Sprintf("/public/data-types") // Make a request to the Gohan service and deserialize the response. err := gohanRequest(path, nil, c, jsonDeserialize) @@ -452,16 +446,12 @@ func main() { return c.String(http.StatusOK, string(data)) }) - e.GET("/katsu-data-types", func(c echo.Context) error { - data, err := katsuRequestFormattedData("/data-types", c) + e.GET("/katsu/data-types", func(c echo.Context) error { + data, err := katsuRequestFormattedData("/public/data-types", c) if err != nil { return err } - fmt.Println("XXXXXXX") - fmt.Println("data: ", string(data)) - fmt.Println("XXXXXXX") - return c.String(http.StatusOK, string(data)) }) From 2c0cff86bf1db30151e96197913f5e054144e67a Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:28:22 -0400 Subject: [PATCH 03/48] types for last ingestion by datatypes --- src/js/types/lastIngestionDataTypeResponse.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/js/types/lastIngestionDataTypeResponse.ts diff --git a/src/js/types/lastIngestionDataTypeResponse.ts b/src/js/types/lastIngestionDataTypeResponse.ts new file mode 100644 index 00000000..9e14a98d --- /dev/null +++ b/src/js/types/lastIngestionDataTypeResponse.ts @@ -0,0 +1,10 @@ +export interface LastIngestionDataTypeResponse { + count: number | null; + id: string; + label: string; + last_ingested: string | null; + queryable: boolean; + } + + export type DataResponseArray = LastIngestionDataTypeResponse[]; + \ No newline at end of file From 485fa67d5cad8845b00b116018960b07928864f4 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:30:23 -0400 Subject: [PATCH 04/48] Remove unnecessary files for wes request --- src/js/features/datasets/datasets.store.ts | 52 ----------------- src/js/features/ingestion/ingestion.store.ts | 59 -------------------- src/js/types/lastIngestionResponse.ts | 36 ------------ 3 files changed, 147 deletions(-) delete mode 100644 src/js/features/datasets/datasets.store.ts delete mode 100644 src/js/features/ingestion/ingestion.store.ts delete mode 100644 src/js/types/lastIngestionResponse.ts diff --git a/src/js/features/datasets/datasets.store.ts b/src/js/features/datasets/datasets.store.ts deleted file mode 100644 index 5ccfb31a..00000000 --- a/src/js/features/datasets/datasets.store.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; -import axios from 'axios'; -import { datasetsUrl } from '@/constants/configConstants'; -import { printAPIError } from '@/utils/error.util'; - -// Type definition for Dataset response. You need to define this according to the response structure -interface DatasetResponse { - // Define the structure based on the response of the /datasets endpoint. - // Here's a placeholder type; replace with actual fields - id: string; - name: string; - description: string; -} - -export const fetchDatasets = createAsyncThunk( - 'datasets/fetchDatasets', - (_, { rejectWithValue }) => - axios - .get(datasetsUrl) - .then((res) => res.data) - .catch(printAPIError(rejectWithValue)) -); - -export interface DatasetsState { - isFetchingDatasets: boolean; - datasets: DatasetResponse[]; -} - -const initialState: DatasetsState = { - isFetchingDatasets: false, - datasets: [], -}; - -const DatasetsStore = createSlice({ - name: 'datasets', - initialState, - reducers: {}, - extraReducers: (builder) => { - builder.addCase(fetchDatasets.pending, (state) => { - state.isFetchingDatasets = true; - }); - builder.addCase(fetchDatasets.fulfilled, (state, { payload }: PayloadAction) => { - state.datasets = payload; - state.isFetchingDatasets = false; - }); - builder.addCase(fetchDatasets.rejected, (state) => { - state.isFetchingDatasets = false; - }); - }, -}); - -export default DatasetsStore.reducer; diff --git a/src/js/features/ingestion/ingestion.store.ts b/src/js/features/ingestion/ingestion.store.ts deleted file mode 100644 index 0fb8964f..00000000 --- a/src/js/features/ingestion/ingestion.store.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; -import axios from 'axios'; -import { lastIngestionsUrl } from '@/constants/configConstants'; -import { printAPIError } from '@/utils/error.util'; -import { IngestionData, LastIngestionResponse } from '@/types/lastIngestionResponse'; - -export const makeGetIngestionDataRequest = createAsyncThunk( - 'ingestionData/getIngestionData', - (_, { rejectWithValue }) => - axios - .get(lastIngestionsUrl) - .then((res) => res.data) - .catch(printAPIError(rejectWithValue)) -); - -export interface IngestionDataState { - isFetchingIngestionData: boolean; - ingestionData: IngestionData[]; - lastEndTimesByDataType: { [dataType: string]: string }; -} - -const initialState: IngestionDataState = { - isFetchingIngestionData: false, - ingestionData: [], - lastEndTimesByDataType: {}, -}; - -const IngestionDataStore = createSlice({ - name: 'ingestionData', - initialState, - reducers: {}, - extraReducers: (builder) => { - builder.addCase(makeGetIngestionDataRequest.pending, (state) => { - state.isFetchingIngestionData = true; - }); - builder.addCase( - makeGetIngestionDataRequest.fulfilled, - (state, { payload }: PayloadAction) => { - state.ingestionData = payload; - payload.forEach((ingestion) => { - const dataType = ingestion.details.request.tags.workflow_metadata.data_type; - console.log("losDATATipes",dataType); - //// here use dataType - const endTime = ingestion.details.run_log.end_time; - const previousEndTime = state.lastEndTimesByDataType[dataType]; - if (!previousEndTime || new Date(endTime) > new Date(previousEndTime)) { - state.lastEndTimesByDataType[dataType] = endTime; - } - }); - state.isFetchingIngestionData = false; - } - ); - builder.addCase(makeGetIngestionDataRequest.rejected, (state) => { - state.isFetchingIngestionData = false; - }); - }, -}); - -export default IngestionDataStore.reducer; diff --git a/src/js/types/lastIngestionResponse.ts b/src/js/types/lastIngestionResponse.ts deleted file mode 100644 index 22357371..00000000 --- a/src/js/types/lastIngestionResponse.ts +++ /dev/null @@ -1,36 +0,0 @@ -interface Tags { - table_id: string; - workflow_id: string; - workflow_metadata: { - data_type: string; - id: string; - }; -} - -interface Request { - tags: Tags; - workflow_type: string; -} - -interface RunLog { - end_time: string; - id: string; - start_time: string; -} - -export interface IngestionDetails { - end_time: string; - request: Request; - run_id: string; - run_log: RunLog; - state: string; - task_logs: null; -} - -export interface IngestionData { - details: IngestionDetails; - run_id: string; - state: string; -} - -export type LastIngestionResponse = IngestionData[]; From 471083aae844d1313adb47ffe00272f81221c151 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:31:18 -0400 Subject: [PATCH 05/48] add store for last ingestion in datatypes --- .../features/ingestion/lastIngestion.store.ts | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/js/features/ingestion/lastIngestion.store.ts diff --git a/src/js/features/ingestion/lastIngestion.store.ts b/src/js/features/ingestion/lastIngestion.store.ts new file mode 100644 index 00000000..af916a0d --- /dev/null +++ b/src/js/features/ingestion/lastIngestion.store.ts @@ -0,0 +1,79 @@ +import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; +import axios from 'axios'; +import { katsuLastIngestionsUrl, gohanLastIngestionsUrl } from '@/constants/configConstants'; +import { printAPIError } from '@/utils/error.util'; + +export interface DataTypeResponse { + count: number | null; + id: string; + label: string; + last_ingested: string | null; + queryable: boolean; +} + +export type DataResponseArray = DataTypeResponse[]; + +// Async thunks to fetch data from the two endpoints +export const fetchKatsuData = createAsyncThunk( + 'dataTypes/fetchKatsuData', + (_, { rejectWithValue }) => + axios.get(katsuLastIngestionsUrl).then((res) => res.data).catch(printAPIError(rejectWithValue)) +); + +export const fetchGohanData = createAsyncThunk( + 'dataTypes/fetchGohanData', + (_, { rejectWithValue }) => + axios.get(gohanLastIngestionsUrl).then((res) => res.data).catch(printAPIError(rejectWithValue)) +); + +// Define the state structure +export interface DataTypeState { + isFetchingData: boolean; + dataTypes: DataResponseArray; +} + +// Initialize the state +const initialDataTypeState: DataTypeState = { + isFetchingData: false, + dataTypes: [], +}; + +// Create a slice to manage the state +const DataTypeStore = createSlice({ + name: 'dataTypes', + initialState: initialDataTypeState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(fetchKatsuData.pending, (state) => { + state.isFetchingData = true; + }); + builder.addCase(fetchGohanData.pending, (state) => { + state.isFetchingData = true; + }); + builder.addCase( + fetchKatsuData.fulfilled, + (state, { payload }: PayloadAction) => { + const uniqueIds = new Set(state.dataTypes.map(data => data.id)); + const newData = payload.filter(data => !uniqueIds.has(data.id)); + state.dataTypes = [...state.dataTypes, ...newData]; + } + ); + builder.addCase( + fetchGohanData.fulfilled, + (state, { payload }: PayloadAction) => { + const uniqueIds = new Set(state.dataTypes.map(data => data.id)); + const newData = payload.filter(data => !uniqueIds.has(data.id)); + state.dataTypes = [...state.dataTypes, ...newData]; + state.isFetchingData = false; + } + ); + builder.addCase(fetchKatsuData.rejected, (state) => { + state.isFetchingData = false; + }); + builder.addCase(fetchGohanData.rejected, (state) => { + state.isFetchingData = false; + }); + }, +}); + +export default DataTypeStore.reducer; From bc2c8d9b068727c1e29cd4d839f7224af6da955a Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:32:14 -0400 Subject: [PATCH 06/48] refactor gohan request --- main.go | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index b5b5ea3b..4f3197bc 100644 --- a/main.go +++ b/main.go @@ -220,21 +220,13 @@ func main() { } gohanRequestPublic := func(c echo.Context) error { - - // Construct the path using the extracted dataset ID. - path := fmt.Sprintf("/public/data-types") - - // Make a request to the Gohan service and deserialize the response. - err := gohanRequest(path, nil, c, jsonDeserialize) + path := fmt.Sprintf("/data-types") + result, err := genericRequestJsonOnly(fmt.Sprintf("%s%s", cfg.GohanUrl, path), nil, c, jsonDeserialize) if err != nil { - // Return the error if there is one. return err } - // If everything is successful, return a success status to the caller. - return c.JSON(http.StatusOK, map[string]string{ - "message": "Success", - }) + return c.JSON(http.StatusOK, result) } fetchAndSetKatsuPublic := func(c echo.Context, katsuCache *cache.Cache) (JsonLike, error) { From 3d9e9ba50bed47be2a71098aaaaa325072bf1af9 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:34:57 -0400 Subject: [PATCH 07/48] add gohan/data-types endpoint --- main.go | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/main.go b/main.go index 4f3197bc..75dae30e 100644 --- a/main.go +++ b/main.go @@ -405,38 +405,7 @@ func main() { return c.String(http.StatusOK, string(data)) }) - e.GET("/datasets", func(c echo.Context) error { - data, err := katsuRequestFormattedData("/api/datasets", c) - if err != nil { - return err - } - - fmt.Println("FFFFF") - fmt.Println("data: ", string(data)) - fmt.Println("FFFFF") - - return c.String(http.StatusOK, string(data)) - - }) - - e.GET("/datasets/:id/data-types/:data-type/public", func(c echo.Context) error { - id := c.Param("id") - dataType := c.Param("data-type") - relativeUrl := fmt.Sprintf("/datasets/%s/data-types/%s/public", id, dataType) - - data, err := katsuRequestFormattedData(relativeUrl, c) - if err != nil { - return err - } - - fmt.Println("XXXXXXX") - - fmt.Println("data: ", string(data)) - - fmt.Println("XXXXXXX") - - return c.String(http.StatusOK, string(data)) - }) + e.GET("/gohan/data-types", gohanRequestPublic) e.GET("/katsu/data-types", func(c echo.Context) error { data, err := katsuRequestFormattedData("/public/data-types", c) From 9e55a48471d51e9c0849a9b6e3c8dafe39373a32 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:35:46 -0400 Subject: [PATCH 08/48] refactor katsu datatypes retrieval --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 75dae30e..361e6f91 100644 --- a/main.go +++ b/main.go @@ -408,7 +408,7 @@ func main() { e.GET("/gohan/data-types", gohanRequestPublic) e.GET("/katsu/data-types", func(c echo.Context) error { - data, err := katsuRequestFormattedData("/public/data-types", c) + data, err := katsuRequestFormattedData("/data-types", c) if err != nil { return err } From 01de0f6d617e62ff89c9def39fd3c6b92632cda1 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:36:12 -0400 Subject: [PATCH 09/48] remove wes request --- main.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/main.go b/main.go index 361e6f91..70075b81 100644 --- a/main.go +++ b/main.go @@ -179,22 +179,6 @@ func main() { return c.JSON(http.StatusOK, result) } - wesRequest := func(path string, qs url.Values, c echo.Context, rf responseFormatterFunc) error { - result, err := genericRequestJsonOnly(fmt.Sprintf("%s%s", cfg.WesUrl, path), qs, c, rf) - if err != nil { - return err - } - return c.JSON(http.StatusOK, result) - } - - gohanRequest := func(path string, qs url.Values, c echo.Context, rf responseFormatterFunc) error { - result, err := genericRequestJsonOnly(fmt.Sprintf("%s%s", cfg.GohanUrl, path), qs, c, rf) - if err != nil { - return err - } - return c.JSON(http.StatusOK, result) - } - katsuRequestBasic := func(path string, c echo.Context) error { return katsuRequest(path, nil, c, jsonDeserialize) } @@ -212,13 +196,6 @@ func main() { return jsonFormattedData, nil } - wesRequestWithDetailsAndPublic := func(c echo.Context) error { - qs := url.Values{} - qs.Add("with_details", "true") - qs.Add("public", "true") - return wesRequest("/runs", qs, c, jsonDeserialize) - } - gohanRequestPublic := func(c echo.Context) error { path := fmt.Sprintf("/data-types") result, err := genericRequestJsonOnly(fmt.Sprintf("%s%s", cfg.GohanUrl, path), nil, c, jsonDeserialize) @@ -380,10 +357,6 @@ func main() { return katsuRequestBasic("/api/public_search_fields", c) }) - e.GET("/wes-runs", wesRequestWithDetailsAndPublic) - - e.GET("/gohan/data-types", gohanRequestPublic) - e.GET("/provenance", func(c echo.Context) error { // Query Katsu for datasets provenance return katsuRequestBasic("/api/public_dataset", c) From 88d359b5e1c6125efd4e7e81e9a5fe403469f68a Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:36:50 -0400 Subject: [PATCH 10/48] configure stire for lastIngestionData --- src/js/store.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/js/store.ts b/src/js/store.ts index 6ef8adbb..3477ad2e 100644 --- a/src/js/store.ts +++ b/src/js/store.ts @@ -4,8 +4,7 @@ import configReducer from '@/features/config/config.store'; import contentReducer from '@/features/content/content.store'; import dataReducer from '@/features/data/data.store'; import queryReducer from '@/features/search/query.store'; -import datasetsReducer from '@/features/datasets/datasets.store'; -import ingestionDataReducer from '@/features/ingestion/ingestion.store'; +import lastIngestionDataReducer from '@/features/ingestion/lastIngestion.store'; import provenanceReducer from '@/features/provenance/provenance.store'; import beaconConfigReducer from './features/beacon/beaconConfig.store'; import beaconQueryReducer from './features/beacon/beaconQuery.store'; @@ -17,8 +16,7 @@ export const store = configureStore({ data: dataReducer, query: queryReducer, provenance: provenanceReducer, - datasets: datasetsReducer, - ingestionData: ingestionDataReducer, + lastIngestionData: lastIngestionDataReducer, beaconConfig: beaconConfigReducer, beaconQuery: beaconQueryReducer, }, From 2c436eff69d5021f0bcfa8f9eb360c9f0db3ec9e Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:38:23 -0400 Subject: [PATCH 11/48] dispatch acction for retrieve data-types with last ingestion data --- src/js/components/TabbedDashboard.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/js/components/TabbedDashboard.tsx b/src/js/components/TabbedDashboard.tsx index a23bd2b7..0c61e0b8 100644 --- a/src/js/components/TabbedDashboard.tsx +++ b/src/js/components/TabbedDashboard.tsx @@ -14,6 +14,7 @@ import {fetchDatasets } from '@/features/datasets/datasets.store'; import { makeGetIngestionDataRequest } from '@/features/ingestion/ingestion.store'; import { getBeaconConfig } from '@/features/beacon/beaconConfig.store'; import {makeGetDataTypes } from '@/features/dataTypes/dataTypes.store'; +import { fetchGohanData, fetchKatsuData } from '@/features/ingestion/lastIngestion.store'; import Loader from './Loader'; import PublicOverview from './Overview/PublicOverview'; @@ -37,8 +38,8 @@ const TabbedDashboard = () => { dispatch(makeGetDataRequestThunk()); dispatch(makeGetSearchFields()); dispatch(makeGetProvenanceRequest()); - dispatch(makeGetIngestionDataRequest()); - dispatch(fetchDatasets()); + dispatch(fetchKatsuData()); + dispatch(fetchGohanData()); dispatch(makeGetDataTypes()); }, []); From 1efabb18c21f1e532e87c3240e2ff622d2a97a49 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:39:12 -0400 Subject: [PATCH 12/48] remove unnecessary dispatchs --- src/js/components/TabbedDashboard.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/js/components/TabbedDashboard.tsx b/src/js/components/TabbedDashboard.tsx index 0c61e0b8..46d39016 100644 --- a/src/js/components/TabbedDashboard.tsx +++ b/src/js/components/TabbedDashboard.tsx @@ -10,8 +10,6 @@ import { makeGetAboutRequest } from '@/features/content/content.store'; import { makeGetDataRequestThunk } from '@/features/data/data.store'; import { makeGetSearchFields } from '@/features/search/query.store'; import { makeGetProvenanceRequest } from '@/features/provenance/provenance.store'; -import {fetchDatasets } from '@/features/datasets/datasets.store'; -import { makeGetIngestionDataRequest } from '@/features/ingestion/ingestion.store'; import { getBeaconConfig } from '@/features/beacon/beaconConfig.store'; import {makeGetDataTypes } from '@/features/dataTypes/dataTypes.store'; import { fetchGohanData, fetchKatsuData } from '@/features/ingestion/lastIngestion.store'; From d171b73e9fe8cf0fe0fa8fee986479b15de2a4e7 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:39:46 -0400 Subject: [PATCH 13/48] refactor LastIngestionInfo for new data --- src/js/components/Overview/LastIngestion.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/js/components/Overview/LastIngestion.tsx b/src/js/components/Overview/LastIngestion.tsx index 46ed6b03..57ff48bb 100644 --- a/src/js/components/Overview/LastIngestion.tsx +++ b/src/js/components/Overview/LastIngestion.tsx @@ -6,10 +6,14 @@ import { useTranslation } from 'react-i18next'; import { DEFAULT_TRANSLATION } from '@/constants/configConstants'; import { useAppSelector } from '@/hooks'; import { getDataTypeLabel } from '@/types/dataTypes'; +import { LastIngestionDataTypeResponse, DataResponseArray } from '@/types/lastIngestionDataTypeResponse'; const LastIngestionInfo: React.FC = () => { const { t, i18n } = useTranslation(DEFAULT_TRANSLATION); - const lastEndTimesByDataType = useAppSelector((state) => state.ingestionData?.lastEndTimesByDataType) || {}; + + const lastEndTimesByDataType: DataResponseArray = useAppSelector((state) => state.lastIngestionData?.dataTypes) || []; + + const queryableDataTypes = lastEndTimesByDataType.filter((item: LastIngestionDataTypeResponse) => item.queryable); const formatDate = useCallback( (dateString: string) => { @@ -28,19 +32,19 @@ const LastIngestionInfo: React.FC = () => { [i18n.language] ); - const hasData = Object.keys(lastEndTimesByDataType).length > 0; + const hasData = queryableDataTypes.length > 0; return ( {t('Latest Data IngestionX')} {hasData ? ( - Object.entries(lastEndTimesByDataType).map(([dataType, endTime]) => ( - + queryableDataTypes.map((dataType: LastIngestionDataTypeResponse) => ( + - {t(getDataTypeLabel(dataType))} + {getDataTypeLabel(dataType.id)} - {formatDate(endTime)} + {dataType.last_ingested ? formatDate(dataType.last_ingested) : 'Not Available'} From 8829bf732abc1a50584d4d24edb8874a7970620a Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:40:34 -0400 Subject: [PATCH 14/48] add partial urls for data-ty retrieval pron katsu and gohan --- src/js/constants/configConstants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/constants/configConstants.ts b/src/js/constants/configConstants.ts index f3eb98af..c3c27e97 100644 --- a/src/js/constants/configConstants.ts +++ b/src/js/constants/configConstants.ts @@ -6,8 +6,8 @@ export const searchFieldsUrl = '/fields'; export const katsuUrl = '/katsu'; export const provenanceUrl = '/provenance'; export const lastIngestionsUrl = '/wes-runs'; -export const datasetsUrl = '/datasets'; -export const datasetDataTypePublicUrl = '/datasets/:id/data-types/:data-type/public'; +export const katsuLastIngestionsUrl = '/katsu/data-types'; +export const gohanLastIngestionsUrl = '/gohan/data-types'; export const DEFAULT_TRANSLATION = 'default_translation'; export const NON_DEFAULT_TRANSLATION = 'translation'; From 8d5411d4714922ef062c2a39b3a4b8e0acd9cfc4 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 11 Oct 2023 14:53:22 -0400 Subject: [PATCH 15/48] prettier --- src/js/components/TabbedDashboard.tsx | 2 +- .../features/ingestion/lastIngestion.store.ts | 46 +++++++++---------- src/js/store.ts | 2 +- src/js/types/lastIngestionDataTypeResponse.ts | 17 ++++--- 4 files changed, 31 insertions(+), 36 deletions(-) diff --git a/src/js/components/TabbedDashboard.tsx b/src/js/components/TabbedDashboard.tsx index 46d39016..cdff2d2b 100644 --- a/src/js/components/TabbedDashboard.tsx +++ b/src/js/components/TabbedDashboard.tsx @@ -11,7 +11,7 @@ import { makeGetDataRequestThunk } from '@/features/data/data.store'; import { makeGetSearchFields } from '@/features/search/query.store'; import { makeGetProvenanceRequest } from '@/features/provenance/provenance.store'; import { getBeaconConfig } from '@/features/beacon/beaconConfig.store'; -import {makeGetDataTypes } from '@/features/dataTypes/dataTypes.store'; +import { makeGetDataTypes } from '@/features/dataTypes/dataTypes.store'; import { fetchGohanData, fetchKatsuData } from '@/features/ingestion/lastIngestion.store'; import Loader from './Loader'; diff --git a/src/js/features/ingestion/lastIngestion.store.ts b/src/js/features/ingestion/lastIngestion.store.ts index af916a0d..36554893 100644 --- a/src/js/features/ingestion/lastIngestion.store.ts +++ b/src/js/features/ingestion/lastIngestion.store.ts @@ -14,16 +14,18 @@ export interface DataTypeResponse { export type DataResponseArray = DataTypeResponse[]; // Async thunks to fetch data from the two endpoints -export const fetchKatsuData = createAsyncThunk( - 'dataTypes/fetchKatsuData', - (_, { rejectWithValue }) => - axios.get(katsuLastIngestionsUrl).then((res) => res.data).catch(printAPIError(rejectWithValue)) +export const fetchKatsuData = createAsyncThunk('dataTypes/fetchKatsuData', (_, { rejectWithValue }) => + axios + .get(katsuLastIngestionsUrl) + .then((res) => res.data) + .catch(printAPIError(rejectWithValue)) ); -export const fetchGohanData = createAsyncThunk( - 'dataTypes/fetchGohanData', - (_, { rejectWithValue }) => - axios.get(gohanLastIngestionsUrl).then((res) => res.data).catch(printAPIError(rejectWithValue)) +export const fetchGohanData = createAsyncThunk('dataTypes/fetchGohanData', (_, { rejectWithValue }) => + axios + .get(gohanLastIngestionsUrl) + .then((res) => res.data) + .catch(printAPIError(rejectWithValue)) ); // Define the state structure @@ -50,23 +52,17 @@ const DataTypeStore = createSlice({ builder.addCase(fetchGohanData.pending, (state) => { state.isFetchingData = true; }); - builder.addCase( - fetchKatsuData.fulfilled, - (state, { payload }: PayloadAction) => { - const uniqueIds = new Set(state.dataTypes.map(data => data.id)); - const newData = payload.filter(data => !uniqueIds.has(data.id)); - state.dataTypes = [...state.dataTypes, ...newData]; - } - ); - builder.addCase( - fetchGohanData.fulfilled, - (state, { payload }: PayloadAction) => { - const uniqueIds = new Set(state.dataTypes.map(data => data.id)); - const newData = payload.filter(data => !uniqueIds.has(data.id)); - state.dataTypes = [...state.dataTypes, ...newData]; - state.isFetchingData = false; - } - ); + builder.addCase(fetchKatsuData.fulfilled, (state, { payload }: PayloadAction) => { + const uniqueIds = new Set(state.dataTypes.map((data) => data.id)); + const newData = payload.filter((data) => !uniqueIds.has(data.id)); + state.dataTypes = [...state.dataTypes, ...newData]; + }); + builder.addCase(fetchGohanData.fulfilled, (state, { payload }: PayloadAction) => { + const uniqueIds = new Set(state.dataTypes.map((data) => data.id)); + const newData = payload.filter((data) => !uniqueIds.has(data.id)); + state.dataTypes = [...state.dataTypes, ...newData]; + state.isFetchingData = false; + }); builder.addCase(fetchKatsuData.rejected, (state) => { state.isFetchingData = false; }); diff --git a/src/js/store.ts b/src/js/store.ts index 3477ad2e..921821a8 100644 --- a/src/js/store.ts +++ b/src/js/store.ts @@ -16,7 +16,7 @@ export const store = configureStore({ data: dataReducer, query: queryReducer, provenance: provenanceReducer, - lastIngestionData: lastIngestionDataReducer, + lastIngestionData: lastIngestionDataReducer, beaconConfig: beaconConfigReducer, beaconQuery: beaconQueryReducer, }, diff --git a/src/js/types/lastIngestionDataTypeResponse.ts b/src/js/types/lastIngestionDataTypeResponse.ts index 9e14a98d..c3e7eebe 100644 --- a/src/js/types/lastIngestionDataTypeResponse.ts +++ b/src/js/types/lastIngestionDataTypeResponse.ts @@ -1,10 +1,9 @@ export interface LastIngestionDataTypeResponse { - count: number | null; - id: string; - label: string; - last_ingested: string | null; - queryable: boolean; - } - - export type DataResponseArray = LastIngestionDataTypeResponse[]; - \ No newline at end of file + count: number | null; + id: string; + label: string; + last_ingested: string | null; + queryable: boolean; +} + +export type DataResponseArray = LastIngestionDataTypeResponse[]; From e1be9136692cb6941dac306e5744aa3ec2ee6160 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 1 Nov 2023 15:29:57 -0400 Subject: [PATCH 16/48] chore: add missing translations & bump version to 0.16.2 --- package.json | 2 +- src/js/components/Overview/Drawer/ChartTree.tsx | 2 +- src/public/locales/en/default_translation_en.json | 2 ++ src/public/locales/fr/default_translation_fr.json | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 50d11e73..53c70d1d 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bento_public", - "version": "0.16.1", + "version": "0.16.2", "description": "A publicly accessible portal for clinical datasets, where users are able to see high-level statistics of the data available through predefined variables of interest and search the data using limited variables at a time. This portal allows users to gain a generic understanding of the data available (secure and firewalled) without the need to access it directly. Initially, this portal facilitates the search in English language only, but the French language will be added at a later time.", "main": "index.js", "scripts": { diff --git a/src/js/components/Overview/Drawer/ChartTree.tsx b/src/js/components/Overview/Drawer/ChartTree.tsx index c1b78c3b..85308777 100644 --- a/src/js/components/Overview/Drawer/ChartTree.tsx +++ b/src/js/components/Overview/Drawer/ChartTree.tsx @@ -23,7 +23,7 @@ const ChartTree = ({ charts, section }: ChartTreeProps) => {
{t(title)} - Width:{' '} + {t('Width')}:{' '} Date: Wed, 1 Nov 2023 15:55:29 -0400 Subject: [PATCH 17/48] fix: chart tree memoized data should change with translation --- src/js/components/Overview/Drawer/ChartTree.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/components/Overview/Drawer/ChartTree.tsx b/src/js/components/Overview/Drawer/ChartTree.tsx index 85308777..d7ec1bf2 100644 --- a/src/js/components/Overview/Drawer/ChartTree.tsx +++ b/src/js/components/Overview/Drawer/ChartTree.tsx @@ -42,7 +42,7 @@ const ChartTree = ({ charts, section }: ChartTreeProps) => { ), key: id, })), - [charts] + [charts, t] ); const onChartDrop: TreeProps['onDrop'] = useMemo(() => { From d9e8ecc126575a999342b325da53e53c1c3143f8 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 1 Nov 2023 15:57:49 -0400 Subject: [PATCH 18/48] fix: use right translations for right keys in ChartTree --- src/js/components/Overview/Drawer/ChartTree.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/js/components/Overview/Drawer/ChartTree.tsx b/src/js/components/Overview/Drawer/ChartTree.tsx index d7ec1bf2..2f5608fc 100644 --- a/src/js/components/Overview/Drawer/ChartTree.tsx +++ b/src/js/components/Overview/Drawer/ChartTree.tsx @@ -4,7 +4,7 @@ import { InputNumber, Tree, TreeProps } from 'antd'; import { useTranslation } from 'react-i18next'; import { rearrange, setDisplayedCharts, setChartWidth } from '@/features/data/data.store'; -import { NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; +import { DEFAULT_TRANSLATION, NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; import { ChartDataField } from '@/types/data'; interface MappedChartItem { @@ -14,14 +14,16 @@ interface MappedChartItem { const ChartTree = ({ charts, section }: ChartTreeProps) => { const dispatch = useDispatch(); - const { t } = useTranslation(NON_DEFAULT_TRANSLATION); + + const { t } = useTranslation(DEFAULT_TRANSLATION); + const { t: td } = useTranslation(NON_DEFAULT_TRANSLATION); const allCharts: MappedChartItem[] = useMemo( () => charts.map(({ field: { title }, id, width }) => ({ title: (
- {t(title)} + {td(title)} {t('Width')}:{' '} { ), key: id, })), - [charts, t] + [charts, t, td] ); const onChartDrop: TreeProps['onDrop'] = useMemo(() => { From 509e4c991f36b3a60c4f095b0fe7f32753e74895 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 1 Nov 2023 16:37:31 -0400 Subject: [PATCH 19/48] fix: remove the DATS translation from the wrong translation file --- src/js/components/Provenance/DownloadDats.tsx | 4 ++-- src/public/locales/en/translation_en.json | 5 ++--- src/public/locales/fr/translation_fr.json | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/js/components/Provenance/DownloadDats.tsx b/src/js/components/Provenance/DownloadDats.tsx index 3f2589d1..73cdea65 100644 --- a/src/js/components/Provenance/DownloadDats.tsx +++ b/src/js/components/Provenance/DownloadDats.tsx @@ -2,11 +2,11 @@ import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; import { Button, Space } from 'antd'; import { DownloadOutlined } from '@ant-design/icons'; -import { useTranslation } from 'react-i18next'; +import { useTranslationDefault } from '@/hooks'; import { ProvenanceStoreDataset } from '@/types/provenance'; const DownloadDats = ({ metadata }: { metadata: ProvenanceStoreDataset }) => { - const { t } = useTranslation(); + const t = useTranslationDefault(); const exportData = useCallback(() => { window.location.href = `/datasets/${metadata.identifier}/dats`; diff --git a/src/public/locales/en/translation_en.json b/src/public/locales/en/translation_en.json index 3b8c08a5..8fc8615e 100644 --- a/src/public/locales/en/translation_en.json +++ b/src/public/locales/en/translation_en.json @@ -9,6 +9,5 @@ "MALE": "MALE", "FEMALE": "FEMALE", "I have no problems in walking about": "I have no problems in walking about", - "Results": "Results", - "Download DATS File": "Download DATS File" -} \ No newline at end of file + "Results": "Results" +} diff --git a/src/public/locales/fr/translation_fr.json b/src/public/locales/fr/translation_fr.json index 68448c6b..97d12d8f 100644 --- a/src/public/locales/fr/translation_fr.json +++ b/src/public/locales/fr/translation_fr.json @@ -9,6 +9,5 @@ "Lab Test Result": "Résultats des tests de laboratoire", "Experiment Types": "Types d'expériences", "I have no problems in walking about": "Je n’ai aucun problème à marcher", - "Results": "Résultats", - "Download DATS File": "Télécharger le fichier DATS" + "Results": "Résultats" } \ No newline at end of file From 6a245f710607cecf48786140a38aa77de55d473f Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 1 Nov 2023 16:53:36 -0400 Subject: [PATCH 20/48] refact: use defined translation hooks --- src/js/components/Overview/ChartCard.tsx | 5 +++-- src/js/components/Overview/Counts.tsx | 10 ++++------ src/js/components/Overview/Drawer/ChartTree.tsx | 9 +++++---- .../components/Overview/Drawer/ManageChartsDrawer.tsx | 8 +++----- src/js/components/Overview/OverviewSection.tsx | 5 ++--- src/js/components/Provenance/DatasetProvenance.tsx | 9 ++++----- src/js/components/Search/MakeQueryOption.tsx | 8 +++----- src/js/components/Search/Search.tsx | 6 ++---- src/js/components/Search/SelectOption.tsx | 6 ++---- src/js/components/SiteFooter.tsx | 8 ++++---- src/js/components/TabbedDashboard.tsx | 8 +++----- src/js/components/Util/CustomEmpty.js | 7 +++---- 12 files changed, 38 insertions(+), 51 deletions(-) diff --git a/src/js/components/Overview/ChartCard.tsx b/src/js/components/Overview/ChartCard.tsx index 4ac93568..37dd38ab 100644 --- a/src/js/components/Overview/ChartCard.tsx +++ b/src/js/components/Overview/ChartCard.tsx @@ -7,13 +7,14 @@ import CustomEmpty from '../Util/CustomEmpty'; import { DEFAULT_TRANSLATION, NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; import { ChartDataField } from '@/types/data'; import { CHART_HEIGHT } from '@/constants/overviewConstants'; +import { useTranslationCustom, useTranslationDefault } from '@/hooks'; const CARD_STYLE = { width: '100%', height: '415px', borderRadius: '11px' }; const ROW_EMPTY_STYLE = { height: `${CHART_HEIGHT}px` }; const ChartCard = memo(({ section, chart, onRemoveChart, width }: ChartCardProps) => { - const { t } = useTranslation(NON_DEFAULT_TRANSLATION); - const { t: td } = useTranslation(DEFAULT_TRANSLATION); + const t = useTranslationCustom(); + const td = useTranslationDefault(); const { data, diff --git a/src/js/components/Overview/Counts.tsx b/src/js/components/Overview/Counts.tsx index 3ad96136..a176f3f8 100644 --- a/src/js/components/Overview/Counts.tsx +++ b/src/js/components/Overview/Counts.tsx @@ -2,15 +2,13 @@ import React from 'react'; import { Typography, Card, Space, Statistic } from 'antd'; import { TeamOutlined } from '@ant-design/icons'; import { BiDna } from 'react-icons/bi'; -import { useTranslation } from 'react-i18next'; import ExpSvg from '../Util/ExpSvg'; import { COUNTS_FILL } from '@/constants/overviewConstants'; -import { DEFAULT_TRANSLATION } from '@/constants/configConstants'; -import { useAppSelector } from '@/hooks'; +import { useAppSelector, useTranslationDefault } from '@/hooks'; const Counts = () => { - const { t } = useTranslation(DEFAULT_TRANSLATION); + const td = useTranslationDefault(); const data = [ { @@ -32,11 +30,11 @@ const Counts = () => { return ( <> - {t('Counts')} + {td('Counts')} {data.map(({ title, icon, count }, i) => ( - + ))} diff --git a/src/js/components/Overview/Drawer/ChartTree.tsx b/src/js/components/Overview/Drawer/ChartTree.tsx index 2f5608fc..8938f631 100644 --- a/src/js/components/Overview/Drawer/ChartTree.tsx +++ b/src/js/components/Overview/Drawer/ChartTree.tsx @@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'; import { rearrange, setDisplayedCharts, setChartWidth } from '@/features/data/data.store'; import { DEFAULT_TRANSLATION, NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; import { ChartDataField } from '@/types/data'; +import { useTranslationCustom, useTranslationDefault } from '@/hooks'; interface MappedChartItem { title: ReactNode; @@ -15,17 +16,17 @@ interface MappedChartItem { const ChartTree = ({ charts, section }: ChartTreeProps) => { const dispatch = useDispatch(); - const { t } = useTranslation(DEFAULT_TRANSLATION); - const { t: td } = useTranslation(NON_DEFAULT_TRANSLATION); + const t = useTranslationCustom(); + const td = useTranslationDefault(); const allCharts: MappedChartItem[] = useMemo( () => charts.map(({ field: { title }, id, width }) => ({ title: (
- {td(title)} + {t(title)} - {t('Width')}:{' '} + {td('Width')}:{' '} { - const { t } = useTranslation(NON_DEFAULT_TRANSLATION); - const { t: td } = useTranslation(DEFAULT_TRANSLATION); + const t = useTranslationCustom(); + const td = useTranslationDefault(); const sections = useAppSelector((state) => state.data.sections); diff --git a/src/js/components/Overview/OverviewSection.tsx b/src/js/components/Overview/OverviewSection.tsx index 9f586131..aa364952 100644 --- a/src/js/components/Overview/OverviewSection.tsx +++ b/src/js/components/Overview/OverviewSection.tsx @@ -1,13 +1,12 @@ import React from 'react'; import { Typography, Space } from 'antd'; -import { useTranslation } from 'react-i18next'; import OverviewDisplayData from './OverviewDisplayData'; -import { NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; +import { useTranslationCustom } from '@/hooks'; import { ChartDataField } from '@/types/data'; const OverviewSection = ({ title, chartData }: { title: string; chartData: ChartDataField[] }) => { - const { t } = useTranslation(NON_DEFAULT_TRANSLATION); + const t = useTranslationCustom(); return ( diff --git a/src/js/components/Provenance/DatasetProvenance.tsx b/src/js/components/Provenance/DatasetProvenance.tsx index 65949796..390530c1 100644 --- a/src/js/components/Provenance/DatasetProvenance.tsx +++ b/src/js/components/Provenance/DatasetProvenance.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { Card, Descriptions, Tag, Typography } from 'antd'; -import { useTranslation } from 'react-i18next'; import DistributionsTable from './Tables/DistributionsTable'; import IsAboutTable from './Tables/IsAboutTable'; @@ -10,7 +9,7 @@ import ExtraPropertiesTable from './Tables/ExtraPropertiesTable'; import PublicationsTable from './Tables/PublicationsTable'; import CreatedByTable from './Tables/CreatedByTable'; import DownloadDats from './DownloadDats'; -import { DEFAULT_TRANSLATION, NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; +import { useTranslationCustom, useTranslationDefault } from '@/hooks'; import { ProvenanceStoreDataset } from '@/types/provenance'; const { Item } = Descriptions; @@ -18,8 +17,8 @@ const { Text, Title } = Typography; const { Meta } = Card; const DatasetProvenance = ({ metadata, loading }: DatasetProvenanceProps) => { - const { t } = useTranslation(NON_DEFAULT_TRANSLATION); - const { t: td } = useTranslation(DEFAULT_TRANSLATION); + const t = useTranslationCustom(); + const td = useTranslationDefault(); return (
@@ -137,7 +136,7 @@ export type DatasetProvenanceProps = { export default DatasetProvenance; const TableTitleWithTranslation = ({ title }: { title: string }) => { - const { t } = useTranslation(DEFAULT_TRANSLATION); + const t = useTranslationCustom(); return ( diff --git a/src/js/components/Search/MakeQueryOption.tsx b/src/js/components/Search/MakeQueryOption.tsx index 1f341276..63d46b97 100644 --- a/src/js/components/Search/MakeQueryOption.tsx +++ b/src/js/components/Search/MakeQueryOption.tsx @@ -1,18 +1,16 @@ import React from 'react'; import { Row, Col, Checkbox } from 'antd'; -import { useTranslation } from 'react-i18next'; import OptionDescription from './OptionDescription'; import { addQueryParam, makeGetKatsuPublic, removeQueryParam } from '@/features/search/query.store'; import SelectOption from './SelectOption'; -import { DEFAULT_TRANSLATION, NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; -import { useAppDispatch, useAppSelector } from '@/hooks'; +import { useAppDispatch, useAppSelector, useTranslationCustom, useTranslationDefault } from '@/hooks'; import { Field } from '@/types/search'; const MakeQueryOption = ({ queryField }: MakeQueryOptionProps) => { - const { t } = useTranslation(NON_DEFAULT_TRANSLATION); - const { t: td } = useTranslation(DEFAULT_TRANSLATION); + const t = useTranslationCustom(); + const td = useTranslationDefault(); const dispatch = useAppDispatch(); const { title, id, description, config, options } = queryField; diff --git a/src/js/components/Search/Search.tsx b/src/js/components/Search/Search.tsx index 31080908..f7c696a3 100644 --- a/src/js/components/Search/Search.tsx +++ b/src/js/components/Search/Search.tsx @@ -1,14 +1,12 @@ import React, { useEffect, useMemo } from 'react'; import { Row, Typography, Space, FloatButton } from 'antd'; -import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import SearchFieldsStack from './SearchFieldsStack'; import SearchResults from './SearchResults'; -import { NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; import { makeGetKatsuPublic, setQueryParams } from '@/features/search/query.store'; -import { useAppDispatch, useAppSelector } from '@/hooks'; +import { useAppDispatch, useAppSelector, useTranslationCustom } from '@/hooks'; import { buildQueryParamsUrl } from '@/utils/search'; import type { QueryParams } from '@/types/search'; @@ -95,7 +93,7 @@ const SEARCH_SECTION_SPACE_ITEM_STYLE = { item: { display: 'flex', justifyConten const SEARCH_SECTION_STYLE = { maxWidth: 1200 }; const Search: React.FC = () => { - const { t } = useTranslation(NON_DEFAULT_TRANSLATION); + const t = useTranslationCustom(); const searchSections = useAppSelector((state) => state.query.querySections); diff --git a/src/js/components/Search/SelectOption.tsx b/src/js/components/Search/SelectOption.tsx index cd3662c4..8a9c0688 100644 --- a/src/js/components/Search/SelectOption.tsx +++ b/src/js/components/Search/SelectOption.tsx @@ -1,14 +1,12 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import React from 'react'; import { Select } from 'antd'; -import { useTranslation } from 'react-i18next'; import { addQueryParam, makeGetKatsuPublic } from '@/features/search/query.store'; -import { NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; -import { useAppDispatch, useAppSelector } from '@/hooks'; +import { useAppDispatch, useAppSelector, useTranslationCustom } from '@/hooks'; const SelectOption = ({ id, isChecked, options }: SelectOptionProps) => { - const { t } = useTranslation(NON_DEFAULT_TRANSLATION); + const t = useTranslationCustom(); const dispatch = useAppDispatch(); const queryParams = useAppSelector((state) => state.query.queryParams); diff --git a/src/js/components/SiteFooter.tsx b/src/js/components/SiteFooter.tsx index ce57dd80..7bff03a2 100644 --- a/src/js/components/SiteFooter.tsx +++ b/src/js/components/SiteFooter.tsx @@ -1,13 +1,13 @@ import React from 'react'; -import { useTranslation } from 'react-i18next'; import { Layout, Row, Typography, Space } from 'antd'; const { Footer } = Layout; const { Title, Text, Link } = Typography; +import { useTranslationDefault } from '@/hooks'; import bentoLogo from '@public/assets/bento.svg'; const SiteFooter = () => { - const { t } = useTranslation(); + const td = useTranslationDefault(); return ( <Footer> @@ -22,7 +22,7 @@ const SiteFooter = () => { <div> <Text type="secondary"> Copyright © 2019-2023 the{' '} - <Link href="http://computationalgenomics.ca" target="_blank"> + <Link href="https://computationalgenomics.ca" target="_blank"> Canadian Centre for Computational Genomics </Link> . @@ -42,7 +42,7 @@ const SiteFooter = () => { </div> <div> <Link href="/public/terms.html" target="_blank"> - {t('Terms of Use')} + {td('Terms of Use')} </Link> </div> </Space> diff --git a/src/js/components/TabbedDashboard.tsx b/src/js/components/TabbedDashboard.tsx index 3a1f8a6e..a95237ce 100644 --- a/src/js/components/TabbedDashboard.tsx +++ b/src/js/components/TabbedDashboard.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; import { useNavigate, useLocation, useParams } from 'react-router-dom'; import { Tabs, Typography } from 'antd'; @@ -18,13 +17,12 @@ import PublicOverview from './Overview/PublicOverview'; import Search from './Search/Search'; import ProvenanceTab from './Provenance/ProvenanceTab'; import BeaconQueryUi from './Beacon/BeaconQueryUi'; -import { DEFAULT_TRANSLATION } from '@/constants/configConstants'; -import { useAppDispatch, useAppSelector } from '@/hooks'; +import { useAppDispatch, useAppSelector, useTranslationDefault } from '@/hooks'; import { buildQueryParamsUrl } from '@/utils/search'; const TabbedDashboard = () => { const dispatch = useAppDispatch(); - const { t } = useTranslation(DEFAULT_TRANSLATION); + const td = useTranslationDefault(); const navigate = useNavigate(); const location = useLocation(); const { page } = useParams<{ page?: string }>(); @@ -98,7 +96,7 @@ const TabbedDashboard = () => { const mappedTabPanes = tabPanes .filter((t) => t.active) .map(({ title, content, loading, key }) => ({ - label: <TabTitle title={t(title)} />, + label: <TabTitle title={td(title)} />, children: loading ? <Loader /> : content, key, })); diff --git a/src/js/components/Util/CustomEmpty.js b/src/js/components/Util/CustomEmpty.js index 640e14bc..8e0192c9 100644 --- a/src/js/components/Util/CustomEmpty.js +++ b/src/js/components/Util/CustomEmpty.js @@ -1,12 +1,11 @@ import React from 'react'; import { Empty } from 'antd'; -import { useTranslation } from 'react-i18next'; -import { DEFAULT_TRANSLATION } from '../../constants/configConstants'; +import { useTranslationDefault } from '@/hooks'; const CustomEmpty = ({ text }) => { - const { t } = useTranslation(DEFAULT_TRANSLATION); + const td = useTranslationDefault(); - return <Empty description={t(text)} />; + return <Empty description={td(text)} />; }; export default CustomEmpty; From 1d55c10cdb3849bad4068331d00a47407aed44cb Mon Sep 17 00:00:00 2001 From: David Lougheed <david.lougheed@gmail.com> Date: Wed, 1 Nov 2023 17:04:03 -0400 Subject: [PATCH 21/48] lint --- src/js/components/Overview/ChartCard.tsx | 4 +--- src/js/components/Overview/Drawer/ChartTree.tsx | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/js/components/Overview/ChartCard.tsx b/src/js/components/Overview/ChartCard.tsx index 37dd38ab..780bd336 100644 --- a/src/js/components/Overview/ChartCard.tsx +++ b/src/js/components/Overview/ChartCard.tsx @@ -2,12 +2,10 @@ import React, { memo } from 'react'; import Chart from './Chart'; import { Card, Button, Tooltip, Space, Typography, Row } from 'antd'; import { CloseOutlined, TeamOutlined, QuestionOutlined } from '@ant-design/icons'; -import { useTranslation } from 'react-i18next'; import CustomEmpty from '../Util/CustomEmpty'; -import { DEFAULT_TRANSLATION, NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; -import { ChartDataField } from '@/types/data'; import { CHART_HEIGHT } from '@/constants/overviewConstants'; import { useTranslationCustom, useTranslationDefault } from '@/hooks'; +import { ChartDataField } from '@/types/data'; const CARD_STYLE = { width: '100%', height: '415px', borderRadius: '11px' }; const ROW_EMPTY_STYLE = { height: `${CHART_HEIGHT}px` }; diff --git a/src/js/components/Overview/Drawer/ChartTree.tsx b/src/js/components/Overview/Drawer/ChartTree.tsx index 8938f631..de22fd7d 100644 --- a/src/js/components/Overview/Drawer/ChartTree.tsx +++ b/src/js/components/Overview/Drawer/ChartTree.tsx @@ -1,12 +1,10 @@ import React, { ReactNode, useMemo } from 'react'; import { useDispatch } from 'react-redux'; import { InputNumber, Tree, TreeProps } from 'antd'; -import { useTranslation } from 'react-i18next'; import { rearrange, setDisplayedCharts, setChartWidth } from '@/features/data/data.store'; -import { DEFAULT_TRANSLATION, NON_DEFAULT_TRANSLATION } from '@/constants/configConstants'; -import { ChartDataField } from '@/types/data'; import { useTranslationCustom, useTranslationDefault } from '@/hooks'; +import { ChartDataField } from '@/types/data'; interface MappedChartItem { title: ReactNode; From c8c53a80687ec0dd0620890596aa8717c132b3a9 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Wed, 8 Nov 2023 14:59:26 -0500 Subject: [PATCH 22/48] remove wes last ingestion retrieval --- main.go | 3 --- src/js/constants/configConstants.ts | 1 - 2 files changed, 4 deletions(-) diff --git a/main.go b/main.go index 70075b81..46c42be4 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,6 @@ const ConfigLogTemplate = `Config -- Static Files: %s Client Name: %s Katsu URL: %v - WES URL: %v Gohan URL: %v Bento Portal Url: %s Port: %d @@ -38,7 +37,6 @@ type BentoConfig struct { StaticFilesPath string `envconfig:"BENTO_PUBLIC_STATIC_FILES_PATH" default:"./www"` ClientName string `envconfig:"BENTO_PUBLIC_CLIENT_NAME"` KatsuUrl string `envconfig:"BENTO_PUBLIC_KATSU_URL"` - WesUrl string `envconfig:"BENTO_PUBLIC_WES_URL"` GohanUrl string `envconfig:"BENTO_PUBLIC_GOHAN_URL"` BentoPortalUrl string `envconfig:"BENTO_PUBLIC_PORTAL_URL"` Port int `envconfig:"INTERNAL_PORT" default:"8090"` @@ -116,7 +114,6 @@ func main() { cfg.StaticFilesPath, cfg.ClientName, cfg.KatsuUrl, - cfg.WesUrl, cfg.GohanUrl, cfg.BentoPortalUrl, cfg.Port, diff --git a/src/js/constants/configConstants.ts b/src/js/constants/configConstants.ts index c3c27e97..02425459 100644 --- a/src/js/constants/configConstants.ts +++ b/src/js/constants/configConstants.ts @@ -5,7 +5,6 @@ export const publicOverviewUrl = '/overview'; export const searchFieldsUrl = '/fields'; export const katsuUrl = '/katsu'; export const provenanceUrl = '/provenance'; -export const lastIngestionsUrl = '/wes-runs'; export const katsuLastIngestionsUrl = '/katsu/data-types'; export const gohanLastIngestionsUrl = '/gohan/data-types'; From e91b8182824279e295427a7dde5d3cbbf390e632 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Fri, 10 Nov 2023 14:51:08 -0500 Subject: [PATCH 23/48] Refactor last ingestion store --- .../features/ingestion/lastIngestion.store.ts | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/js/features/ingestion/lastIngestion.store.ts b/src/js/features/ingestion/lastIngestion.store.ts index 36554893..4d11bab6 100644 --- a/src/js/features/ingestion/lastIngestion.store.ts +++ b/src/js/features/ingestion/lastIngestion.store.ts @@ -40,6 +40,16 @@ const initialDataTypeState: DataTypeState = { dataTypes: [], }; +const reduceServiceDataTypes = ( + state: DataTypeState, + { payload }: PayloadAction<DataResponseArray> +) => { + const uniqueIds = new Set(state.dataTypes.map((data: DataTypeResponse) => data.id)); + const newData = payload.filter((data: DataTypeResponse) => !uniqueIds.has(data.id)); + state.dataTypes = [...state.dataTypes, ...newData]; + state.isFetchingData = false; +}; + // Create a slice to manage the state const DataTypeStore = createSlice({ name: 'dataTypes', @@ -52,17 +62,8 @@ const DataTypeStore = createSlice({ builder.addCase(fetchGohanData.pending, (state) => { state.isFetchingData = true; }); - builder.addCase(fetchKatsuData.fulfilled, (state, { payload }: PayloadAction<DataResponseArray>) => { - const uniqueIds = new Set(state.dataTypes.map((data) => data.id)); - const newData = payload.filter((data) => !uniqueIds.has(data.id)); - state.dataTypes = [...state.dataTypes, ...newData]; - }); - builder.addCase(fetchGohanData.fulfilled, (state, { payload }: PayloadAction<DataResponseArray>) => { - const uniqueIds = new Set(state.dataTypes.map((data) => data.id)); - const newData = payload.filter((data) => !uniqueIds.has(data.id)); - state.dataTypes = [...state.dataTypes, ...newData]; - state.isFetchingData = false; - }); + builder.addCase(fetchKatsuData.fulfilled, reduceServiceDataTypes); + builder.addCase(fetchGohanData.fulfilled, reduceServiceDataTypes); builder.addCase(fetchKatsuData.rejected, (state) => { state.isFetchingData = false; }); From ebee93d2c980ed94d6779f77f6ce971831bb623b Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Fri, 10 Nov 2023 14:54:06 -0500 Subject: [PATCH 24/48] lint --- src/js/features/ingestion/lastIngestion.store.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/js/features/ingestion/lastIngestion.store.ts b/src/js/features/ingestion/lastIngestion.store.ts index 4d11bab6..b1521894 100644 --- a/src/js/features/ingestion/lastIngestion.store.ts +++ b/src/js/features/ingestion/lastIngestion.store.ts @@ -40,10 +40,7 @@ const initialDataTypeState: DataTypeState = { dataTypes: [], }; -const reduceServiceDataTypes = ( - state: DataTypeState, - { payload }: PayloadAction<DataResponseArray> -) => { +const reduceServiceDataTypes = (state: DataTypeState, { payload }: PayloadAction<DataResponseArray>) => { const uniqueIds = new Set(state.dataTypes.map((data: DataTypeResponse) => data.id)); const newData = payload.filter((data: DataTypeResponse) => !uniqueIds.has(data.id)); state.dataTypes = [...state.dataTypes, ...newData]; From bf98a5f23191644fc64e1fd42a1e8bfce75ca4ef Mon Sep 17 00:00:00 2001 From: noctillion <ornatus30@gmail.com> Date: Fri, 10 Nov 2023 19:11:19 -0500 Subject: [PATCH 25/48] Update LastIngestion.tsx remove typo --- src/js/components/Overview/LastIngestion.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/components/Overview/LastIngestion.tsx b/src/js/components/Overview/LastIngestion.tsx index 57ff48bb..88ea533c 100644 --- a/src/js/components/Overview/LastIngestion.tsx +++ b/src/js/components/Overview/LastIngestion.tsx @@ -36,7 +36,7 @@ const LastIngestionInfo: React.FC = () => { return ( <Space direction="vertical" size={0}> - <Typography.Title level={3}>{t('Latest Data IngestionX')}</Typography.Title> + <Typography.Title level={3}>{t('Latest Data Ingestion')}</Typography.Title> <Space direction="horizontal"> {hasData ? ( queryableDataTypes.map((dataType: LastIngestionDataTypeResponse) => ( From e413073f4a0874139204248008b6bd9236463c39 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Wed, 15 Nov 2023 16:42:07 -0500 Subject: [PATCH 26/48] Set count to null from gohan data-types response --- main.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 46c42be4..f8413d15 100644 --- a/main.go +++ b/main.go @@ -200,7 +200,22 @@ func main() { return err } - return c.JSON(http.StatusOK, result) + resultSlice, ok := result.([]JsonLike) + if !ok { + return fmt.Errorf("result is not of type []JsonLike") + } + + var modifiedResult []JsonLike + + // Remove the "count" key + for _, item := range resultSlice { + item["count"] = nil + modifiedResult = append(modifiedResult, item) + } + + fmt.Printf("modifiedResult: %v\n", modifiedResult) + + return c.JSON(http.StatusOK, modifiedResult) } fetchAndSetKatsuPublic := func(c echo.Context, katsuCache *cache.Cache) (JsonLike, error) { From d48c0a2737fc27bd05daaec6396860b0388a843c Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Wed, 15 Nov 2023 16:45:32 -0500 Subject: [PATCH 27/48] correct comment --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index f8413d15..ad747ee2 100644 --- a/main.go +++ b/main.go @@ -207,7 +207,7 @@ func main() { var modifiedResult []JsonLike - // Remove the "count" key + // Update the "count" value for _, item := range resultSlice { item["count"] = nil modifiedResult = append(modifiedResult, item) From e91b57ab7e3dd4db3cdba68ad35fbc7df374ab35 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Wed, 15 Nov 2023 16:59:01 -0500 Subject: [PATCH 28/48] remove logs --- main.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/main.go b/main.go index ad747ee2..df5f9562 100644 --- a/main.go +++ b/main.go @@ -213,8 +213,6 @@ func main() { modifiedResult = append(modifiedResult, item) } - fmt.Printf("modifiedResult: %v\n", modifiedResult) - return c.JSON(http.StatusOK, modifiedResult) } From 4cee04329635a1103738ca4033c7ad6a7d702888 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Thu, 16 Nov 2023 17:33:08 -0500 Subject: [PATCH 29/48] Add request handling for data-types endpoint and count value removal --- main.go | 46 ++++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/main.go b/main.go index df5f9562..f3dc055a 100644 --- a/main.go +++ b/main.go @@ -193,27 +193,28 @@ func main() { return jsonFormattedData, nil } - gohanRequestPublic := func(c echo.Context) error { - path := fmt.Sprintf("/data-types") - result, err := genericRequestJsonOnly(fmt.Sprintf("%s%s", cfg.GohanUrl, path), nil, c, jsonDeserialize) - if err != nil { - return err - } + dataTypesEndpointHandler := func(baseUrl string) echo.HandlerFunc { + return func(c echo.Context) error { + fullPath := fmt.Sprintf("%s/data-types", baseUrl) + result, err := genericRequestJsonOnly(fullPath, nil, c, jsonDeserialize) + if err != nil { + return err + } - resultSlice, ok := result.([]JsonLike) - if !ok { - return fmt.Errorf("result is not of type []JsonLike") - } + resultSlice, ok := result.([]JsonLike) + if !ok { + return fmt.Errorf("result is not of type []JsonLike") + } - var modifiedResult []JsonLike + var modifiedResult []JsonLike + // Update the "count" value + for _, item := range resultSlice { + item["count"] = nil + modifiedResult = append(modifiedResult, item) + } - // Update the "count" value - for _, item := range resultSlice { - item["count"] = nil - modifiedResult = append(modifiedResult, item) + return c.JSON(http.StatusOK, modifiedResult) } - - return c.JSON(http.StatusOK, modifiedResult) } fetchAndSetKatsuPublic := func(c echo.Context, katsuCache *cache.Cache) (JsonLike, error) { @@ -388,16 +389,9 @@ func main() { return c.String(http.StatusOK, string(data)) }) - e.GET("/gohan/data-types", gohanRequestPublic) + e.GET("/gohan/data-types", dataTypesEndpointHandler(cfg.GohanUrl)) - e.GET("/katsu/data-types", func(c echo.Context) error { - data, err := katsuRequestFormattedData("/data-types", c) - if err != nil { - return err - } - - return c.String(http.StatusOK, string(data)) - }) + e.GET("/katsu/data-types", dataTypesEndpointHandler(cfg.KatsuUrl)) // Run e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.Port))) From 8525ad89d556527f06d226037edb81b18266a998 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 09:50:21 -0500 Subject: [PATCH 30/48] Add clinical data to translation --- src/public/locales/en/default_translation_en.json | 3 ++- src/public/locales/fr/default_translation_fr.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/public/locales/en/default_translation_en.json b/src/public/locales/en/default_translation_en.json index b3587487..74c37cf8 100644 --- a/src/public/locales/en/default_translation_en.json +++ b/src/public/locales/en/default_translation_en.json @@ -74,5 +74,6 @@ "e.g.": "e.g.", "or": "or", "Ingestion History Is Empty": "Ingestion History Is Empty", - "Latest Data Ingestion": "Latest Data Ingestion" + "Latest Data Ingestion": "Latest Data Ingestion", + "Clinical Data": "Clinical Data" } \ No newline at end of file diff --git a/src/public/locales/fr/default_translation_fr.json b/src/public/locales/fr/default_translation_fr.json index b5e11373..1b2194ce 100644 --- a/src/public/locales/fr/default_translation_fr.json +++ b/src/public/locales/fr/default_translation_fr.json @@ -74,5 +74,6 @@ "e.g.": "par exemple", "or": "ou", "Ingestion History Is Empty": "L'historique d'ingestion est vide", - "Latest Data Ingestion": "Dernière ingestion de données" + "Latest Data Ingestion": "Dernière ingestion de données", + "Clinical Data": "Données cliniques" } \ No newline at end of file From 1bfae35a33fbfc1fdf8179f7fd2ecefb8884443d Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 09:54:37 -0500 Subject: [PATCH 31/48] Remove redundant types --- src/js/features/ingestion/lastIngestion.store.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/js/features/ingestion/lastIngestion.store.ts b/src/js/features/ingestion/lastIngestion.store.ts index b1521894..0010bcb9 100644 --- a/src/js/features/ingestion/lastIngestion.store.ts +++ b/src/js/features/ingestion/lastIngestion.store.ts @@ -3,15 +3,7 @@ import axios from 'axios'; import { katsuLastIngestionsUrl, gohanLastIngestionsUrl } from '@/constants/configConstants'; import { printAPIError } from '@/utils/error.util'; -export interface DataTypeResponse { - count: number | null; - id: string; - label: string; - last_ingested: string | null; - queryable: boolean; -} - -export type DataResponseArray = DataTypeResponse[]; +import { LastIngestionDataTypeResponse, DataTypeMap } from '@/types/lastIngestionDataTypeResponse'; // Async thunks to fetch data from the two endpoints export const fetchKatsuData = createAsyncThunk('dataTypes/fetchKatsuData', (_, { rejectWithValue }) => From 012932d0122df23fbb09b17d9131ab1361a3d447 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 09:55:45 -0500 Subject: [PATCH 32/48] Refactor lastIngestion store to keep rendering order --- .../features/ingestion/lastIngestion.store.ts | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/js/features/ingestion/lastIngestion.store.ts b/src/js/features/ingestion/lastIngestion.store.ts index 0010bcb9..9206e91c 100644 --- a/src/js/features/ingestion/lastIngestion.store.ts +++ b/src/js/features/ingestion/lastIngestion.store.ts @@ -22,21 +22,25 @@ export const fetchGohanData = createAsyncThunk('dataTypes/fetchGohanData', (_, { // Define the state structure export interface DataTypeState { - isFetchingData: boolean; - dataTypes: DataResponseArray; + isFetchingKatsuData: boolean; + isFetchingGohanData: boolean; + dataTypes: DataTypeMap; } // Initialize the state const initialDataTypeState: DataTypeState = { - isFetchingData: false, - dataTypes: [], + isFetchingKatsuData: false, + isFetchingGohanData: false, + dataTypes: {}, }; -const reduceServiceDataTypes = (state: DataTypeState, { payload }: PayloadAction<DataResponseArray>) => { - const uniqueIds = new Set(state.dataTypes.map((data: DataTypeResponse) => data.id)); - const newData = payload.filter((data: DataTypeResponse) => !uniqueIds.has(data.id)); - state.dataTypes = [...state.dataTypes, ...newData]; - state.isFetchingData = false; +const reduceServiceDataTypes = (state: DataTypeState, { payload }: PayloadAction<LastIngestionDataTypeResponse[]>) => { + state.dataTypes = { + ...state.dataTypes, + ...Object.fromEntries(payload.map((data) => [data.id, data])), + }; + state.isFetchingKatsuData = false; + state.isFetchingGohanData = false; }; // Create a slice to manage the state @@ -46,18 +50,18 @@ const DataTypeStore = createSlice({ reducers: {}, extraReducers: (builder) => { builder.addCase(fetchKatsuData.pending, (state) => { - state.isFetchingData = true; + state.isFetchingKatsuData = true; }); builder.addCase(fetchGohanData.pending, (state) => { - state.isFetchingData = true; + state.isFetchingGohanData = true; }); builder.addCase(fetchKatsuData.fulfilled, reduceServiceDataTypes); builder.addCase(fetchGohanData.fulfilled, reduceServiceDataTypes); builder.addCase(fetchKatsuData.rejected, (state) => { - state.isFetchingData = false; + state.isFetchingKatsuData = false; }); builder.addCase(fetchGohanData.rejected, (state) => { - state.isFetchingData = false; + state.isFetchingGohanData = false; }); }, }); From 5025155ea851b6ef69b1143eb4bf63422dc708f7 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 09:56:16 -0500 Subject: [PATCH 33/48] Refactor LastIngestion types --- src/js/types/lastIngestionDataTypeResponse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/types/lastIngestionDataTypeResponse.ts b/src/js/types/lastIngestionDataTypeResponse.ts index c3e7eebe..617bd148 100644 --- a/src/js/types/lastIngestionDataTypeResponse.ts +++ b/src/js/types/lastIngestionDataTypeResponse.ts @@ -6,4 +6,4 @@ export interface LastIngestionDataTypeResponse { queryable: boolean; } -export type DataResponseArray = LastIngestionDataTypeResponse[]; +export type DataTypeMap = { [id: string]: LastIngestionDataTypeResponse }; From a6e6fe3a9d2b66b07b0c8a8f9ada3c8691f2c131 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 09:56:56 -0500 Subject: [PATCH 34/48] Refactor lastIngestion rendering --- src/js/components/Overview/LastIngestion.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/js/components/Overview/LastIngestion.tsx b/src/js/components/Overview/LastIngestion.tsx index 88ea533c..0ccd0bc4 100644 --- a/src/js/components/Overview/LastIngestion.tsx +++ b/src/js/components/Overview/LastIngestion.tsx @@ -6,14 +6,19 @@ import { useTranslation } from 'react-i18next'; import { DEFAULT_TRANSLATION } from '@/constants/configConstants'; import { useAppSelector } from '@/hooks'; import { getDataTypeLabel } from '@/types/dataTypes'; -import { LastIngestionDataTypeResponse, DataResponseArray } from '@/types/lastIngestionDataTypeResponse'; + +import { LastIngestionDataTypeResponse } from '@/types/lastIngestionDataTypeResponse'; const LastIngestionInfo: React.FC = () => { const { t, i18n } = useTranslation(DEFAULT_TRANSLATION); - const lastEndTimesByDataType: DataResponseArray = useAppSelector((state) => state.lastIngestionData?.dataTypes) || []; + const dataTypesObject = useAppSelector((state) => state.lastIngestionData?.dataTypes) || {}; + const dataTypesArray = Object.values(dataTypesObject); + + const sortedDataTypes = dataTypesArray.sort((a, b) => a.label.localeCompare(b.label)); - const queryableDataTypes = lastEndTimesByDataType.filter((item: LastIngestionDataTypeResponse) => item.queryable); + // Filter out the queryable data types + const queryableDataTypes = sortedDataTypes.filter((dataType: LastIngestionDataTypeResponse) => dataType.queryable); const formatDate = useCallback( (dateString: string) => { @@ -42,7 +47,7 @@ const LastIngestionInfo: React.FC = () => { queryableDataTypes.map((dataType: LastIngestionDataTypeResponse) => ( <Card key={dataType.id}> <Space direction="vertical"> - <Typography.Text style={{ color: 'rgba(0,0,0,0.45)' }}>{getDataTypeLabel(dataType.id)}</Typography.Text> + <Typography.Text style={{ color: 'rgba(0,0,0,0.45)' }}>{t(getDataTypeLabel(dataType.id))}</Typography.Text> <Typography.Text> <CalendarOutlined /> {dataType.last_ingested ? formatDate(dataType.last_ingested) : 'Not Available'} </Typography.Text> From 89eb3d5ac188bf96e91b322b66e17da1a8f5999a Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 09:59:05 -0500 Subject: [PATCH 35/48] lint --- src/js/components/Overview/LastIngestion.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/js/components/Overview/LastIngestion.tsx b/src/js/components/Overview/LastIngestion.tsx index 0ccd0bc4..76fe7739 100644 --- a/src/js/components/Overview/LastIngestion.tsx +++ b/src/js/components/Overview/LastIngestion.tsx @@ -47,7 +47,9 @@ const LastIngestionInfo: React.FC = () => { queryableDataTypes.map((dataType: LastIngestionDataTypeResponse) => ( <Card key={dataType.id}> <Space direction="vertical"> - <Typography.Text style={{ color: 'rgba(0,0,0,0.45)' }}>{t(getDataTypeLabel(dataType.id))}</Typography.Text> + <Typography.Text style={{ color: 'rgba(0,0,0,0.45)' }}> + {t(getDataTypeLabel(dataType.id))} + </Typography.Text> <Typography.Text> <CalendarOutlined /> {dataType.last_ingested ? formatDate(dataType.last_ingested) : 'Not Available'} </Typography.Text> From b39f43ac3663175a8bba41cdb18e98e6ada668a0 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 10:52:17 -0500 Subject: [PATCH 36/48] Refactor combine array creation and sorting --- src/js/components/Overview/LastIngestion.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/js/components/Overview/LastIngestion.tsx b/src/js/components/Overview/LastIngestion.tsx index 76fe7739..d486153b 100644 --- a/src/js/components/Overview/LastIngestion.tsx +++ b/src/js/components/Overview/LastIngestion.tsx @@ -13,9 +13,8 @@ const LastIngestionInfo: React.FC = () => { const { t, i18n } = useTranslation(DEFAULT_TRANSLATION); const dataTypesObject = useAppSelector((state) => state.lastIngestionData?.dataTypes) || {}; - const dataTypesArray = Object.values(dataTypesObject); - const sortedDataTypes = dataTypesArray.sort((a, b) => a.label.localeCompare(b.label)); + const sortedDataTypes = Object.values(dataTypesObject).sort((a, b) => a.label.localeCompare(b.label)); // Filter out the queryable data types const queryableDataTypes = sortedDataTypes.filter((dataType: LastIngestionDataTypeResponse) => dataType.queryable); From 8a038e5b6babc1e28f19f221ba0e7ab2070f28a0 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 11:05:01 -0500 Subject: [PATCH 37/48] Update fetching status flags --- src/js/features/ingestion/lastIngestion.store.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/js/features/ingestion/lastIngestion.store.ts b/src/js/features/ingestion/lastIngestion.store.ts index 9206e91c..09146e2e 100644 --- a/src/js/features/ingestion/lastIngestion.store.ts +++ b/src/js/features/ingestion/lastIngestion.store.ts @@ -39,8 +39,6 @@ const reduceServiceDataTypes = (state: DataTypeState, { payload }: PayloadAction ...state.dataTypes, ...Object.fromEntries(payload.map((data) => [data.id, data])), }; - state.isFetchingKatsuData = false; - state.isFetchingGohanData = false; }; // Create a slice to manage the state @@ -55,8 +53,14 @@ const DataTypeStore = createSlice({ builder.addCase(fetchGohanData.pending, (state) => { state.isFetchingGohanData = true; }); - builder.addCase(fetchKatsuData.fulfilled, reduceServiceDataTypes); - builder.addCase(fetchGohanData.fulfilled, reduceServiceDataTypes); + builder.addCase(fetchKatsuData.fulfilled, (state, action) => { + reduceServiceDataTypes(state, action); + state.isFetchingKatsuData = false; + }); + builder.addCase(fetchGohanData.fulfilled, (state, action) => { + reduceServiceDataTypes(state, action); + state.isFetchingGohanData = false; + }); builder.addCase(fetchKatsuData.rejected, (state) => { state.isFetchingKatsuData = false; }); From 4006fdcc7e4eb362675c5f21287c1fd3611595e7 Mon Sep 17 00:00:00 2001 From: Julian <ornatus30@gmail.com> Date: Mon, 20 Nov 2023 13:22:55 -0500 Subject: [PATCH 38/48] Disable makeGetDataTypes dispatch --- src/js/components/TabbedDashboard.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/js/components/TabbedDashboard.tsx b/src/js/components/TabbedDashboard.tsx index cdff2d2b..0b2c3b64 100644 --- a/src/js/components/TabbedDashboard.tsx +++ b/src/js/components/TabbedDashboard.tsx @@ -11,7 +11,6 @@ import { makeGetDataRequestThunk } from '@/features/data/data.store'; import { makeGetSearchFields } from '@/features/search/query.store'; import { makeGetProvenanceRequest } from '@/features/provenance/provenance.store'; import { getBeaconConfig } from '@/features/beacon/beaconConfig.store'; -import { makeGetDataTypes } from '@/features/dataTypes/dataTypes.store'; import { fetchGohanData, fetchKatsuData } from '@/features/ingestion/lastIngestion.store'; import Loader from './Loader'; @@ -38,7 +37,7 @@ const TabbedDashboard = () => { dispatch(makeGetProvenanceRequest()); dispatch(fetchKatsuData()); dispatch(fetchGohanData()); - dispatch(makeGetDataTypes()); + //TODO: Dispatch makeGetDataTypes to get the data types from service-registry }, []); const isFetchingOverviewData = useAppSelector((state) => state.data.isFetchingData); From 7173dabe76aef71a3f25d9bde200f7fe7d274c14 Mon Sep 17 00:00:00 2001 From: Sanjeev Lakhwani <lakhwani.sanjeev691@gmail.com> Date: Wed, 29 Nov 2023 14:33:03 -0500 Subject: [PATCH 39/48] Added loading status to beacon search --- src/js/components/Beacon/BeaconQueryUi.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/js/components/Beacon/BeaconQueryUi.tsx b/src/js/components/Beacon/BeaconQueryUi.tsx index 8a226f95..2e80641a 100644 --- a/src/js/components/Beacon/BeaconQueryUi.tsx +++ b/src/js/components/Beacon/BeaconQueryUi.tsx @@ -132,6 +132,8 @@ const BeaconQueryUi = () => { </Tooltip> ); }; + + const isFetchingBeaconQuery = useAppSelector((state) => state.beaconQuery.isFetchingQueryResponse); return ( <div style={WRAPPER_STYLE}> @@ -173,7 +175,7 @@ const BeaconQueryUi = () => { <Row> <Col span={24}> <div style={BUTTON_AREA_STYLE}> - <Button type="primary" htmlType="submit" style={BUTTON_STYLE}> + <Button type="primary" htmlType="submit" loading={isFetchingBeaconQuery} style={BUTTON_STYLE}> {td('Search Beacon')} </Button> <Button onClick={handleClearForm} style={BUTTON_STYLE}> From ed0d92aa9874d85b8b244dcf483229d34cf729c7 Mon Sep 17 00:00:00 2001 From: Sanjeev Lakhwani <lakhwani.sanjeev691@gmail.com> Date: Wed, 29 Nov 2023 15:24:18 -0500 Subject: [PATCH 40/48] Added show all and hide all functionality --- .../Overview/Drawer/ManageChartsDrawer.tsx | 48 +++++++++++++++++-- src/js/features/data/data.store.ts | 31 +++++++++++- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx b/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx index 456f930c..eff27a70 100644 --- a/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx +++ b/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx @@ -1,24 +1,64 @@ import React from 'react'; -import { Drawer, DrawerProps, Typography } from 'antd'; +import { Button, Drawer, DrawerProps, Flex, Space, Typography } from 'antd'; const { Title } = Typography; import ChartTree from './ChartTree'; import { ChartDataField } from '@/types/data'; -import { useAppSelector, useTranslationCustom, useTranslationDefault } from '@/hooks'; +import { useAppSelector, useAppDispatch, useTranslationCustom, useTranslationDefault } from '@/hooks'; +import { hideAllSectionCharts, setAllDisplayedCharts } from '@/features/data/data.store'; const ManageChartsDrawer = ({ onManageDrawerClose, manageDrawerVisible }: ManageChartsDrawerProps) => { const t = useTranslationCustom(); const td = useTranslationDefault(); + const dispatch = useAppDispatch(); + const sections = useAppSelector((state) => state.data.sections); return ( - <Drawer title={td('Manage Charts')} placement="right" onClose={onManageDrawerClose} open={manageDrawerVisible}> + <Drawer + title={td('Manage Charts')} + placement="right" + onClose={onManageDrawerClose} + open={manageDrawerVisible} + extra={ + <Button + size="small" + onClick={() => { + dispatch(setAllDisplayedCharts({})); + }} + > + Show All + </Button> + } + > {sections.map(({ sectionTitle, charts }: { sectionTitle: string; charts: ChartDataField[] }, i: number) => ( <div key={i}> - <Title level={5}>{t(sectionTitle)} + + + {t(sectionTitle)} + + + + + +
))} diff --git a/src/js/features/data/data.store.ts b/src/js/features/data/data.store.ts index 34c697c8..45d3f966 100644 --- a/src/js/features/data/data.store.ts +++ b/src/js/features/data/data.store.ts @@ -47,6 +47,28 @@ const data = createSlice({ const chartObj = state.sections.find((e) => e.sectionTitle === section)!.charts.find((c) => c.id === chart)!; chartObj.width = width; }, + setAllDisplayedCharts: (state, { payload }: PayloadAction<{ section?: string }>) => { + if (payload.section) { + state.sections + .find((e) => e.sectionTitle === payload.section)! + .charts.forEach((_, ind, arr) => { + arr[ind].isDisplayed = true; + }); + } else { + state.sections.forEach((section) => { + section.charts.forEach((val, ind, arr) => { + arr[ind].isDisplayed = true; + }); + }); + } + }, + hideAllSectionCharts: (state, { payload }: PayloadAction<{ section: string }>) => { + state.sections + .find((e) => e.sectionTitle === payload.section)! + .charts.forEach((_, ind, arr) => { + arr[ind].isDisplayed = false; + }); + }, }, extraReducers: (builder) => { builder @@ -64,6 +86,13 @@ const data = createSlice({ }, }); -export const { rearrange, disableChart, setDisplayedCharts, setChartWidth } = data.actions; +export const { + rearrange, + disableChart, + setDisplayedCharts, + setChartWidth, + setAllDisplayedCharts, + hideAllSectionCharts, +} = data.actions; export { makeGetDataRequestThunk }; export default data.reducer; From 5d1fe9e189dccc50b5bf2b646d5563e4002e2a81 Mon Sep 17 00:00:00 2001 From: Sanjeev Lakhwani Date: Wed, 29 Nov 2023 15:33:20 -0500 Subject: [PATCH 41/48] ran prettier --- .../Overview/Drawer/ManageChartsDrawer.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx b/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx index eff27a70..0d7203f4 100644 --- a/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx +++ b/src/js/components/Overview/Drawer/ManageChartsDrawer.tsx @@ -36,19 +36,19 @@ const ManageChartsDrawer = ({ onManageDrawerClose, manageDrawerVisible }: Manage > {sections.map(({ sectionTitle, charts }: { sectionTitle: string; charts: ChartDataField[] }, i: number) => (
- + {t(sectionTitle)} - +