);
}
diff --git a/src/components/sidebar/GranulesTable.tsx b/src/components/sidebar/GranulesTable.tsx
index b978246..4bb8342 100644
--- a/src/components/sidebar/GranulesTable.tsx
+++ b/src/components/sidebar/GranulesTable.tsx
@@ -5,7 +5,7 @@ import { granuleAlertMessageConstant, granuleSelectionLabels, productCustomizati
footprintSearchCollectionConceptId } from '../../constants/rasterParameterConstants';
import { Button, Col, Form, OverlayTrigger, Row, Tooltip, Spinner } from 'react-bootstrap';
import { InfoCircle, Plus, Trash } from 'react-bootstrap-icons';
-import { AdjustType, AdjustValueDecoder, GranuleForTable, GranuleTableProps, InputType, SaveType, SpatialSearchResult, TableTypes, alertMessageInput, allProductParameters, validScene } from '../../types/constantTypes';
+import { AdjustType, AdjustValueDecoder, GranuleForTable, GranuleTableProps, InputType, SaveType, SpatialSearchResult, TableTypes, alertMessageInput, allProductParameters, handleSaveResult, validScene } from '../../types/constantTypes';
import { addProduct, setSelectedGranules, setGranuleFocus, addGranuleTableAlerts, editProduct, addSpatialSearchResults, setWaitingForFootprintSearch, clearGranuleTableAlerts } from './actions/productSlice';
import { setShowDeleteProductModalTrue } from './actions/modalSlice';
import DeleteGranulesModal from './DeleteGranulesModal';
@@ -33,7 +33,7 @@ const GranuleTable = (props: GranuleTableProps) => {
const {outputSamplingGridType} = generateProductParameters
// search parameters
- const [searchParams, setSearchParams] = useSearchParams();
+ const [searchParams, setSearchParams] = useSearchParams()
// set the default url state parameters
useEffect(() => {
@@ -44,16 +44,6 @@ const GranuleTable = (props: GranuleTableProps) => {
const sceneParamArray = Array.from(new Set(cyclePassSceneParameters.split('-')))
sceneParamArray.forEach((sceneParams, index) => {
const splitSceneParams = sceneParams.split('_')
- if (splitSceneParams.length > 3) {
- // update zone and band adjust values
- const zoneAdjustValue = adjustParamDecoder('value', splitSceneParams[3])
- const bandAdjustValue = adjustParamDecoder('value', splitSceneParams[4])
- const productToEdit = addedProducts.find(granuleObj => granuleObj.cycle === splitSceneParams[0] && granuleObj.pass === splitSceneParams[1] && granuleObj.scene === splitSceneParams[2])
- if (productToEdit?.utmZoneAdjust !== zoneAdjustValue || productToEdit?.mgrsBandAdjust !== bandAdjustValue) {
- const editedProduct = {...productToEdit, utmZoneAdjust: zoneAdjustValue, mgrsBandAdjust: bandAdjustValue}
- dispatch(editProduct(editedProduct as allProductParameters))
- }
- }
handleSave('urlParameter', sceneParamArray.length, index, splitSceneParams[0], splitSceneParams[1], splitSceneParams[2])
})
}
@@ -63,20 +53,25 @@ const GranuleTable = (props: GranuleTableProps) => {
dispatch(clearGranuleTableAlerts())
if (spatialSearchResults.length > 0) {
let scenesFoundArray: string[] = []
+ let addedScenes: string[] = []
const fetchData = async () => {
for(let i=0; i {
-
- scenesFoundArray.push(result)
+ if(result.savedScenes) {
+ addedScenes.push(...(result.savedScenes).map(productObject => productObject.granuleId))
+ }
+ scenesFoundArray.push(result.result)
})
}
+ // add parameters
+ addSearchParamToCurrentUrlState({'cyclePassScene': addedScenes.join('-')})
return scenesFoundArray
}
// call the function
fetchData()
- .then((noScenesFoundResult) => {
- if(scenesFoundArray.includes('noScenesFound') && !scenesFoundArray.includes('found something')){
+ .then((noScenesFoundResults) => {
+ if(noScenesFoundResults.includes('noScenesFound') && !noScenesFoundResults.includes('found something')){
setSaveGranulesAlert('noScenesFound')
}
})
@@ -89,16 +84,50 @@ const GranuleTable = (props: GranuleTableProps) => {
}, [spatialSearchResults])
const addSearchParamToCurrentUrlState = (newPairsObject: object, remove?: string) => {
- const currentSearchParams = Object.fromEntries(searchParams.entries())
- Object.entries(newPairsObject).forEach(pair => {
+ const currentSearchParams = Object.fromEntries(searchParams.entries())
+ const cyclePassSceneParameters = searchParams.get('cyclePassScene')
+ Object.entries(newPairsObject).forEach(pair => {
+ if (pair[0] === 'cyclePassScene') {
+ if(cyclePassSceneParameters !== null) {
+ // check if cps already exists in cyclePassSceneParameters
+ const currentCpsUrlSplit = cyclePassSceneParameters.split('-')
+ const paramsToAddSplit = pair[1].toString().split('-')
+ // let combinedParamsArray = currentCpsUrlSplit
+ let newParamsArray: string[] = []
+ paramsToAddSplit.forEach((newParam: string) => {
+ if(!currentCpsUrlSplit.includes(newParam)) {
+ newParamsArray.push(newParam)
+ // if cps combo not already in url param, add it
+ // NOTE FOR WHEN I GET BACK: making sure no duplicates of cps
+ }
+ })
+ if (newParamsArray.length > 0) {
+ // if cps without adjust params is in currentCpsUrlSplit and newParamsArray has cps with added adjust params
+ const newCPSParams: string[] = []
+ newParamsArray.forEach(newParam => {
+ currentCpsUrlSplit.forEach(oldParam => {
+ const splitOldParam = oldParam.split('_')
+ if(!newParam.includes(`${splitOldParam[0]}_${splitOldParam[1]}_${splitOldParam[2]}`) && !newCPSParams.includes(oldParam)) {
+ // remove old param
+ newCPSParams.push(oldParam)
+ }
+ })
+ })
+ currentSearchParams[pair[0]] = [...newCPSParams, ...newParamsArray].join('-')
+ }
+ } else {
currentSearchParams[pair[0]] = pair[1].toString()
- })
-
- // remove unused search param
- if (remove) {
- delete currentSearchParams[remove]
+ }
+ } else {
+ currentSearchParams[pair[0]] = pair[1].toString()
}
- setSearchParams(currentSearchParams)
+ })
+
+ // remove unused search param
+ if (remove) {
+ delete currentSearchParams[remove]
+ }
+ setSearchParams(currentSearchParams)
}
// add granules
@@ -159,7 +188,6 @@ const validateSceneAvailability = async (cycleToUse: number, passToUse: number,
// check for characters other than integers and one -
if (inputValue.includes('-')) {
const inputBoundsValue = inputValue.split('-')
- // const allInputsValidNumbers = inputBoundsValue.every(inputString => !isNaN(+inputString))
const min: string = inputBoundsValue[0].trim()
const max: string = inputBoundsValue[1].trim()
const minIsValid = checkInBounds(inputType, min)
@@ -270,7 +298,7 @@ const validateSceneAvailability = async (cycleToUse: number, passToUse: number,
return cpsValueToReturn
}
- const handleSave = async (saveType: SaveType, totalRuns: number, index: number, cycleParam?: string, passParam?: string, sceneParam?: string): Promise => {
+ const handleSave = async (saveType: SaveType, totalRuns: number, index: number, cycleParam?: string, passParam?: string, sceneParam?: string): Promise => {
if (saveType === 'manual') dispatch(clearGranuleTableAlerts())
setWaitingForScenesToBeAdded(true)
// String(+(stringParam)) is used to remove the leading zeros
@@ -287,10 +315,10 @@ const validateSceneAvailability = async (cycleToUse: number, passToUse: number,
if (!validCycle) setSaveGranulesAlert('invalidCycle')
if (!validPass) setSaveGranulesAlert('invalidPass')
if (!validScene) setSaveGranulesAlert('invalidScene')
- return 'first step'
+ return {result: 'first step'}
} else if (addedProducts.length >= granuleTableLimit) {
setSaveGranulesAlert('granuleLimit')
- return 'second-step'
+ return {result: 'second-step'}
} else {
const granulesToAdd: allProductParameters[] = []
let someGranulesAlreadyAdded = false
@@ -336,7 +364,7 @@ const validateSceneAvailability = async (cycleToUse: number, passToUse: number,
someGranulesAlreadyAdded = true
}
})
- if (saveType !== 'spatialSearch') {
+ if (saveType !== 'spatialSearch' && saveType !== 'urlParameter') {
// check if any granules could not be found or they were already added
if (someGranulesAlreadyAdded) {
setSaveGranulesAlert('alreadyAdded')
@@ -364,38 +392,44 @@ const validateSceneAvailability = async (cycleToUse: number, passToUse: number,
}))
})).then(async productsWithFootprints => {
// don't run time range check if granule was manually entered
- const productsInTimeRange: allProductParameters[] = []
- const productsNotInTimeRange:allProductParameters[] = []
- productsWithFootprints.forEach(product => {
- if (product.inTimeRange){
- delete product.inTimeRange
- productsInTimeRange.push(product)
- } else if (!product.inTimeRange) {
- delete product.inTimeRange
- productsNotInTimeRange.push(product)
- }
- })
- if (productsInTimeRange.length > 0) {
- setSaveGranulesAlert('success')
- dispatch(addProduct(productsInTimeRange))
+ if (saveType === 'manual' || saveType === 'urlParameter') {
addSearchParamToCurrentUrlState({'cyclePassScene': cyclePassSceneSearchParams})
- }
- if (productsNotInTimeRange.length > 0) {
- // set alerts for not in range
- setSaveGranulesAlert('notInTimeRange')
+ if (saveType !== 'urlParameter') {
+ setSaveGranulesAlert('success')
+ }
+ dispatch(addProduct(productsWithFootprints))
+ } else {
+ const productsInTimeRange: allProductParameters[] = []
+ const productsNotInTimeRange:allProductParameters[] = []
+ productsWithFootprints.forEach(product => {
+ if (product.inTimeRange){
+ delete product.inTimeRange
+ productsInTimeRange.push(product)
+ } else if (!product.inTimeRange) {
+ delete product.inTimeRange
+ productsNotInTimeRange.push(product)
+ }
+ })
+ if (productsInTimeRange.length > 0) {
+ setSaveGranulesAlert('success')
+ dispatch(addProduct(productsInTimeRange))
+ }
+ if (productsNotInTimeRange.length > 0) {
+ // set alerts for not in range
+ setSaveGranulesAlert('notInTimeRange')
+ }
}
})
- return 'found something'
+ return {result: 'found something', savedScenes: granulesToAdd}
} else {
if (index+1 === totalRuns){
- return 'noScenesFound'
+ return {result: 'noScenesFound'}
} else {
- return 'not applicable'
+ return {result: 'not applicable'}
}
}
})
return validationResult
- // return 'third step'
}
}
diff --git a/src/components/sidebar/ProductCustomization.tsx b/src/components/sidebar/ProductCustomization.tsx
index 363e7eb..9b7ad43 100644
--- a/src/components/sidebar/ProductCustomization.tsx
+++ b/src/components/sidebar/ProductCustomization.tsx
@@ -81,7 +81,6 @@ const ProductCustomization = () => {
if (showUTMAdvancedOptions) {
handleShowUTMAdvancedOptions()
}
-
} else {
gridType = "rasterResolutionUTM"
searchParamToRemove = "rasterResolutionGEO"
@@ -113,13 +112,13 @@ const ProductCustomization = () => {
if (outputSamplingGridType === 'utm') {
return (
setRasterResolutionUTM(parseInt(event.target.value))}>
- {parameterOptionValues.rasterResolutionUTM.values.map(parameterValue => )}
+ {parameterOptionValues.rasterResolutionUTM.values.map((parameterValue, index) => )}
)
} else if (outputSamplingGridType === 'lat/lon') {
return (
setRasterResolutionGEO(parseInt(event.target.value))}>
- {parameterOptionValues.rasterResolutionGEO.values.map(parameterValue => )}
+ {parameterOptionValues.rasterResolutionGEO.values.map((parameterValue, index) => )}
)
}
@@ -162,6 +161,7 @@ const ProductCustomization = () => {
type={'radio'}
id={`outputSamplingGridTypeGroup-radio-${index}`}
onChange={() => setOutputSamplingGridType(value as string, resolutionToUse)}
+ key={`outputSamplingGridTypeGroup-radio-key-${index}`}
/>
)}
)
@@ -176,6 +176,7 @@ const ProductCustomization = () => {
label={'advanced options'}
style={{marginTop: '10px'}}
disabled={!(outputSamplingGridType === 'utm')}
+ key={`outputGranuleExtentFlag-switch-key`}
/>
)
)
@@ -206,6 +207,7 @@ const ProductCustomization = () => {
type={'radio'}
id={`outputGranuleExtentFlagTypeGroup-radio-${index}`}
onChange={() => setOutputGranuleExtentFlag(value)}
+ key={`outputGranuleExtentFlagTypeGroup-radio-key-${index}`}
/>
)
})}
diff --git a/src/components/sidebar/actions/modalSlice.ts b/src/components/sidebar/actions/modalSlice.ts
index 0587281..ae3a743 100644
--- a/src/components/sidebar/actions/modalSlice.ts
+++ b/src/components/sidebar/actions/modalSlice.ts
@@ -1,5 +1,4 @@
import { createSlice } from '@reduxjs/toolkit'
-import { allProductParameters } from '../../../types/constantTypes'
// Define a type for the slice state
interface AddCustomProductModalState {
@@ -7,7 +6,6 @@ interface AddCustomProductModalState {
showEditProductModal: boolean,
showDeleteProductModal: boolean,
showGenerateProductModal: boolean,
- addedProducts: allProductParameters[],
sampleGranuleDataArray: number[],
selectedGranules: string[],
showTutorialModal: boolean,
@@ -20,11 +18,10 @@ const initialState: AddCustomProductModalState = {
showEditProductModal: false,
showDeleteProductModal: false,
showGenerateProductModal: false,
- showTutorialModal: true,
+ showTutorialModal: false,
skipTutorial: true,
// allProducts: this will be like a 'database' for the local state of all the products added
// the key will be cycleId_passId_sceneId and the value will be a 'parameterOptionDefaults' type object
- addedProducts: [],
sampleGranuleDataArray: [],
selectedGranules: []
}
diff --git a/src/components/sidebar/actions/productSlice.ts b/src/components/sidebar/actions/productSlice.ts
index 7682a9d..a98c05e 100644
--- a/src/components/sidebar/actions/productSlice.ts
+++ b/src/components/sidebar/actions/productSlice.ts
@@ -45,7 +45,7 @@ const initialState: GranuleState = {
spatialSearchResults: [],
waitingForSpatialSearch: false,
waitingForFootprintSearch: false,
- spatialSearchStartDate: (new Date(date.setMonth(date.getMonth() - 1))).toISOString(),
+ spatialSearchStartDate: (new Date(2022, 11, 16)).toISOString(),
spatialSearchEndDate: (new Date()).toISOString()
}
diff --git a/src/components/sidebar/actions/sidebarSlice.ts b/src/components/sidebar/actions/sidebarSlice.ts
index 3c70317..0a1cd5c 100644
--- a/src/components/sidebar/actions/sidebarSlice.ts
+++ b/src/components/sidebar/actions/sidebarSlice.ts
@@ -77,7 +77,4 @@ export const {
setSidebarWidth
} = sidebarSlice.actions
-// Other code such as selectors can use the imported `RootState` type
-// export const selectShowAddProductModal = (state: RootState) => state.addCustomProductModal.showAddProductModal
-
export default sidebarSlice.reducer
\ No newline at end of file
diff --git a/src/components/tutorial/tutorialConstants.ts b/src/components/tutorial/tutorialConstants.ts
index 215d207..41c93e5 100644
--- a/src/components/tutorial/tutorialConstants.ts
+++ b/src/components/tutorial/tutorialConstants.ts
@@ -34,7 +34,6 @@ export const tutorialSteps = [
}
},
{
- // target: "#spatial-search-map",
target: '#map-tutorial-target',
content: "This map allows you to search for scenes by drawing a search area and will display the footprints of scenes once they have been added to your Added Scenes list.",
disableBeacon: true,
@@ -43,7 +42,6 @@ export const tutorialSteps = [
options: {
zIndex: 1000,
primaryColor: '#0d6efd',
- // offset: 40,
}
}
},
@@ -116,17 +114,6 @@ export const tutorialSteps = [
}
}
},
- {
- target: "#configure-products-button",
- content: "Click the Configure Products button to proceed to the Configure Options page where you can select options for how your selected scenes can be made into custom products.",
- disableBeacon: true,
- styles: {
- options: {
- zIndex: 1000,
- primaryColor: '#0d6efd',
- }
- }
- },
{
target: "#configure-options-breadcrumb",
content: "You can also click on the Configure Options tab to proceed to the Configure Options view.",
diff --git a/src/components/welcome/Welcome.tsx b/src/components/welcome/Welcome.tsx
index c681a0b..75eefc5 100644
--- a/src/components/welcome/Welcome.tsx
+++ b/src/components/welcome/Welcome.tsx
@@ -73,8 +73,8 @@ const Welcome = () => {
4.
-
Download
-
Download generated products once processing is complete.
+
Download
+
Download generated products once processing is complete.
diff --git a/src/constants/graphqlQueries.ts b/src/constants/graphqlQueries.ts
index 6fe47d6..e1c1151 100644
--- a/src/constants/graphqlQueries.ts
+++ b/src/constants/graphqlQueries.ts
@@ -1,3 +1,5 @@
+import { userProductQueryLimit } from "./rasterParameterConstants"
+
export const userQuery = `
{
currentUser {
@@ -27,7 +29,7 @@ export const generateL2RasterProductQuery = `
export const userProductsQuery = `
{
currentUser {
- products {
+ products (limit: ${userProductQueryLimit}) {
id
timestamp
cycle
diff --git a/src/constants/rasterParameterConstants.ts b/src/constants/rasterParameterConstants.ts
index a171c46..fad2e10 100644
--- a/src/constants/rasterParameterConstants.ts
+++ b/src/constants/rasterParameterConstants.ts
@@ -96,7 +96,6 @@ export const parameterOptionDefaults = {
}
export const parameterHelp: ParameterHelp = {
- // outputGranuleExtentFlag: `There are two sizing options for raster granules: square (128 km x 128 km) or rectangular (256 km x 128 km). The square granule extent utilizes the data from only the specific square scene ID indicated, whereas the rectangular granule extent utilizes the specific square scene ID indicated and data from the two adjacent scene IDs along the SWOT swath. At the very edges of scenes, there is a risk that the pixels SWOT measures will not be aggregated as accurately into the raster product. The rectangular extent addresses this issue and could be most helpful with points of interest near the edges of scenes.`,
outputGranuleExtentFlag: `There are two sizing options for raster granules: nonoverlapping square (128 km x 128 km) or overlapping rectangular (256 km x 128 km). The rectangular granule extent is 64 km longer in along-track on both sides of the granule and can be useful for observing areas of interest near the along-track edges of the nonoverlapping granules without the need to stitch sequential granules together.`,
outputSamplingGridType: `Specifies the type of the raster sampling grid. It can be either a Universal Transverse Mercator (UTM) grid or a geodetic latitude-longitude grid.`,
rasterResolution: `Resolution of the raster sampling grid in units of integer meters for UTM grids and integer arc-seconds for latitude-longitude grids.`,
@@ -219,15 +218,10 @@ export const granuleAlertMessageConstant: granuleAlertMessageConstantType = {
]
export const spatialSearchResultLimit = 2000
-// export const beforeCPS = '_PIXC_'
-// export const afterCPSR = 'R_'
-// export const afterCPSL = 'L_'
-// export const spatialSearchCollectionConceptId = 'C2799438266-POCLOUD'
-// export const spatialSearchCollectionConceptId = 'C2799438271-POCLOUD'
-
export const beforeCPS = '_x_x_x_'
export const afterCPSR = 'F_'
export const afterCPSL = 'F_'
export const spatialSearchCollectionConceptId = 'C2799438271-POCLOUD'
-// export const footprintSearchCollectionConceptId = 'C2799438266-POCLOUD'
-export const footprintSearchCollectionConceptId = 'C2799438271-POCLOUD'
\ No newline at end of file
+export const footprintSearchCollectionConceptId = 'C2799438271-POCLOUD'
+
+export const userProductQueryLimit = 1000
\ No newline at end of file
diff --git a/src/redux/store.ts b/src/redux/store.ts
index 84eda7e..66b8e76 100644
--- a/src/redux/store.ts
+++ b/src/redux/store.ts
@@ -4,7 +4,6 @@ import productSlice from '../components/sidebar/actions/productSlice'
import navbarSlice from '../components/navbar/navbarSlice'
import appSlice from '../components/app/appSlice'
import sidebarSlice from '../components/sidebar/actions/sidebarSlice'
-// ...
export const store = configureStore({
reducer: {
diff --git a/src/types/constantTypes.ts b/src/types/constantTypes.ts
index 66de6a3..b61f34a 100644
--- a/src/types/constantTypes.ts
+++ b/src/types/constantTypes.ts
@@ -100,7 +100,6 @@ export interface AlertMessageObject {
type: string,
message: string,
variant: "danger" | "success" | "warning",
- // timeoutId: ReturnType,
tableType: TableTypes
}
@@ -152,4 +151,9 @@ export interface MapFocusObject {
zoom: number
}
-export type SaveType = 'manual' | 'urlParameter' | 'spatialSearch'
\ No newline at end of file
+export type SaveType = 'manual' | 'urlParameter' | 'spatialSearch'
+
+export interface handleSaveResult {
+ result: string,
+ savedScenes?: allProductParameters[]
+}
\ No newline at end of file
diff --git a/src/user/userData.ts b/src/user/userData.ts
index f3b5558..c75aa95 100644
--- a/src/user/userData.ts
+++ b/src/user/userData.ts
@@ -78,21 +78,6 @@ export const generateL2RasterProduct = async (
) => {
try {
// TODO: why doesn't typescript like when I don't specifiy 2 different objects for variables utm and geo???
- // const variablesToUse: ProductGenerationVariables = {
- // cycle: parseInt(cycle),
- // pass: parseInt(pass),
- // scene: parseInt(scene),
- // outputGranuleExtentFlag: Boolean(outputGranuleExtentFlag),
- // outputSamplingGridType: 'GEO',
- // rasterResolution,
- // }
-
- // // if outputSamplingGridType is lat/lon (UTM)
- // if (outputSamplingGridType === 'lat/lon') {
- // variablesToUse.utmZoneAdjust = parseInt(utmZoneAdjust)
- // variablesToUse.mgrsBandAdjust = parseInt(mgrsBandAdjust)
- // variablesToUse.outputSamplingGridType = outputSamplingGridType.toUpperCase()
- // }
const utmVariables = {
cycle: parseInt(cycle),
@@ -129,14 +114,6 @@ export const getUserProducts = async () => {
try {
const userProductResponse = await graphQLClient.request(userProductsQuery).then(result => {
const userProductsResult = (result as UserResponse).currentUser.products
- // const userProductsGeneratedForm = userProductResponse.result.map(productResult => {
- // const {cycle, pass, scene, rasterResolution, outputGranuleExtentFlag, outputSamplingGridType, utmZoneAdjust, timestamp, id: productId, status} = productResult
- // // const generatedFormToReuturn: GeneratedProduct =
- // // return generatedFormToReuturn
- // })
-
- // turn into GeneratedProduct
- // const generatedProduct: GeneratedProduct = {}
return {status: 'success', products: userProductsResult} as getUserProductsResponse
})
return userProductResponse