Skip to content

Commit

Permalink
Feature/swodlr UI 114 - implement endpoint for My Data page filtering (
Browse files Browse the repository at this point in the history
…#116)

* feature/swodlr-ui-114: implemented filtering endpoint for some my data page properties

* feature/swodlr-ui-114: fixed merge marker

* feature/swodlr-ui-114: resolved comments by Josh in PR

---------

Co-authored-by: jbyrne <jimmy.byrne@jpl.nasa.gov>
  • Loading branch information
jbyrne6 and jbyrne committed Jun 21, 2024
1 parent e84f200 commit 7773197
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 82 deletions.
26 changes: 7 additions & 19 deletions src/components/history/DataPagination.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { Col, Pagination, Row, Spinner } from "react-bootstrap";
import { Col, Pagination, Row } from "react-bootstrap";
import { useAppDispatch, useAppSelector } from "../../redux/hooks";
import { setUserProducts } from "../sidebar/actions/productSlice";
import { productsPerPage } from "../../constants/rasterParameterConstants";
import { useState } from "react";


const DataPagination = (props: {totalNumberOfProducts: number, totalNumberOfFilteredProducts: number, }) => {
const {totalNumberOfProducts, totalNumberOfFilteredProducts} = props
const { totalNumberOfFilteredProducts} = props
const dispatch = useAppDispatch()
const userProducts = useAppSelector((state) => state.product.userProducts)
const allUserProducts = useAppSelector((state) => state.product.allUserProducts)
const [noNextPage, setNoNextPage] = useState<boolean>(false)
const [noPreviousPage, setNoPreviousPage] = useState<boolean>(true)
const [waitingForPagination, setWaitingForPagination] = useState<boolean>(false)
const [currentPageNumber, setCurrentPageNumber] = useState<number>(1)
const numberOfTotalPages = Math.ceil(allUserProducts.length / parseInt(productsPerPage))

Expand All @@ -33,16 +32,6 @@ const DataPagination = (props: {totalNumberOfProducts: number, totalNumberOfFilt
}
}

const waitingForPaginationSpinner = () => {
return (
<div>
<Spinner animation="border" role="status">
<span className="visually-hidden">Loading...</span>
</Spinner>
</div>
)
}

const getPaginationItemsWithEllipsis = () => {
let numberOfSlotsFreeLeft = 0
if(currentPageNumber >= numberOfTotalPages-4) {
Expand Down Expand Up @@ -78,12 +67,12 @@ const DataPagination = (props: {totalNumberOfProducts: number, totalNumberOfFilt
}
}

if(pagesAllowed[0] > 2) pagesToShow.unshift(<Pagination.Ellipsis />)
if(pagesAllowed[pagesAllowed.length-1] < numberOfTotalPages-1) pagesToShow.push(<Pagination.Ellipsis />)
if(pagesAllowed[0] > 2) pagesToShow.unshift(<Pagination.Ellipsis key='ellipsis-first' />)
if(pagesAllowed[pagesAllowed.length-1] < numberOfTotalPages-1) pagesToShow.push(<Pagination.Ellipsis key='ellipsis-last'/>)
return pagesToShow
}

return waitingForPagination ? waitingForPaginationSpinner() : (
return (
<Row>
<Col xs={2}></Col>
<Col xs={7}>
Expand All @@ -99,10 +88,9 @@ const DataPagination = (props: {totalNumberOfProducts: number, totalNumberOfFilt
: null
}
</Col>
<Col xs={3} style={{paddingTop: '15px'}}><h6><b>{totalNumberOfProducts}</b> Total Generated Products</h6></Col>
<Col xs={3} style={{paddingTop: '15px'}}><h6><b>{totalNumberOfFilteredProducts}</b> Total Generated Products</h6></Col>
</Row>
)
}

export default DataPagination;

export default DataPagination;
66 changes: 16 additions & 50 deletions src/components/history/GeneratedProductHistory.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,17 @@
import { Alert, Col, OverlayTrigger, Row, Table, Tooltip, Spinner, Form, DropdownButton, Dropdown, Badge } from "react-bootstrap";
import { useAppDispatch, useAppSelector } from "../../redux/hooks";
import { Product, ProductState } from "../../types/graphqlTypes";
import { Product } from "../../types/graphqlTypes";
import { useEffect, useState } from "react";
import { InfoCircle } from "react-bootstrap-icons";
import { generatedProductsLabels, infoIconsToRender, parameterHelp, productsPerPage } from "../../constants/rasterParameterConstants";
import { getUserProducts } from "../../user/userData";
import { useLocation, useNavigate } from "react-router-dom";
import DataPagination from "./DataPagination";
import HistoryFilters from "./HistoryFilters";
import { Adjust, FilterParameters, OutputGranuleExtentFlagOptions, OutputSamplingGridType, RasterResolution } from "../../types/historyPageTypes";
import HistoryFilters, { getFilterParameters, productPassesFilterCheck } from "./HistoryFilters";
import { setShowReGenerateProductModalTrue } from "../sidebar/actions/modalSlice";
import ReGenerateProductsModal from "./ReGenerateProductsModal";
import { setAllUserProducts, setGranulesToReGenerate, setUserProducts, setWaitingForMyDataFiltering, setWaitingForProductsToLoad } from "../sidebar/actions/productSlice";

export const productPassesFilterCheck = (currentFilters: FilterParameters, cycle: number, pass: number, scene: number, outputGranuleExtentFlag: boolean, status: string, outputSamplingGridType: string, rasterResolution: number, dateGenerated: string, utmZoneAdjust?: number, mgrsBandAdjust?: number): boolean => {
let productPassesFilter = true
const outputGranuleExtentFlagMap = ['128 x 128','256 x 128']

if(currentFilters.cycle !== 'none' && currentFilters.cycle !== String(cycle)) {
productPassesFilter = false
}
if (currentFilters.pass !== 'none' && currentFilters.pass !== String(pass)) {
productPassesFilter = false
}
if (currentFilters.scene !== 'none' && currentFilters.scene !== String(scene)) {
productPassesFilter = false
}
if (currentFilters.outputGranuleExtentFlag.length > 0 && !currentFilters.outputGranuleExtentFlag.includes(outputGranuleExtentFlagMap[+outputGranuleExtentFlag] as OutputGranuleExtentFlagOptions)) {
productPassesFilter = false
}
if (currentFilters.status.length > 0 && !currentFilters.status.includes(status as ProductState)) {
productPassesFilter = false
}
if (currentFilters.outputSamplingGridType.length > 0 && !currentFilters.outputSamplingGridType.includes(outputSamplingGridType as OutputSamplingGridType)) {
productPassesFilter = false
}
if (currentFilters.rasterResolution.length > 0 && !currentFilters.rasterResolution.includes(String(rasterResolution) as RasterResolution)) {
productPassesFilter = false
}
if (utmZoneAdjust !== undefined && currentFilters.utmZoneAdjust.length > 0 && !currentFilters.utmZoneAdjust.includes(String(utmZoneAdjust) as Adjust)) {
productPassesFilter = false
}
if (mgrsBandAdjust !== undefined && currentFilters.mgrsBandAdjust.length > 0 && !currentFilters.mgrsBandAdjust.includes(String(mgrsBandAdjust) as Adjust)) {
productPassesFilter = false
}
if(currentFilters.startDate !== 'none' && new Date(dateGenerated) < currentFilters.startDate) {
productPassesFilter = false
}
if(currentFilters.endDate !== 'none' && new Date(dateGenerated) > currentFilters.endDate) {
productPassesFilter = false
}
return productPassesFilter
}
import { setAllUserProducts, setGranulesToReGenerate, setUserProducts, setWaitingForMyDataFiltering, setWaitingForMyDataFilteringReset, setWaitingForProductsToLoad } from "../sidebar/actions/productSlice";
import { defaultUserProductsLimit } from "../../constants/graphqlQueries";

const GeneratedProductHistory = () => {
const dispatch = useAppDispatch()
Expand All @@ -60,43 +20,49 @@ const GeneratedProductHistory = () => {
const currentFilters = useAppSelector((state) => state.product.currentFilters)
const waitingForProductsToLoad = useAppSelector((state) => state.product.waitingForProductsToLoad)
const waitingForMyDataFiltering = useAppSelector((state) => state.product.waitingForMyDataFiltering)
const waitingForMyDataFilteringReset = useAppSelector((state) => state.product.waitingForMyDataFilteringReset)
const { search } = useLocation()
const navigate = useNavigate()
const [totalNumberOfProducts, setTotalNumberOfProducts] = useState<number>(0)
const [totalNumberOfFilteredProducts, setTotalNumberOfFilteredProducts] = useState<number>(0)
const [checkedProducts, setCheckedProducts] = useState<Product[]>([])
const [allChecked, setAllChecked] = useState<boolean>(false)
const [hasAlreadyLoadedInitialProducts, setHasAlreadyLoadedInitialProducts] = useState<boolean>(false)

useEffect(() => {
// get the data for the first page
// go through all the user product data to get the id of each one so that
const fetchData = async () => {
if(!waitingForMyDataFiltering) dispatch(setWaitingForProductsToLoad(true))
await getUserProducts({limit: '1000000'}).then(response => {

const productQueryParameters = getFilterParameters(currentFilters, defaultUserProductsLimit)
// add variables for filters
await getUserProducts(productQueryParameters).then(response => {
dispatch(setWaitingForProductsToLoad(false))
// filter products for what is in the filter
const allProducts = response.products as Product[]
setTotalNumberOfProducts(allProducts.length)
const filteredProducts = allProducts.filter(product => {
const {status, utmZoneAdjust, mgrsBandAdjust, outputGranuleExtentFlag, outputSamplingGridType, rasterResolution, timestamp: dateGenerated, cycle, pass, scene, granules} = product
const {status, utmZoneAdjust, mgrsBandAdjust, rasterResolution} = product
const statusToUse = status[0].state
const outputSamplingGridTypeToUse = outputSamplingGridType === 'GEO' ? 'LAT/LON' : outputSamplingGridType
const productPassesFilter = productPassesFilterCheck(currentFilters, cycle, pass, scene, outputGranuleExtentFlag, statusToUse, outputSamplingGridTypeToUse, rasterResolution, dateGenerated, utmZoneAdjust, mgrsBandAdjust)
const productPassesFilter = productPassesFilterCheck(currentFilters, statusToUse, rasterResolution, utmZoneAdjust, mgrsBandAdjust)
if(productPassesFilter) {
return product
} else {
return null
}
})
setTotalNumberOfFilteredProducts(filteredProducts.length)
setHasAlreadyLoadedInitialProducts(true)
dispatch(setAllUserProducts(filteredProducts))
const productsPerPageToInt = parseInt(productsPerPage)
dispatch(setUserProducts(filteredProducts.slice(0, productsPerPageToInt)))
dispatch(setWaitingForMyDataFiltering(false))
dispatch(setWaitingForMyDataFilteringReset(false))
})
}
fetchData().catch(console.error)
}, [currentFilters]);
}, [dispatch, currentFilters, waitingForMyDataFiltering, waitingForMyDataFilteringReset]);

// reset all checked checkbox when going to next page
useEffect(() => {
Expand Down Expand Up @@ -226,7 +192,7 @@ const GeneratedProductHistory = () => {
</div>
{<DataPagination totalNumberOfProducts={totalNumberOfProducts} totalNumberOfFilteredProducts={totalNumberOfFilteredProducts} />}
{!waitingForProductsToLoad && userProducts.length === 0 ? <Row>{productHistoryAlert()}</Row> : null}
{waitingForProductsToLoad ? waitingForProductsToLoadSpinner() : null}
{waitingForProductsToLoad && !hasAlreadyLoadedInitialProducts ? waitingForProductsToLoadSpinner() : null}
</div>
</Col>
</Row>
Expand Down
Loading

0 comments on commit 7773197

Please sign in to comment.