diff --git a/strudel-taskflows/src/components/CheckboxList.tsx b/strudel-taskflows/src/components/CheckboxList.tsx index a3b40d73..9cf879fc 100644 --- a/strudel-taskflows/src/components/CheckboxList.tsx +++ b/strudel-taskflows/src/components/CheckboxList.tsx @@ -39,8 +39,9 @@ export const CheckboxList: React.FC = ({ }; useEffect(() => { - console.log(checkValues) - if (onChange) onChange(checkValues); + if (onChange && checkValues?.length !== values?.length) { + onChange(checkValues); + } }, [checkValues]); useEffect(() => { diff --git a/strudel-taskflows/src/components/FilterContext.tsx b/strudel-taskflows/src/components/FilterContext.tsx index 4623155d..8330b271 100644 --- a/strudel-taskflows/src/components/FilterContext.tsx +++ b/strudel-taskflows/src/components/FilterContext.tsx @@ -43,15 +43,10 @@ function filterReducer(state: FilterState, action: FilterAction): FilterState { } else if (filter.value) { activeFilters.push(filter); } - console.log(activeFilters); return { ...state, activeFilters } - // return { - // ...state, - // activeFilters: { ...state.activeFilters, [action.payload.field]: action.payload.value } - // } } case 'SET_ACTIVE_FILTERS': { return { @@ -95,14 +90,6 @@ export const FilterContext: React.FC = ({ if (onChange) onChange(state.activeFilters); }, [JSON.stringify(state.activeFilters)]); - /** - * If activeFilters is changed from outside the context (e.g. filters are reset) - * then the new value should be dispatched. - */ - // useEffect(() => { - // dispatch({ type: 'SET_ACTIVE_FILTERS', payload: activeFilters }); - // }, [activeFilters]); - return ( {children} diff --git a/strudel-taskflows/src/components/PageHeader.tsx b/strudel-taskflows/src/components/PageHeader.tsx index 1eaf76ec..df39415e 100644 --- a/strudel-taskflows/src/components/PageHeader.tsx +++ b/strudel-taskflows/src/components/PageHeader.tsx @@ -3,7 +3,7 @@ import { PaperProps, Breadcrumbs, Link, Paper, Stack, Typography } from '@mui/ma import HomeIcon from '@mui/icons-material/Home'; interface PageHeaderProps extends PaperProps { - pageTitle: string; + pageTitle: React.ReactNode; breadcrumbTitle?: string; description?: string; actions?: React.ReactNode; diff --git a/strudel-taskflows/src/pages/explore-data/[id].tsx b/strudel-taskflows/src/pages/explore-data/[id].tsx index 0fbe0c16..8271f117 100644 --- a/strudel-taskflows/src/pages/explore-data/[id].tsx +++ b/strudel-taskflows/src/pages/explore-data/[id].tsx @@ -3,23 +3,48 @@ import React from 'react'; import { useParams } from 'react-router-dom'; import { PageHeader } from '../../components/PageHeader'; import { taskflow } from './_config/taskflow.config'; +import { useQuery } from '@tanstack/react-query'; + +interface DataDetailPageProps { + item: any +} /** - * Work in Progress: - * * Detail view for a selected row from the` ` in the explore-data Task Flow. */ -const DataDetailPage: React.FC = () => { +const DataDetailPage: React.FC = ({ item }) => { const params = useParams(); + const dataSource = taskflow.data.item.source; const dataIdField = taskflow.data.items.idField; const columns = taskflow.pages.index.tableColumns; - const data: any[] = []; - const entity = data?.find((d) => { - if (params.id) { - return d[dataIdField].toString() === params.id.toString(); + const queryMode = taskflow.data.items.queryMode; + const staticParams = taskflow.data.items.staticParams; + let queryParams = { ...staticParams }; + const queryString = new URLSearchParams(queryParams).toString(); + let queryFn; + if (queryMode === 'server') { + queryFn = async (): Promise => { + const response = await fetch(`${dataSource}/${params.id}?${queryString}`); + return await response.json(); + } + } else if (queryMode === 'client') { + queryFn = async (): Promise => { + const response = await fetch(`${dataSource}?${queryString}`); + const results = await response.json(); + return results?.find((d: any) => { + if (params.id) { + return d[dataIdField].toString() === params.id.toString(); + } + }); } + } + + + // Define query for this page and fetch data items + const { isPending, isFetching, isError, data, error } = useQuery({ + queryKey: ['item', params.id, queryParams], + queryFn, }); - const entityTitle = entity ? entity[columns[0].field] : 'Not Found'; /** * Content to render on the page for this component @@ -27,7 +52,7 @@ const DataDetailPage: React.FC = () => { return ( { {columns[1].field} - {entity && entity[columns[1].field]} + {data && data[columns[1].field]} - - More coming soon! - diff --git a/strudel-taskflows/src/pages/explore-data/_config/exoplanets.config.ts b/strudel-taskflows/src/pages/explore-data/_config/exoplanets.config.ts index 519a2f93..209e0e78 100644 --- a/strudel-taskflows/src/pages/explore-data/_config/exoplanets.config.ts +++ b/strudel-taskflows/src/pages/explore-data/_config/exoplanets.config.ts @@ -2,9 +2,12 @@ import { ExploreDataConfig } from "./taskflow.types"; export const taskflow: ExploreDataConfig = { data: { + /** + * Data definition for the initial items list + */ items: { /** - * Source of the data for the initial list of items on the main page. + * URL or path to the data source */ source: "https://exoplanetarchive.ipac.caltech.edu/cgi-bin/nstedAPI/nph-nstedAPI", /** @@ -15,6 +18,21 @@ export const taskflow: ExploreDataConfig = { * Method by which data should be filtered, either client or server. */ queryMode: "client", + /** + * Key-value object of params that should always be included in the query URL + */ + staticParams: { + table: 'cumulative', + format: 'json' + } + }, + /** + * Data definition for the item detail page + */ + item: { + source: "https://exoplanetarchive.ipac.caltech.edu/cgi-bin/nstedAPI/nph-nstedAPI", + idField: "kepoi_name", + queryMode: "client", staticParams: { table: 'cumulative', format: 'json' @@ -42,22 +60,22 @@ export const taskflow: ExploreDataConfig = { }, { field: "kepoi_name", - headerName: "Name", + headerName: "Kepler OI Name", width: 150 }, { - field: "koi_disposition", - headerName: "koi_disposition", + field: "kepler_name", + headerName: "Kepler Name", width: 150 }, { - field: "koi_pdisposition", - headerName: "koi_pdisposition", + field: "koi_disposition", + headerName: "Disposition", width: 150 }, { field: "koi_period", - headerName: "koi_period", + headerName: "Period", width: 150, type: 'number' } diff --git a/strudel-taskflows/src/pages/explore-data/_config/gbif.config.ts b/strudel-taskflows/src/pages/explore-data/_config/gbif.config.ts index e20254f9..a126f1c3 100644 --- a/strudel-taskflows/src/pages/explore-data/_config/gbif.config.ts +++ b/strudel-taskflows/src/pages/explore-data/_config/gbif.config.ts @@ -2,9 +2,12 @@ import { ExploreDataConfig } from "./taskflow.types"; export const taskflow: ExploreDataConfig = { data: { + /** + * Data definition for the initial items list + */ items: { /** - * Source of the data for the initial list of items on the main page. + * URL or path to the data source */ source: "https://api.gbif.org/v1/occurrence/search", /** @@ -14,7 +17,20 @@ export const taskflow: ExploreDataConfig = { /** * Method by which data should be filtered, either client or server. */ - queryMode: "server" + queryMode: "server", + /** + * Key-value object of params that should always be included in the query URL + */ + staticParams: null + }, + /** + * Data definition for the item detail page + */ + item: { + source: "https://api.gbif.org/v1/occurrence", + idField: "key", + queryMode: "server", + staticParams: null } }, pages: { diff --git a/strudel-taskflows/src/pages/explore-data/_config/taskflow.config.ts b/strudel-taskflows/src/pages/explore-data/_config/taskflow.config.ts index 519a2f93..209e0e78 100644 --- a/strudel-taskflows/src/pages/explore-data/_config/taskflow.config.ts +++ b/strudel-taskflows/src/pages/explore-data/_config/taskflow.config.ts @@ -2,9 +2,12 @@ import { ExploreDataConfig } from "./taskflow.types"; export const taskflow: ExploreDataConfig = { data: { + /** + * Data definition for the initial items list + */ items: { /** - * Source of the data for the initial list of items on the main page. + * URL or path to the data source */ source: "https://exoplanetarchive.ipac.caltech.edu/cgi-bin/nstedAPI/nph-nstedAPI", /** @@ -15,6 +18,21 @@ export const taskflow: ExploreDataConfig = { * Method by which data should be filtered, either client or server. */ queryMode: "client", + /** + * Key-value object of params that should always be included in the query URL + */ + staticParams: { + table: 'cumulative', + format: 'json' + } + }, + /** + * Data definition for the item detail page + */ + item: { + source: "https://exoplanetarchive.ipac.caltech.edu/cgi-bin/nstedAPI/nph-nstedAPI", + idField: "kepoi_name", + queryMode: "client", staticParams: { table: 'cumulative', format: 'json' @@ -42,22 +60,22 @@ export const taskflow: ExploreDataConfig = { }, { field: "kepoi_name", - headerName: "Name", + headerName: "Kepler OI Name", width: 150 }, { - field: "koi_disposition", - headerName: "koi_disposition", + field: "kepler_name", + headerName: "Kepler Name", width: 150 }, { - field: "koi_pdisposition", - headerName: "koi_pdisposition", + field: "koi_disposition", + headerName: "Disposition", width: 150 }, { field: "koi_period", - headerName: "koi_period", + headerName: "Period", width: 150, type: 'number' } diff --git a/strudel-taskflows/src/pages/explore-data/_config/taskflow.types.ts b/strudel-taskflows/src/pages/explore-data/_config/taskflow.types.ts index 9d4f2041..43b6b2a6 100644 --- a/strudel-taskflows/src/pages/explore-data/_config/taskflow.types.ts +++ b/strudel-taskflows/src/pages/explore-data/_config/taskflow.types.ts @@ -13,13 +13,13 @@ export interface ExploreDataConfig { source: string, idField: string, queryMode: 'client' | 'server', - staticParams?: Record + staticParams?: Record | null }, [key: string]: { source: string, idField: string, queryMode: 'client' | 'server', - staticParams?: Record + staticParams?: Record | null } }, pages: { diff --git a/strudel-taskflows/src/pages/explore-data/index.tsx b/strudel-taskflows/src/pages/explore-data/index.tsx index d9a2dc0f..67ab32d9 100644 --- a/strudel-taskflows/src/pages/explore-data/index.tsx +++ b/strudel-taskflows/src/pages/explore-data/index.tsx @@ -1,4 +1,4 @@ -import { Box, Grid, Paper } from '@mui/material'; +import { Box, Paper, Stack } from '@mui/material'; import React, { useState } from 'react'; import { FilterContext } from '../../components/FilterContext'; import { PageHeader } from '../../components/PageHeader'; @@ -41,17 +41,23 @@ const DataExplorer: React.FC = () => { padding: 2, }} /> - - {showFiltersPanel && ( - - - - )} - + + + {showFiltersPanel && ( + + + + )} { setPreviewItem={setPreviewItem} /> - - {previewItem && ( - - - - )} - + {previewItem && ( + + + + )} + + ) } -const getMainColumnSize = (showFiltersPanel: boolean, showPreviewPanel: boolean) => { - if (!showFiltersPanel && !showPreviewPanel) { - return 12; - } else if (showFiltersPanel && !showPreviewPanel) { - return 10; - } else if (!showFiltersPanel && showPreviewPanel) { - return 8; - } else if (showFiltersPanel && showPreviewPanel) { - return 6; - } -} - export default DataExplorer; \ No newline at end of file