From 9ed133f7e0f126a052103feabda4a0e9ecfe029d Mon Sep 17 00:00:00 2001 From: Natanael Date: Thu, 29 Feb 2024 18:05:00 -0300 Subject: [PATCH] multiple custom imaging columns --- components/xtable/ClassTab.tsx | 2 + components/xtable/CustomImagingTab.tsx | 191 ++++++++++++++++--------- components/xtable/XTableBody.tsx | 25 +++- contexts/XTableConfigContext.tsx | 62 ++++++-- contexts/XTableDataContext.tsx | 4 +- 5 files changed, 196 insertions(+), 88 deletions(-) diff --git a/components/xtable/ClassTab.tsx b/components/xtable/ClassTab.tsx index 4623168..a9756e1 100644 --- a/components/xtable/ClassTab.tsx +++ b/components/xtable/ClassTab.tsx @@ -283,6 +283,8 @@ export default function ClassTab() { +
+
diff --git a/components/xtable/CustomImagingTab.tsx b/components/xtable/CustomImagingTab.tsx index a87e32d..1c16b7b 100644 --- a/components/xtable/CustomImagingTab.tsx +++ b/components/xtable/CustomImagingTab.tsx @@ -4,6 +4,111 @@ import Row from 'react-bootstrap/Row' import InputGroup from 'react-bootstrap/InputGroup' import { useContext } from 'react' import { useXTableConfig } from '../../contexts/XTableConfigContext' +import { Button } from 'react-bootstrap' +import { BiPlus } from 'react-icons/bi' +import { HiMinusSm } from 'react-icons/hi' +import Help from '../common/Help' + +const CustomImagingColumnGroup = ({ index }: { index: number }) => { + const { tcState, tcDispatch } = useXTableConfig() + const custom = tcState.customImaging.columns[index] + + return ( + <> + + +
+ + + Base URL + + tcDispatch({ + type: 'updateCustomImaging', + payload: { index, url: e.target.value } + })} + /> + + + The base resource url is the first (static) part of the URL. + This value must starts with http://{" "} + or https://
+ The final url for each row is:
+ Base URL + RI Column + suffix +
+
+ + + +
+ + Suffix + tcDispatch({ + type: 'updateCustomImaging', + payload: { index, fileExtension: e.target.value } + })} + /> + + + The url suffix is the last (static) part of the URL and {" "} + is used to specify the file extension, for example.
+ The final url for each row is:
+ Base URL + RI Column + suffix +
+
+ +
+ + + +
+ + RI Column + tcDispatch({ + type: 'updateCustomImaging', + payload: { index, columnIndex: (parseInt(e.target.value)) } + })}> + + {tcState.table.columns.map((colName, idx) => ( + + ))} + + + + The resource identification column (RI column) is the {" "} + only variable part of the url. This field must specify the {" "} + column to use to make a specific url for each row.
+ The final url for each row is:
+ Base URL + RI Column + suffix +
+
+ + + + + +
+ + ) +} export default function CustomImagingTab() { const { tcState, tcDispatch } = useXTableConfig() @@ -21,85 +126,33 @@ export default function CustomImagingTab() { label="Show Custom Images Column" checked={custom.enabled} onChange={e => tcDispatch({ - type: 'setCustomImaging', + type: 'enableCustomImaging', payload: { enabled: e.target.checked } })} /> - - - - - URL - - tcDispatch({ - type: 'setCustomImaging', - payload: { url: e.target.value } - })} - /> - - - + {custom.columns.map((_, i) => ( + <> + +
+ + ))} - - - Column - tcDispatch({ - type: 'setCustomImaging', - payload: { columnIndex: (parseInt(e.target.value)) } - })}> - - {tcState.table.columns.map((colName, index) => ( - - ))} - - - - - - - - - File Extension - tcDispatch({ - type: 'setCustomImaging', - payload: { fileExtension: e.target.value } - })}> - - - - - - - - - - - - - - - - - + + - ) } \ No newline at end of file diff --git a/components/xtable/XTableBody.tsx b/components/xtable/XTableBody.tsx index 3fd9ee8..848cb95 100644 --- a/components/xtable/XTableBody.tsx +++ b/components/xtable/XTableBody.tsx @@ -52,7 +52,7 @@ const columnsAccessors = { zoomHeight={460} />, header: 'S-PLUS' }), - customImaging: () => columnHelper.accessor('customImaging', { + customImaging: (i: number) => columnHelper.accessor(`customImaging:${i}`, { cell: info => { + const refRow = src[i + 1][col.columnIndex] + row[`customImaging:${colId}`] = `${col.url}${refRow}${col.fileExtension}` + }) } // classification column diff --git a/contexts/XTableConfigContext.tsx b/contexts/XTableConfigContext.tsx index 84e93ff..ccee2b1 100644 --- a/contexts/XTableConfigContext.tsx +++ b/contexts/XTableConfigContext.tsx @@ -81,13 +81,17 @@ interface IStampModal extends IterableInterface { showPetroFluxRadius: boolean, } -interface ICustomImaging extends IterableInterface { - enabled: boolean, +interface ICustomImagingColumn extends IterableInterface { url: string, fileExtension: string, columnIndex: number, } +interface ICustomImaging extends IterableInterface { + enabled: boolean, + columns: ICustomImagingColumn[], +} + export interface IState { schemaVersion: number, table: ITableConfig, @@ -103,7 +107,7 @@ export interface IState { customImaging: ICustomImaging, } -export const SCHEMA_VERSION: number = 6 +export const SCHEMA_VERSION: number = 7 const getInitialState = (): IState => ({ schemaVersion: SCHEMA_VERSION, @@ -172,9 +176,13 @@ const getInitialState = (): IState => ({ }, customImaging: { enabled: false, - url: '', - fileExtension: '', - columnIndex: -1, + columns: [ + { + url: '', + fileExtension: '', + columnIndex: -1, + } + ] } }) const initialState = getInitialState() @@ -294,15 +302,43 @@ const setStampModal = (state: IState, action: IAction) => { return s } -const setCustomImaging = (state: IState, action: IAction) => { +const addCustomImaging = (state: IState, action: IAction<{ prevColumns: ICustomImagingColumn[] }>) => { + const s = { ...state } + s.customImaging.columns = [ + ...action.payload.prevColumns, + { + url: '', + fileExtension: '', + columnIndex: -1 + } + ] + persistStateAsync(s) + return s +} + +const updateCustomImaging = (state: IState, action: IAction) => { const s = { ...state } for (const k in action.payload) { - s.customImaging[k] = action.payload[k] + s.customImaging.columns[action.payload.index][k] = action.payload[k] } persistStateAsync(s) return s } +const removeCustomImaging = (state: IState, action: IAction<{ index: number, prevColumns: ICustomImagingColumn[] }>) => { + const s = { ...state } + s.customImaging.columns = action.payload.prevColumns.filter((_, i) => i != action.payload.index) + persistStateAsync(s) + return s +} + +const enableCustomImaging = (state: IState, action: IAction<{ enabled: boolean }>) => { + const s = { ...state } + s.customImaging.enabled = action.payload.enabled + persistStateAsync(s) + return s +} + type PayloadType = IState | ITrilogyConfig | ISplusImaging | ILuptonConfig | ITableConfig | IClassification | ILegacyImaging | ISdssSpectra | ISdssCatalog | ISplusPhotoSpectra @@ -333,8 +369,14 @@ const reducer = (state: IState, action: IAction) => { return setNearbyRedshifts(state, action) case 'setStampModal': return setStampModal(state, action) - case 'setCustomImaging': - return setCustomImaging(state, action) + case 'addCustomImaging': + return addCustomImaging(state, action) + case 'updateCustomImaging': + return updateCustomImaging(state, action) + case 'removeCustomImaging': + return removeCustomImaging(state, action) + case 'enableCustomImaging': + return enableCustomImaging(state, action) default: console.log(`Action ${action.type} not found`) return { ...state } diff --git a/contexts/XTableDataContext.tsx b/contexts/XTableDataContext.tsx index 4d93e70..3c02119 100644 --- a/contexts/XTableDataContext.tsx +++ b/contexts/XTableDataContext.tsx @@ -23,7 +23,7 @@ export interface ISchema { legacyImaging: { enabled: boolean, pixelScale: number }, splusImaging: boolean, sdssSpectra: boolean, - customImaging: boolean, + customImaging: { enabled: boolean, nCols: number }, splusPhotoSpectra: boolean, nearbyRedshifts: boolean, } @@ -51,7 +51,7 @@ const initialState: IState = { classification: false, legacyImaging: { enabled: false, pixelScale: 0.55 }, splusImaging: false, - customImaging: false, + customImaging: { enabled: false, nCols: 0 }, sdssSpectra: false, splusPhotoSpectra: false, nearbyRedshifts: false,