From 98c25b9484340facc52b0696c1db32a9b91a00b7 Mon Sep 17 00:00:00 2001 From: sambokar Date: Thu, 12 Sep 2024 16:06:32 -0400 Subject: [PATCH] Stabilization is almost completed. Testing has been completed for all supporting grids except for species, roles, and quadratpersonnel, none of which are immediately vital. --- .../fixeddatainput/alltaxonomies/page.tsx | 4 +- .../(hub)/fixeddatainput/attributes/page.tsx | 4 +- .../(hub)/fixeddatainput/personnel/page.tsx | 4 +- .../fixeddatainput/quadratpersonnel/page.tsx | 4 +- .../(hub)/fixeddatainput/quadrats/page.tsx | 4 +- .../fixeddatainput/stemtaxonomies/page.tsx | 4 +- frontend/app/(hub)/layout.tsx | 6 +- .../components/client/datagridcolumns.tsx | 12 +- .../isolatedalltaxonomiesdatagrid.tsx | 322 ++++++ .../isolated/isolatedattributesdatagrid.tsx | 76 ++ .../isolated/isolatedpersonneldatagrid.tsx | 167 +++ .../isolatedquadratpersonneldatagrid.tsx | 127 ++ .../isolated/isolatedquadratsdatagrid.tsx | 107 ++ .../isolated/isolatedrolesdatagrid.tsx | 60 + .../isolatedstemtaxonomiesviewdatagrid.tsx | 95 ++ .../applications/quadratsdatagrid.tsx | 6 +- .../datagrids/isolateddatagridcommons.tsx | 901 ++++++++++++++ .../components/datagrids/reentrydatamodal.tsx | 290 +++-- .../processors/processorhelperfunctions.tsx | 45 +- frontend/components/sidebar.tsx | 72 +- frontend/components/themeregistry/theme.ts | 2 + .../themeregistry/themeregistry.tsx | 19 +- frontend/config/datagridhelpers.ts | 30 +- frontend/config/macros.ts | 7 +- frontend/config/sqlrdsdefinitions/views.ts | 1 + frontend/config/sqlrdsdefinitions/zones.ts | 16 +- frontend/config/utils.ts | 23 + frontend/next-env.d.ts | 2 +- frontend/package-lock.json | 1030 +++++++++-------- frontend/package.json | 34 +- 30 files changed, 2764 insertions(+), 710 deletions(-) diff --git a/frontend/app/(hub)/fixeddatainput/alltaxonomies/page.tsx b/frontend/app/(hub)/fixeddatainput/alltaxonomies/page.tsx index f3655f3f..f035cbdb 100644 --- a/frontend/app/(hub)/fixeddatainput/alltaxonomies/page.tsx +++ b/frontend/app/(hub)/fixeddatainput/alltaxonomies/page.tsx @@ -1,5 +1,5 @@ -import AllTaxonomiesViewDataGrid from '@/components/datagrids/applications/alltaxonomiesviewdatagrid'; +import IsolatedAllTaxonomiesViewDataGrid from '@/components/datagrids/applications/isolated/isolatedalltaxonomiesdatagrid'; export default function AllTaxonomiesPage() { - return ; + return ; } diff --git a/frontend/app/(hub)/fixeddatainput/attributes/page.tsx b/frontend/app/(hub)/fixeddatainput/attributes/page.tsx index e4987af1..1caea421 100644 --- a/frontend/app/(hub)/fixeddatainput/attributes/page.tsx +++ b/frontend/app/(hub)/fixeddatainput/attributes/page.tsx @@ -1,5 +1,5 @@ -import AttributesDataGrid from '@/components/datagrids/applications/attributesdatagrid'; +import IsolatedAttributesDataGrid from '@/components/datagrids/applications/isolated/isolatedattributesdatagrid'; export default function AttributesPage() { - return ; + return ; } diff --git a/frontend/app/(hub)/fixeddatainput/personnel/page.tsx b/frontend/app/(hub)/fixeddatainput/personnel/page.tsx index e1e66012..aea5f87d 100644 --- a/frontend/app/(hub)/fixeddatainput/personnel/page.tsx +++ b/frontend/app/(hub)/fixeddatainput/personnel/page.tsx @@ -1,5 +1,5 @@ -import PersonnelDataGrid from '@/components/datagrids/applications/personneldatagrid'; +import IsolatedPersonnelDataGrid from '@/components/datagrids/applications/isolated/isolatedpersonneldatagrid'; export default function PersonnelPage() { - return ; + return ; } diff --git a/frontend/app/(hub)/fixeddatainput/quadratpersonnel/page.tsx b/frontend/app/(hub)/fixeddatainput/quadratpersonnel/page.tsx index 258c96e7..b60bb63c 100644 --- a/frontend/app/(hub)/fixeddatainput/quadratpersonnel/page.tsx +++ b/frontend/app/(hub)/fixeddatainput/quadratpersonnel/page.tsx @@ -1,5 +1,5 @@ -import QuadratPersonnelDataGrid from '@/components/datagrids/applications/quadratpersonneldatagrid'; +import IsolatedQuadratPersonnelDataGrid from '@/components/datagrids/applications/isolated/isolatedquadratpersonneldatagrid'; export default function QuadratPersonnelPage() { - return ; + return ; } diff --git a/frontend/app/(hub)/fixeddatainput/quadrats/page.tsx b/frontend/app/(hub)/fixeddatainput/quadrats/page.tsx index 7af8a2f4..f0aaa5c8 100644 --- a/frontend/app/(hub)/fixeddatainput/quadrats/page.tsx +++ b/frontend/app/(hub)/fixeddatainput/quadrats/page.tsx @@ -1,5 +1,5 @@ -import QuadratsDataGrid from '@/components/datagrids/applications/quadratsdatagrid'; +import IsolatedQuadratsDataGrid from '@/components/datagrids/applications/isolated/isolatedquadratsdatagrid'; export default function QuadratsPage() { - return ; + return ; } diff --git a/frontend/app/(hub)/fixeddatainput/stemtaxonomies/page.tsx b/frontend/app/(hub)/fixeddatainput/stemtaxonomies/page.tsx index b583ff35..74cd3733 100644 --- a/frontend/app/(hub)/fixeddatainput/stemtaxonomies/page.tsx +++ b/frontend/app/(hub)/fixeddatainput/stemtaxonomies/page.tsx @@ -1,7 +1,7 @@ 'use client'; -import StemTaxonomiesViewDataGrid from '@/components/datagrids/applications/stemtaxonomiesviewdatagrid'; +import IsolatedStemTaxonomiesViewDataGrid from '@/components/datagrids/applications/isolated/isolatedstemtaxonomiesviewdatagrid'; export default function StemTaxonomiesPage() { - return ; + return ; } diff --git a/frontend/app/(hub)/layout.tsx b/frontend/app/(hub)/layout.tsx index 91e9b0ad..e67abde5 100644 --- a/frontend/app/(hub)/layout.tsx +++ b/frontend/app/(hub)/layout.tsx @@ -79,7 +79,6 @@ export default function HubLayout({ children }: { children: React.ReactNode }) { const fetchSiteList = useCallback(async () => { const now = Date.now(); if (lastExecutedRef.current && now - lastExecutedRef.current < debounceDelay + 200) { - console.log('Debounced fetchSiteList: Too soon since last call.'); return; } @@ -88,7 +87,7 @@ export default function HubLayout({ children }: { children: React.ReactNode }) { try { setLoading(true, 'Loading Sites...'); - if (session && !siteListLoaded) { + if (session && !siteListLoaded && !currentSite) { const sites = session?.user?.allsites ?? []; if (sites.length === 0) { throw new Error('Session sites undefined'); @@ -107,7 +106,6 @@ export default function HubLayout({ children }: { children: React.ReactNode }) { const loadPlotData = useCallback(async () => { const now = Date.now(); if (plotLastExecutedRef.current && now - plotLastExecutedRef.current < debounceDelay) { - console.log('Debounced loadPlotData: Too soon since last call.'); return; } plotLastExecutedRef.current = now; @@ -132,7 +130,6 @@ export default function HubLayout({ children }: { children: React.ReactNode }) { const loadCensusData = useCallback(async () => { const now = Date.now(); if (censusLastExecutedRef.current && now - censusLastExecutedRef.current < debounceDelay) { - console.log('Debounced loadCensusData: Too soon since last call.'); return; } censusLastExecutedRef.current = now; @@ -158,7 +155,6 @@ export default function HubLayout({ children }: { children: React.ReactNode }) { const loadQuadratData = useCallback(async () => { const now = Date.now(); if (quadratLastExecutedRef.current && now - quadratLastExecutedRef.current < debounceDelay) { - console.log('Debounced loadQuadratData: Too soon since last call.'); return; } quadratLastExecutedRef.current = now; diff --git a/frontend/components/client/datagridcolumns.tsx b/frontend/components/client/datagridcolumns.tsx index cd523e82..17d90d8f 100644 --- a/frontend/components/client/datagridcolumns.tsx +++ b/frontend/components/client/datagridcolumns.tsx @@ -79,7 +79,7 @@ export const quadratGridColumns: GridColDef[] = [ headerName: 'Coordinate Units', headerClassName: 'header', flex: 1, - renderHeader: () => formatHeader('Coordinate', 'Units'), + // renderHeader: () => formatHeader('Coordinate', 'Units'), align: 'right', headerAlign: 'right', editable: true, @@ -104,7 +104,7 @@ export const quadratGridColumns: GridColDef[] = [ headerName: 'Area Unit', headerClassName: 'header', flex: 1, - renderHeader: () => formatHeader('Area', 'Unit'), + // renderHeader: () => formatHeader('Area', 'Unit'), align: 'right', headerAlign: 'right', editable: true, @@ -120,7 +120,9 @@ export const quadratGridColumns: GridColDef[] = [ align: 'right', type: 'number', valueFormatter: (value: any) => { - return Number(value).toFixed(2); + let parsedValue = Number(value); + if (isNaN(value)) parsedValue = 0.0; + return parsedValue.toFixed(2); }, editable: true }, @@ -134,7 +136,9 @@ export const quadratGridColumns: GridColDef[] = [ headerAlign: 'right', type: 'number', valueFormatter: (value: any) => { - return Number(value).toFixed(2); + let parsedValue = Number(value); + if (isNaN(value)) parsedValue = 0.0; + return parsedValue.toFixed(2); }, editable: true }, diff --git a/frontend/components/datagrids/applications/isolated/isolatedalltaxonomiesdatagrid.tsx b/frontend/components/datagrids/applications/isolated/isolatedalltaxonomiesdatagrid.tsx index e69de29b..497b9014 100644 --- a/frontend/components/datagrids/applications/isolated/isolatedalltaxonomiesdatagrid.tsx +++ b/frontend/components/datagrids/applications/isolated/isolatedalltaxonomiesdatagrid.tsx @@ -0,0 +1,322 @@ +// alltaxonomiesview datagrid +'use client'; +import { GridColDef, GridRenderEditCellParams } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +import { Box, Button, DialogContent, DialogTitle, Modal, ModalClose, ModalDialog, Typography } from '@mui/joy'; +import { useSession } from 'next-auth/react'; +import UploadParentModal from '@/components/uploadsystemhelpers/uploadparentmodal'; +import { FormType } from '@/config/macros/formdetails'; +import { AllTaxonomiesViewRDS } from '@/config/sqlrdsdefinitions/views'; +import { formatHeader } from '@/components/client/datagridcolumns'; +import { SpeciesLimitsRDS, SpeciesRDS } from '@/config/sqlrdsdefinitions/taxonomies'; +import { useSiteContext } from '@/app/contexts/userselectionprovider'; +import SpeciesLimitsDataGrid from '@/components/datagrids/applications/specieslimitsdatagrid'; +import IsolatedDataGridCommons from '@/components/datagrids/isolateddatagridcommons'; + +export default function IsolatedAllTaxonomiesViewDataGrid() { + const initialAllTaxonomiesViewRDSRow: AllTaxonomiesViewRDS = { + id: 0, + familyID: 0, + genusID: 0, + speciesID: 0, + family: '', + genus: '', + genusAuthority: '', + speciesCode: '', + speciesName: '', + subspeciesName: '', + speciesIDLevel: '', + speciesAuthority: '', + subspeciesAuthority: '', + fieldFamily: '', + speciesDescription: '' + }; + const [refresh, setRefresh] = useState(false); + const [isUploadModalOpen, setIsUploadModalOpen] = useState(false); + const { data: session } = useSession(); + const [isSpeciesLimitsDialogOpen, setIsSpeciesLimitsDialogOpen] = useState(false); + const [selectedSpeciesRow, setSelectedSpeciesRow] = useState(null); + const [selectedSpeciesLimits, setSelectedSpeciesLimits] = useState([]); + const currentSite = useSiteContext(); + + useEffect(() => { + async function fetchLimits() { + if (selectedSpeciesRow && currentSite?.schemaName) { + const response = await fetch(`/api/specieslimits/${selectedSpeciesRow.speciesID}?schema=${currentSite.schemaName}`, { method: 'GET' }); + setSelectedSpeciesLimits(await response.json()); + } + } + + fetchLimits().catch(console.error); + }, [selectedSpeciesRow]); + + const handleOpenSpeciesLimitsModal = (speciesRow: SpeciesRDS) => { + setSelectedSpeciesRow(speciesRow); + setIsSpeciesLimitsDialogOpen(true); + }; + + const handleCloseSpeciesLimitsModal = () => { + setIsSpeciesLimitsDialogOpen(false); + setSelectedSpeciesRow(null); + }; + + const renderSpeciesLimitsCell = (params: GridRenderEditCellParams) => { + const lowerBound = params.row.lowerBound !== undefined ? Number(params.row.lowerBound).toFixed(2) : 'Lower'; + const upperBound = params.row.upperBound !== undefined ? Number(params.row.upperBound).toFixed(2) : 'Upper'; + const unit = params.row.unit || ''; + + return ( + + + + ); + }; + + const AllTaxonomiesViewGridColumns: GridColDef[] = [ + { + field: 'id', + headerName: '#', + headerClassName: 'header', + flex: 0.3, + align: 'right', + headerAlign: 'right', + editable: false + }, + { + field: 'speciesID', + headerName: '#', + headerClassName: 'header', + flex: 0.5, + align: 'center', + headerAlign: 'center', + type: 'number', + editable: false + }, + { + field: 'speciesCode', + headerName: 'Species Code', + renderHeader: () => formatHeader('Species', 'Code'), + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'familyID', + headerName: 'Family ID', + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'number', + editable: false + }, + { + field: 'family', + headerName: 'Family', + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'genusID', + headerName: 'Genus ID', + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'number', + editable: false + }, + { + field: 'genus', + headerName: 'Genus', + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'genusAuthority', + headerName: 'Genus Auth', + renderHeader: () => formatHeader('Genus', 'Authority'), + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'speciesName', + headerName: 'Species', + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'subspeciesName', + headerName: 'Subspecies', + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'speciesIDLevel', + headerName: 'Species ID Level', + renderHeader: () => formatHeader('Species', 'ID Level'), + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'speciesAuthority', + headerName: 'Species Auth', + renderHeader: () => formatHeader('Species', 'Authority'), + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'subspeciesAuthority', + headerName: 'Subspecies Auth', + renderHeader: () => formatHeader('Subspecies', 'Authority'), + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'fieldFamily', + headerName: 'Field Family', + renderHeader: () => formatHeader('Field', 'Family'), + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'speciesDescription', + headerName: 'Species Description', + renderHeader: () => formatHeader('Species', 'Description'), + headerClassName: 'header', + flex: 1, + align: 'center', + headerAlign: 'center', + type: 'string', + editable: true + }, + { + field: 'speciesLimits', + headerName: 'Species Limits', + flex: 1, + align: 'center', + renderCell: renderSpeciesLimitsCell, + editable: false, + sortable: false, + filterable: false + } + ]; + + return ( + <> + + + + {session?.user.userStatus !== 'field crew' && ( + + Note: ADMINISTRATOR VIEW + + )} + + + {/* Upload Button */} + + + + + { + setIsUploadModalOpen(false); + setRefresh(true); + }} + formType={FormType.species} + /> + + + + {}} sx={{ display: 'flex', flex: 1, alignItems: 'center', justifyContent: 'center' }}> + + + Species Limits Test + + {selectedSpeciesRow && selectedSpeciesRow.speciesID && } + + + + + ); +} diff --git a/frontend/components/datagrids/applications/isolated/isolatedattributesdatagrid.tsx b/frontend/components/datagrids/applications/isolated/isolatedattributesdatagrid.tsx index e69de29b..3f0fbb43 100644 --- a/frontend/components/datagrids/applications/isolated/isolatedattributesdatagrid.tsx +++ b/frontend/components/datagrids/applications/isolated/isolatedattributesdatagrid.tsx @@ -0,0 +1,76 @@ +'use client'; + +// isolated attributes datagrid +import React, { useState } from 'react'; +import { Box, Button, Typography } from '@mui/joy'; +import { useSession } from 'next-auth/react'; +import UploadParentModal from '@/components/uploadsystemhelpers/uploadparentmodal'; +import { AttributeGridColumns } from '@/components/client/datagridcolumns'; +import { FormType } from '@/config/macros/formdetails'; +import IsolatedDataGridCommons from '@/components/datagrids/isolateddatagridcommons'; + +export default function IsolatedAttributesDataGrid() { + const initialAttributesRDSRow = { + id: 0, + code: '', + description: '', + status: '' + }; + const [refresh, setRefresh] = useState(false); + const [isUploadModalOpen, setIsUploadModalOpen] = useState(false); + const { data: session } = useSession(); + + return ( + <> + + + + {session?.user.userStatus !== 'field crew' && ( + + Note: ADMINISTRATOR VIEW + + )} + + + {/* Upload Button */} + + + + + { + setIsUploadModalOpen(false); + setRefresh(true); + }} + formType={FormType.attributes} + /> + + + + ); +} diff --git a/frontend/components/datagrids/applications/isolated/isolatedpersonneldatagrid.tsx b/frontend/components/datagrids/applications/isolated/isolatedpersonneldatagrid.tsx index e69de29b..6033b461 100644 --- a/frontend/components/datagrids/applications/isolated/isolatedpersonneldatagrid.tsx +++ b/frontend/components/datagrids/applications/isolated/isolatedpersonneldatagrid.tsx @@ -0,0 +1,167 @@ +// personnel datagrid +'use client'; +import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; +import React, { useEffect, useState } from 'react'; +import { useSession } from 'next-auth/react'; +import { Box, Button, Chip, IconButton, Modal, ModalDialog, Stack, Typography } from '@mui/joy'; +import UploadParentModal from '@/components/uploadsystemhelpers/uploadparentmodal'; +import Link from 'next/link'; +import { FormType } from '@/config/macros/formdetails'; +import { PersonnelGridColumns } from '@/components/client/datagridcolumns'; +import { useOrgCensusContext, useSiteContext } from '@/app/contexts/userselectionprovider'; +import CloseIcon from '@mui/icons-material/Close'; +import { PersonnelRDS, RoleRDS } from '@/config/sqlrdsdefinitions/personnel'; +import IsolatedDataGridCommons from '@/components/datagrids/isolateddatagridcommons'; +import IsolatedRolesDataGrid from '@/components/datagrids/applications/isolated/isolatedrolesdatagrid'; + +export default function IsolatedPersonnelDataGrid() { + const currentSite = useSiteContext(); + const currentCensus = useOrgCensusContext(); + const initialPersonnelRDSRow: PersonnelRDS = { + id: 0, + personnelID: 0, + censusID: currentCensus?.dateRanges[0]?.censusID, + firstName: '', + lastName: '', + roleID: 0 + }; + const [refresh, setRefresh] = useState(false); + const [isUploadModalOpen, setIsUploadModalOpen] = useState(false); + const [isRolesModalOpen, setIsRolesModalOpen] = useState(false); + const [roles, setRoles] = useState([]); + const { data: session } = useSession(); + + useEffect(() => { + async function fetchRoles() { + const response = await fetch(`/api/fetchall/roles?schema=${currentSite?.schemaName}`); + setRoles(await response.json()); + } + + fetchRoles().catch(console.error); + }, [refresh]); + + const roleIDColumn: GridColDef = { + field: 'roleID', + headerName: 'Role', + headerClassName: 'header', + headerAlign: 'left', + type: 'singleSelect', + flex: 1, + align: 'center', + editable: true, + valueOptions: roles.map(role => ({ + value: role.roleID, + label: `${role.roleName}` + })), + renderCell: (params: GridRenderCellParams) => ( + + + {roles.find(role => role.roleID === params.value)?.roleName} + + + ) + }; + + return ( + <> + + + + {session?.user.userStatus !== 'field crew' && ( + + Note: ADMINISTRATOR VIEW + + )} + + Note: This is a locked view and will not allow modification. + + + Please use this view as a way to confirm changes made to measurements. + + + + {/* Upload Button */} + + + {/* Link to Quadrat Personnel Data Grid */} + + + + + + + + + { + setIsUploadModalOpen(false); + setRefresh(true); + }} + formType={FormType.personnel} + /> + setIsRolesModalOpen(false)} + aria-labelledby="roles-dialog-modal" + sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }} + > + + setIsRolesModalOpen(false)} sx={{ position: 'absolute', top: 8, right: 8 }}> + + + + { + // This triggers the personnel grid to refresh + setRefresh(true); + }} + /> + + + + ({ + value: role.roleID ?? 0, + label: `${role.roleName}` + }))} + initialRow={initialPersonnelRDSRow} + fieldToFocus={'firstName'} + clusters={{ + Name: ['firstName', 'lastName'], + Role: ['roleID'] + }} + /> + + ); +} diff --git a/frontend/components/datagrids/applications/isolated/isolatedquadratpersonneldatagrid.tsx b/frontend/components/datagrids/applications/isolated/isolatedquadratpersonneldatagrid.tsx index e69de29b..e821002b 100644 --- a/frontend/components/datagrids/applications/isolated/isolatedquadratpersonneldatagrid.tsx +++ b/frontend/components/datagrids/applications/isolated/isolatedquadratpersonneldatagrid.tsx @@ -0,0 +1,127 @@ +// quadratpersonnel datagrid +'use client'; +import { Box, Button, Typography } from '@mui/joy'; +import { GridColDef } from '@mui/x-data-grid'; +import { useSession } from 'next-auth/react'; +import React, { useEffect, useState } from 'react'; +import { useOrgCensusContext, usePlotContext, useSiteContext } from '@/app/contexts/userselectionprovider'; +import { GridSelections } from '@/config/macros'; +import { useRouter } from 'next/navigation'; +import { QuadratPersonnelRDS } from '@/config/sqlrdsdefinitions/personnel'; +import IsolatedDataGridCommons from '@/components/datagrids/isolateddatagridcommons'; + +export default function IsolatedQuadratPersonnelDataGrid() { + const initialQuadratPersonnelRDSRow: QuadratPersonnelRDS = { + id: 0, + quadratPersonnelID: 0, + quadratID: 0, + personnelID: 0, + censusID: 0 + }; + const [refresh, setRefresh] = useState(false); + const { data: session } = useSession(); + const router = useRouter(); + + const [quadratOptions, setQuadratOptions] = useState([]); + const [personnelOptions, setPersonnelOptions] = useState([]); + + const currentSite = useSiteContext(); + const currentPlot = usePlotContext(); + const currentCensus = useOrgCensusContext(); + + useEffect(() => { + const fetchOptions = async () => { + const quadratResponse = await fetch(`/api/fetchall/quadrats/${currentPlot?.plotID}/${currentCensus?.plotCensusNumber}?schema=${currentSite?.schemaName}`); + const quadratData = await quadratResponse.json(); + if (quadratData.length === 0) throw new Error('quadratData fetchall is empty'); + setQuadratOptions( + quadratData.map((item: any) => ({ + label: item.quadratName, // Adjust based on your data structure + value: item.quadratID + })) + ); + + const personnelResponse = await fetch(`/api/fetchall/personnel?schema=${currentSite?.schemaName}`); + const personnelData = await personnelResponse.json(); + if (personnelData.length === 0) throw new Error('personnelData fetchall is empty'); + setPersonnelOptions( + personnelData.map((person: any) => ({ + label: `${person.firstName} ${person.lastName}`, // Adjust based on your data structure + value: person.personnelID + })) + ); + }; + if (currentSite && currentPlot && currentCensus) fetchOptions().catch(console.error); + }, [currentSite, currentPlot, currentCensus]); + + const QuadratPersonnelGridColumns: GridColDef[] = [ + { + field: 'quadratPersonnelID', + headerName: 'ID', + headerClassName: 'header', + minWidth: 75, + align: 'left', + editable: false + }, + { + field: 'quadratID', + headerName: 'Quadrat ID', + headerClassName: 'header', + flex: 1, + minWidth: 140, + align: 'left', + type: 'singleSelect', + valueOptions: quadratOptions, + editable: true + }, + { + field: 'personnelID', + headerName: 'Personnel ID', + headerClassName: 'header', + flex: 1, + minWidth: 140, + align: 'left', + type: 'singleSelect', + valueOptions: personnelOptions, + editable: true + } + ]; + + return ( + <> + + + + {session?.user.userStatus !== 'field crew' && ( + + Note: ADMINISTRATOR VIEW + + )} + + {/* Back Button */} + + + + + + ); +} diff --git a/frontend/components/datagrids/applications/isolated/isolatedquadratsdatagrid.tsx b/frontend/components/datagrids/applications/isolated/isolatedquadratsdatagrid.tsx index e69de29b..744ecc60 100644 --- a/frontend/components/datagrids/applications/isolated/isolatedquadratsdatagrid.tsx +++ b/frontend/components/datagrids/applications/isolated/isolatedquadratsdatagrid.tsx @@ -0,0 +1,107 @@ +// quadrats datagrid +'use client'; +import React, { useState } from 'react'; +import { Box, Button, Typography } from '@mui/joy'; +import { useSession } from 'next-auth/react'; +import UploadParentModal from '@/components/uploadsystemhelpers/uploadparentmodal'; +import Link from 'next/link'; +import { quadratGridColumns } from '@/components/client/datagridcolumns'; +import { FormType } from '@/config/macros/formdetails'; +import { QuadratRDS } from '@/config/sqlrdsdefinitions/zones'; +import IsolatedDataGridCommons from '@/components/datagrids/isolateddatagridcommons'; +import { useOrgCensusContext, usePlotContext } from '@/app/contexts/userselectionprovider'; + +export default function IsolatedQuadratsDataGrid() { + const currentPlot = usePlotContext(); + const currentCensus = useOrgCensusContext(); + const initialQuadratRDSRow: QuadratRDS = { + id: 0, + quadratID: 0, + plotID: currentPlot?.plotID, + censusID: currentCensus?.dateRanges[0].censusID, + quadratName: '', + startX: 0, + startY: 0, + coordinateUnits: 'm', + dimensionX: 0, + dimensionY: 0, + dimensionUnits: 'm', + area: 0, + areaUnits: 'm2', + quadratShape: '' + }; + const [refresh, setRefresh] = useState(false); + const { data: session } = useSession(); + const [isUploadModalOpen, setIsUploadModalOpen] = useState(false); + + return ( + <> + + + + {session?.user.userStatus !== 'field crew' && ( + + Note: ADMINISTRATOR VIEW + + )} + + Note: This is a locked view and will not allow modification. + + + Please use this view as a way to confirm changes made to measurements. + + + + {/* Upload Button */} + + {/* Link to Quadrat Personnel Data Grid */} + + + + + + { + setIsUploadModalOpen(false); + setRefresh(true); + }} + formType={FormType.quadrats} + /> + + + ); +} diff --git a/frontend/components/datagrids/applications/isolated/isolatedrolesdatagrid.tsx b/frontend/components/datagrids/applications/isolated/isolatedrolesdatagrid.tsx index e69de29b..c521b1b6 100644 --- a/frontend/components/datagrids/applications/isolated/isolatedrolesdatagrid.tsx +++ b/frontend/components/datagrids/applications/isolated/isolatedrolesdatagrid.tsx @@ -0,0 +1,60 @@ +// roles datagrid +'use client'; +import React, { useState } from 'react'; +import { Box, Typography } from '@mui/joy'; +import { useSession } from 'next-auth/react'; +import { RolesGridColumns } from '@/components/client/datagridcolumns'; +import { RoleRDS } from '@/config/sqlrdsdefinitions/personnel'; +import IsolatedDataGridCommons from '@/components/datagrids/isolateddatagridcommons'; + +type IsolatedRolesDataGridProps = { + onRolesUpdated: () => void; // Accept the onRolesUpdated prop +}; + +export default function IsolatedRolesDataGrid(props: IsolatedRolesDataGridProps) { + const { onRolesUpdated } = props; + const initialRoleRDSRow: RoleRDS = { + id: 0, + roleID: 0, + roleName: '', + roleDescription: '' + }; + const [refresh, setRefresh] = useState(false); + const { data: session } = useSession(); + + return ( + <> + + + + {session?.user.userStatus !== 'field crew' && ( + + Note: ADMINISTRATOR VIEW + + )} + + + + + + + ); +} diff --git a/frontend/components/datagrids/applications/isolated/isolatedstemtaxonomiesviewdatagrid.tsx b/frontend/components/datagrids/applications/isolated/isolatedstemtaxonomiesviewdatagrid.tsx index e69de29b..785ed90f 100644 --- a/frontend/components/datagrids/applications/isolated/isolatedstemtaxonomiesviewdatagrid.tsx +++ b/frontend/components/datagrids/applications/isolated/isolatedstemtaxonomiesviewdatagrid.tsx @@ -0,0 +1,95 @@ +// stemtaxonomiesview datagrid +'use client'; +import React, { useState } from 'react'; +import { Box, Button, Typography } from '@mui/joy'; +import { useSession } from 'next-auth/react'; +import UploadParentModal from '@/components/uploadsystemhelpers/uploadparentmodal'; +import { StemTaxonomiesViewGridColumns } from '@/components/client/datagridcolumns'; +import { FormType } from '@/config/macros/formdetails'; +import { StemTaxonomiesViewRDS } from '@/config/sqlrdsdefinitions/views'; +import IsolatedDataGridCommons from '@/components/datagrids/isolateddatagridcommons'; + +export default function IsolatedStemTaxonomiesViewDataGrid() { + const initialStemTaxonomiesViewRDSRow: StemTaxonomiesViewRDS = { + id: 0, + stemID: 0, + treeID: 0, + speciesID: 0, + genusID: 0, + familyID: 0, + quadratID: 0, + stemTag: '', + treeTag: '', + speciesCode: '', + family: '', + genus: '', + speciesName: '', + subspeciesName: '', + validCode: '', + genusAuthority: '', + speciesAuthority: '', + subspeciesAuthority: '', + speciesIDLevel: '', + speciesFieldFamily: '' + }; + const [refresh, setRefresh] = useState(false); + const [isUploadModalOpen, setIsUploadModalOpen] = useState(false); + const { data: session } = useSession(); + + return ( + <> + + + + {session?.user.userStatus !== 'field crew' && ( + + Note: ADMINISTRATOR VIEW + + )} + + + {/* Upload Button */} + + + + + { + setIsUploadModalOpen(false); + setRefresh(true); + }} + formType={FormType.species} + /> + + + + ); +} diff --git a/frontend/components/datagrids/applications/quadratsdatagrid.tsx b/frontend/components/datagrids/applications/quadratsdatagrid.tsx index 4d0a411b..65072c42 100644 --- a/frontend/components/datagrids/applications/quadratsdatagrid.tsx +++ b/frontend/components/datagrids/applications/quadratsdatagrid.tsx @@ -23,12 +23,12 @@ export default function QuadratsDataGrid() { quadratName: '', startX: 0, startY: 0, - coordinateunit: '', + coordinateUnits: '', dimensionX: 0, dimensionY: 0, - dimensionunit: '', + dimensionUnits: '', area: 0, - areaunit: '', + areaUnits: '', quadratShape: '' }; const [rows, setRows] = React.useState([initialQuadratRDSRow] as GridRowsProp); diff --git a/frontend/components/datagrids/isolateddatagridcommons.tsx b/frontend/components/datagrids/isolateddatagridcommons.tsx index e69de29b..f8c8108a 100644 --- a/frontend/components/datagrids/isolateddatagridcommons.tsx +++ b/frontend/components/datagrids/isolateddatagridcommons.tsx @@ -0,0 +1,901 @@ +'use client'; + +import { + CellItemContainer, + createDeleteQuery, + createFetchQuery, + createPostPatchQuery, + EditToolbarCustomProps, + filterColumns, + getColumnVisibilityModel, + getGridID, + IsolatedDataGridCommonProps, + PendingAction +} from '@/config/datagridhelpers'; +import { + GridActionsCellItem, + GridColDef, + GridEventListener, + GridFilterModel, + GridRowEditStopReasons, + GridRowId, + GridRowModel, + GridRowModes, + GridRowModesModel, + GridRowsProp, + GridToolbar, + GridToolbarContainer, + GridToolbarProps, + ToolbarPropsOverrides, + useGridApiRef +} from '@mui/x-data-grid'; +import { Alert, AlertProps, Button, Snackbar } from '@mui/material'; +import AddIcon from '@mui/icons-material/Add'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import FileDownloadIcon from '@mui/icons-material/FileDownload'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { useOrgCensusContext, usePlotContext, useQuadratContext, useSiteContext } from '@/app/contexts/userselectionprovider'; +import { useLoading } from '@/app/contexts/loadingprovider'; +import { useDataValidityContext } from '@/app/contexts/datavalidityprovider'; +import { useSession } from 'next-auth/react'; +import { HTTPResponses, UnifiedValidityFlags } from '@/config/macros'; +import { Tooltip, Typography } from '@mui/joy'; +import SaveIcon from '@mui/icons-material/Save'; +import CancelIcon from '@mui/icons-material/Close'; +import EditIcon from '@mui/icons-material/Edit'; +import DeleteIcon from '@mui/icons-material/DeleteOutlined'; +import { redirect } from 'next/navigation'; +import Box from '@mui/joy/Box'; +import { StyledDataGrid } from '@/config/styleddatagrid'; +import ReEnterDataModal from '@/components/datagrids/reentrydatamodal'; +import ConfirmationDialog from '@/components/datagrids/confirmationdialog'; +import { randomId } from '@mui/x-data-grid-generator'; + +type EditToolbarProps = EditToolbarCustomProps & GridToolbarProps & ToolbarPropsOverrides; + +const EditToolbar = ({ handleAddNewRow, handleRefresh, handleExportAll, locked, filterModel }: EditToolbarProps) => { + if (!handleAddNewRow || !handleRefresh) return <>; + const handleExportClick = async () => { + if (!handleExportAll) return; + const fullData = await handleExportAll(filterModel); + const blob = new Blob([JSON.stringify(fullData, null, 2)], { + type: 'application/json' + }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = 'data.json'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + + return ( + + + + + + + ); +}; + +export default function IsolatedDataGridCommons(props: Readonly) { + const { gridColumns, gridType, refresh, setRefresh, locked = false, selectionOptions, initialRow, fieldToFocus, clusters } = props; + + const [rows, setRows] = useState([initialRow] as GridRowsProp); + const [rowCount, setRowCount] = useState(0); + const [rowModesModel, setRowModesModel] = useState({}); + const [snackbar, setSnackbar] = React.useState | null>(null); + const [paginationModel, setPaginationModel] = useState({ + page: 0, + pageSize: 10 + }); + const [isNewRowAdded, setIsNewRowAdded] = useState(false); + const [shouldAddRowAfterFetch, setShouldAddRowAfterFetch] = useState(false); + const [newLastPage, setNewLastPage] = useState(null); + const [isDialogOpen, setIsDialogOpen] = useState(false); + const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); + const [pendingAction, setPendingAction] = useState({ + actionType: '', + actionId: null + }); + const [promiseArguments, setPromiseArguments] = useState<{ + resolve: (value: GridRowModel) => void; + reject: (reason?: any) => void; + newRow: GridRowModel; + oldRow: GridRowModel; + } | null>(null); + const [filterModel, setFilterModel] = useState({ + items: [] + }); + const [rowsUpdated, setRowsUpdated] = useState(false); + const [rowModesModelUpdated, setRowModesModelUpdated] = useState(false); + + const currentPlot = usePlotContext(); + const currentCensus = useOrgCensusContext(); + const currentQuadrat = useQuadratContext(); + const currentSite = useSiteContext(); + + const { setLoading } = useLoading(); + const { triggerRefresh } = useDataValidityContext(); + + useSession(); + + const apiRef = useGridApiRef(); + + // Track when rows and rowModesModel are updated using useEffect + useEffect(() => { + if (rows.length > 0) { + setRowsUpdated(true); + } + }, [rows]); + + useEffect(() => { + if (Object.keys(rowModesModel).length > 0) { + setRowModesModelUpdated(true); + } + }, [rowModesModel]); + + // Function to wait for rows and rowModesModel to update + const waitForStateUpdates = async () => { + return new Promise(resolve => { + const checkUpdates = () => { + if (rowsUpdated && rowModesModelUpdated) { + resolve(); + } else { + setTimeout(checkUpdates, 50); // Check every 50ms until both are updated + } + }; + checkUpdates(); + }); + }; + + useEffect(() => { + if (!isNewRowAdded) { + fetchPaginatedData(paginationModel.page).catch(console.error); + } + }, [paginationModel.page]); + + useEffect(() => { + if (currentPlot?.plotID || currentCensus?.plotCensusNumber) { + fetchPaginatedData(paginationModel.page).catch(console.error); + } + }, [currentPlot, currentCensus, paginationModel.page]); + + useEffect(() => { + if (refresh && currentSite) { + handleRefresh().then(() => { + if (refresh) { + setRefresh(false); // Only update state if it hasn't already been reset + } + }); + } + }, [refresh, currentSite]); // No need for setRefresh in dependencies + + useEffect(() => { + const updatedRowModesModel = rows.reduce((acc, row) => { + if (row.id) { + acc[row.id] = rowModesModel[row.id] || { mode: GridRowModes.View }; // Ensure valid row ID is used + } + return acc; + }, {} as GridRowModesModel); + + // Clean invalid rowModesModel entries like '0' + const cleanedRowModesModel = Object.fromEntries(Object.entries(updatedRowModesModel).filter(([key]) => key !== '0')); + + if (JSON.stringify(cleanedRowModesModel) !== JSON.stringify(rowModesModel)) { + setRowModesModel(cleanedRowModesModel); + } + }, [rows]); + + const fetchFullData = useCallback(async () => { + setLoading(true, 'Fetching full dataset...'); + let partialQuery = ``; + if (currentPlot?.plotID) partialQuery += `/${currentPlot.plotID}`; + if (currentCensus?.plotCensusNumber) partialQuery += `/${currentCensus.plotCensusNumber}`; + if (currentQuadrat?.quadratID) partialQuery += `/${currentQuadrat.quadratID}`; + const fullDataQuery = `/api/fetchall/${gridType}` + partialQuery + `?schema=${currentSite?.schemaName}`; + + try { + const response = await fetch(fullDataQuery, { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(filterModel) + }); + const data = await response.json(); + if (!response.ok) throw new Error(data.message || 'Error fetching full data'); + return data.output; + } catch (error) { + console.error('Error fetching full data:', error); + setSnackbar({ children: 'Error fetching full data', severity: 'error' }); + return []; + } finally { + setLoading(false); + } + }, [filterModel, currentPlot, currentCensus, currentQuadrat, currentSite, gridType, setLoading]); + + const openConfirmationDialog = useCallback( + (actionType: 'save' | 'delete', actionId: GridRowId) => { + setPendingAction({ actionType, actionId }); + + const row = rows.find(row => String(row.id) === String(actionId)); + if (row) { + if (actionType === 'delete') { + setIsDeleteDialogOpen(true); + } else { + // Open the reentry modal after setting promiseArguments + setIsDialogOpen(true); + } + } + }, + [rows] + ); + + const handleConfirmAction = useCallback( + async (confirmedRow?: GridRowModel) => { + setIsDialogOpen(false); + setIsDeleteDialogOpen(false); + + if (pendingAction.actionType === 'delete' && pendingAction.actionId !== null) { + // Call performDeleteAction if the confirmed action is delete + await performDeleteAction(pendingAction.actionId); + } else if (promiseArguments) { + try { + console.log('handleconfirmaction: confirmedRow: ', confirmedRow); + console.log('handleconfirmaction: promiseArguments.newRow: ', promiseArguments.newRow); + const resolvedRow = confirmedRow || promiseArguments.newRow; + console.log('handleconfirmaction: resolvedRow: ', resolvedRow); + // Proceed with saving the row after confirmation + await performSaveAction(promiseArguments.newRow.id, resolvedRow); + setSnackbar({ children: 'Row successfully updated!', severity: 'success' }); + } catch (error: any) { + setSnackbar({ children: `Error: ${error.message}`, severity: 'error' }); + } + } + + setPendingAction({ actionType: '', actionId: null }); + setPromiseArguments(null); // Clear promise arguments after handling + }, + [pendingAction, promiseArguments] + ); + + const handleCancelAction = useCallback(() => { + setIsDialogOpen(false); + setIsDeleteDialogOpen(false); + if (promiseArguments) { + promiseArguments.reject(new Error('Action cancelled by user')); + } + setPendingAction({ actionType: '', actionId: null }); + setPromiseArguments(null); // Clear promise arguments after handling + }, [promiseArguments]); + + const performSaveAction = useCallback( + async (id: GridRowId, confirmedRow: GridRowModel) => { + if (locked || !promiseArguments) return; + + setLoading(true, 'Saving changes...'); + + try { + // Set the row to view mode after confirmation + setRowModesModel(prevModel => ({ + ...prevModel, + [id]: { mode: GridRowModes.View } + })); + + const updatedRow = await updateRow( + gridType, + currentSite?.schemaName, + confirmedRow, + promiseArguments.oldRow, + setSnackbar, + setIsNewRowAdded, + setShouldAddRowAfterFetch, + fetchPaginatedData, + paginationModel + ); + + promiseArguments.resolve(updatedRow); + + // Trigger onDataUpdate after successfully saving + if (props.onDataUpdate) { + props.onDataUpdate(); + } + } catch (error) { + promiseArguments.reject(error); + } + + triggerRefresh(); + setLoading(false); + await fetchPaginatedData(paginationModel.page); + }, + [ + locked, + promiseArguments, + gridType, + currentSite, + setSnackbar, + setIsNewRowAdded, + setShouldAddRowAfterFetch, + paginationModel, + rows, + triggerRefresh, + setLoading + ] + ); + + const performDeleteAction = useCallback( + async (id: GridRowId) => { + if (locked) return; + + setLoading(true, 'Deleting...'); + + const rowToDelete = rows.find(row => String(row.id) === String(id)); + if (!rowToDelete) return; // Ensure row exists + + const deleteQuery = createDeleteQuery(currentSite?.schemaName ?? '', gridType, getGridID(gridType), rowToDelete.id); + + try { + const response = await fetch(deleteQuery, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ newRow: rowToDelete }) + }); + + if (!response.ok) { + const error = await response.json(); + if (response.status === HTTPResponses.FOREIGN_KEY_CONFLICT) { + setSnackbar({ + children: `Error: Cannot delete row due to foreign key constraint in table ${error.referencingTable}`, + severity: 'error' + }); + } else { + setSnackbar({ + children: `Error: ${error.message || 'Deletion failed'}`, + severity: 'error' + }); + } + } else { + setRows(prevRows => prevRows.filter(row => row.id !== id)); // Update rows by removing the deleted row + setSnackbar({ + children: 'Row successfully deleted', + severity: 'success' + }); + triggerRefresh([gridType as keyof UnifiedValidityFlags]); + await fetchPaginatedData(paginationModel.page); + } + } catch (error: any) { + setSnackbar({ + children: `Error: ${error.message || 'Deletion failed'}`, + severity: 'error' + }); + } finally { + setLoading(false); + } + }, + [locked, rows, currentSite, gridType, setSnackbar, paginationModel, triggerRefresh, setLoading] + ); + + const handleSaveClick = useCallback( + (id: GridRowId) => async () => { + if (locked) return; + + const updatedRowModesModel = { ...rowModesModel }; + if (!updatedRowModesModel[id] || updatedRowModesModel[id].mode === undefined) { + updatedRowModesModel[id] = { mode: GridRowModes.View }; // Set default mode if it doesn't exist + } + + // Stop edit mode and apply changes locally without committing to the server yet + apiRef.current.stopRowEditMode({ id, ignoreModifications: true }); + + // Get the original row data (before edits) + const oldRow = rows.find(row => String(row.id) === String(id)); + + // Use getRowWithUpdatedValues to fetch all updated field values (the field is ignored in row editing mode) + const updatedRow = apiRef.current.getRowWithUpdatedValues(id, 'anyField'); // 'anyField' is a dummy value, ignored in row editing + + if (oldRow && updatedRow) { + // Set promise arguments before opening the modal + setPromiseArguments({ + resolve: (value: GridRowModel) => {}, // Define resolve + reject: (reason?: any) => {}, // Define reject + oldRow, // Pass the old (original) row + newRow: updatedRow // Pass the updated (edited) row + }); + + // Open the confirmation dialog for reentry data + openConfirmationDialog('save', id); + } + }, + [locked, rowModesModel, rows, apiRef, openConfirmationDialog] + ); + + const handleDeleteClick = useCallback( + (id: GridRowId) => () => { + if (locked) return; + if (gridType === 'census') { + const rowToDelete = rows.find(row => String(row.id) === String(id)); + if (currentCensus && rowToDelete && rowToDelete.censusID === currentCensus.dateRanges[0].censusID) { + alert('Cannot delete the currently selected census.'); + return; + } + } + openConfirmationDialog('delete', id); + }, + [locked, gridType, currentCensus, rows, openConfirmationDialog] + ); + + const handleAddNewRow = useCallback(async () => { + if (locked) return; + if (isNewRowAdded) return; // Debounce double adds + const newRowCount = rowCount + 1; + const calculatedNewLastPage = Math.ceil(newRowCount / paginationModel.pageSize) - 1; + const existingLastPage = Math.ceil(rowCount / paginationModel.pageSize) - 1; + const isNewPageNeeded = newRowCount % paginationModel.pageSize === 1; + if (isNewPageNeeded) { + setPaginationModel({ ...paginationModel, page: calculatedNewLastPage }); + } else { + setPaginationModel({ ...paginationModel, page: existingLastPage }); + } + const id = randomId(); // Generate a unique string ID + const newRow = { ...initialRow, id, isNew: true }; + setRows(prevRows => { + return [...prevRows, newRow]; + }); + setRowModesModel(prevModel => { + return { + ...prevModel, + [id]: { mode: GridRowModes.Edit, fieldToFocus } // Add the new row with 'Edit' mode + }; + }); + + setShouldAddRowAfterFetch(isNewPageNeeded); + setNewLastPage(calculatedNewLastPage); + setIsNewRowAdded(true); + }, [locked, isNewRowAdded, rowCount, paginationModel, initialRow, setRows, setRowModesModel, fieldToFocus]); + + const handleRefresh = useCallback(async () => { + await fetchPaginatedData(paginationModel.page); + }, [paginationModel.page]); + + const fetchPaginatedData = async (pageToFetch: number) => { + setLoading(true, 'Loading data...'); + const paginatedQuery = createFetchQuery( + currentSite?.schemaName ?? '', + gridType, + pageToFetch, + paginationModel.pageSize, + currentPlot?.plotID, + currentCensus?.plotCensusNumber, + currentQuadrat?.quadratID + ); + try { + const response = await fetch(paginatedQuery, { method: 'GET' }); + const data = await response.json(); + if (!response.ok) throw new Error(data.message || 'Error fetching data'); + console.log('rows: ', data.output); + setRows(data.output); + setRowCount(data.totalCount); + + if (isNewRowAdded && pageToFetch === newLastPage) { + await handleAddNewRow(); + } + } catch (error) { + console.error('Error fetching data:', error); + setSnackbar({ children: 'Error fetching data', severity: 'error' }); + } finally { + setLoading(false); + } + }; + + const updateRow = async ( + gridType: string, + schemaName: string | undefined, + newRow: GridRowModel, + oldRow: GridRowModel, + setSnackbar: (value: { children: string; severity: 'error' | 'success' }) => void, + setIsNewRowAdded: (value: boolean) => void, + setShouldAddRowAfterFetch: (value: boolean) => void, + fetchPaginatedData: (page: number) => Promise, + paginationModel: { page: number } + ): Promise => { + const gridID = getGridID(gridType); + const fetchProcessQuery = createPostPatchQuery(schemaName ?? '', gridType, gridID); + + try { + const response = await fetch(fetchProcessQuery, { + method: oldRow.isNew ? 'POST' : 'PATCH', // Ensure POST for new row, PATCH for existing + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ oldRow: oldRow, newRow: newRow }) + }); + + const responseJSON = await response.json(); + + if (!response.ok) { + // If the response isn't okay, throw an error to be caught + throw new Error(responseJSON.message || 'An unknown error occurred'); + } + + setSnackbar({ + children: oldRow.isNew ? 'New row added!' : 'Row updated!', + severity: 'success' + }); + + if (oldRow.isNew) { + setIsNewRowAdded(false); + setShouldAddRowAfterFetch(false); + await fetchPaginatedData(paginationModel.page); + } + + return newRow; + } catch (error: any) { + // Handle error, display the error in snackbar + setSnackbar({ children: `Error: ${error.message}`, severity: 'error' }); + return Promise.reject(newRow); // Ensure the promise is rejected so processRowUpdate can handle it + } + }; + + const processRowUpdate = useCallback( + async (newRow: GridRowModel, oldRow: GridRowModel) => { + // If the row is newly added and is being canceled, skip the update + if (newRow?.isNew && !newRow?.id) { + return oldRow; // Return the old row without making changes + } + + setLoading(true, 'Processing changes...'); + + // Handle new rows by confirming the save action with the user + if (newRow.isNew || !newRow.id) { + setPromiseArguments({ + resolve: async (confirmedRow: GridRowModel) => { + try { + const updatedRow = await updateRow( + gridType, + currentSite?.schemaName, + confirmedRow, + oldRow, + setSnackbar, + setIsNewRowAdded, + setShouldAddRowAfterFetch, + fetchPaginatedData, + paginationModel + ); + setLoading(false); + return updatedRow; + } catch (error: any) { + setLoading(false); + setSnackbar({ children: `Error: ${error.message}`, severity: 'error' }); + return Promise.reject(error); + } + }, + reject: reason => { + setLoading(false); + return Promise.reject(reason); + }, + oldRow, + newRow + }); + + openConfirmationDialog('save', newRow.id); + return Promise.reject(new Error('Row update interrupted for new row, awaiting confirmation')); + } + + // Proceed with updating existing rows + try { + const updatedRow = await updateRow( + gridType, + currentSite?.schemaName, + newRow, + oldRow, + setSnackbar, + setIsNewRowAdded, + setShouldAddRowAfterFetch, + fetchPaginatedData, + paginationModel + ); + setLoading(false); + return updatedRow; + } catch (error: any) { + setLoading(false); + setSnackbar({ children: `Error: ${error.message}`, severity: 'error' }); + return Promise.reject(error); + } + }, + [gridType, currentSite?.schemaName, setSnackbar, setIsNewRowAdded, setShouldAddRowAfterFetch, fetchPaginatedData, paginationModel] + ); + + const handleRowModesModelChange = useCallback((newRowModesModel: GridRowModesModel) => { + setRowModesModel(prevModel => { + const updatedModel = { ...prevModel }; + Object.keys(newRowModesModel).forEach(id => { + if (updatedModel[id]) { + updatedModel[id] = { + ...updatedModel[id], + ...newRowModesModel[id], + mode: newRowModesModel[id]?.mode || updatedModel[id]?.mode || GridRowModes.View + }; + } else { + // Prevent setting mode for rows that don't exist in the model + console.warn(`Row ID ${id} does not exist in rowModesModel. Skipping.`); + } + }); + return updatedModel; + }); + }, []); + + const handleCloseSnackbar = useCallback(() => setSnackbar(null), []); + + const handleRowEditStop = useCallback>((params, event) => { + if (params.reason === GridRowEditStopReasons.rowFocusOut) { + event.defaultMuiPrevented = true; + } + }, []); + + const handleEditClick = useCallback( + (id: GridRowId) => () => { + if (locked) return; + setRowModesModel(prevModel => ({ + ...prevModel, + [id]: { mode: GridRowModes.Edit } + })); + // Auto-focus on the first editable cell when entering edit mode + setTimeout(() => { + const firstEditableColumn = filteredColumns.find(col => col.editable); + if (firstEditableColumn) { + apiRef.current.setCellFocus(id, firstEditableColumn.field); + } + }); + }, + [locked, apiRef] + ); + + const handleCancelClick = useCallback( + (id: GridRowId, event?: React.MouseEvent | React.KeyboardEvent) => { + if (locked) return; + event?.preventDefault(); + + const row = rows.find(row => String(row.id) === String(id)); + + if (row?.isNew) { + // Remove the new row from the rows state + setRows(oldRows => oldRows.filter(row => row.id !== id)); + + // Safely remove the row from rowModesModel + setRowModesModel(prevModel => { + const updatedModel = { ...prevModel }; + delete updatedModel[id]; // Remove the newly added row from rowModesModel + return updatedModel; + }); + + setIsNewRowAdded(false); // Reset the flag indicating a new row was added + } else { + // Revert the row to view mode if it's an existing row + setRowModesModel(prevModel => ({ + ...prevModel, + [id]: { mode: GridRowModes.View, ignoreModifications: true } + })); + } + }, + [locked, rows] + ); + + const getEnhancedCellAction = useCallback( + (type: string, icon: any, onClick: any) => ( + + + + + + ), + [] + ); + + const getGridActionsColumn = useCallback( + (): GridColDef => ({ + field: 'actions', + type: 'actions', + headerName: 'Actions', + flex: 1, + cellClassName: 'actions', + getActions: ({ id }) => { + if (!rowModesModel[id]?.mode) return []; + const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; + if (isInEditMode && !locked) { + return [ + getEnhancedCellAction('Save', , handleSaveClick(id)), + getEnhancedCellAction('Cancel', , (e: any) => handleCancelClick(id, e)) + ]; + } + return [getEnhancedCellAction('Edit', , handleEditClick(id)), getEnhancedCellAction('Delete', , handleDeleteClick(id))]; + } + }), + [rowModesModel, locked] + ); + + const columns = useMemo(() => { + return [...gridColumns, getGridActionsColumn()]; + }, [gridColumns, rowModesModel, getGridActionsColumn]); + + const filteredColumns = useMemo(() => { + console.log('columns unfiltered: ', columns); + console.log('rows: ', rows); + console.log('filtered: ', filterColumns(rows, columns)); + if (gridType !== 'quadratpersonnel') return filterColumns(rows, columns); + else return columns; + }, [rows, columns]); + + const handleCellDoubleClick: GridEventListener<'cellDoubleClick'> = params => { + if (locked) return; + setRowModesModel(prevModel => ({ + ...prevModel, + [params.id]: { mode: GridRowModes.Edit } + })); + }; + + const handleCellKeyDown: GridEventListener<'cellKeyDown'> = (params, event) => { + if (event.key === 'Enter' && !locked) { + event.defaultMuiPrevented = true; + // console.log('params: ', params); + // setRowModesModel(prevModel => ({ + // ...prevModel, + // [params.id]: { mode: GridRowModes.Edit } + // })); + } + if (event.key === 'Escape') { + event.defaultMuiPrevented = true; + // console.log('params: ', params); + // setRowModesModel(prevModel => ({ + // ...prevModel, + // [params.id]: { mode: GridRowModes.View, ignoreModifications: true } + // })); + // handleCancelClick(params.id, event); + } + }; + + if (!currentSite || !currentPlot || !currentCensus) { + redirect('/dashboard'); + } else { + return ( + + + Note: The Grid is filtered by your selected Plot and Plot ID + { + // Create a promise to wait for state updates + const waitForStateUpdates = async () => { + return new Promise(resolve => { + const checkUpdates = () => { + if (rows.length > 0 && Object.keys(rowModesModel).length > 0) { + resolve(); // Resolve when states are updated + } else { + setTimeout(checkUpdates, 50); // Retry every 50ms + } + }; + checkUpdates(); + }); + }; + + // Wait for rows and rowModesModel to update + await waitForStateUpdates(); + + // Now call the actual processRowUpdate logic after the state has settled + try { + return await processRowUpdate(newRow, oldRow); + } catch (error) { + console.error('Error processing row update:', error); + setSnackbar({ children: 'Error updating row', severity: 'error' }); + return Promise.reject(error); // Handle error if needed + } + }} + onProcessRowUpdateError={error => { + console.error('Row update error:', error); + setSnackbar({ + children: 'Error updating row', + severity: 'error' + }); + }} + loading={refresh} + paginationMode="server" + onPaginationModelChange={setPaginationModel} + paginationModel={paginationModel} + rowCount={rowCount} + pageSizeOptions={[paginationModel.pageSize]} + filterModel={filterModel} + onFilterModelChange={newFilterModel => setFilterModel(newFilterModel)} + initialState={{ + columns: { + columnVisibilityModel: getColumnVisibilityModel(gridType) + } + }} + slots={{ + toolbar: EditToolbar + }} + slotProps={{ + toolbar: { + locked: locked, + handleAddNewRow: handleAddNewRow, + handleRefresh: handleRefresh, + handleExportAll: fetchFullData, + filterModel: filterModel + } + }} + autoHeight + getRowHeight={() => 'auto'} + /> + + {!!snackbar && ( + + + + )} + {isDialogOpen && promiseArguments && ( + + )} + {isDeleteDialogOpen && ( + + )} + + ); + } +} diff --git a/frontend/components/datagrids/reentrydatamodal.tsx b/frontend/components/datagrids/reentrydatamodal.tsx index ef24d961..34957ff9 100644 --- a/frontend/components/datagrids/reentrydatamodal.tsx +++ b/frontend/components/datagrids/reentrydatamodal.tsx @@ -1,8 +1,7 @@ 'use client'; import React, { useEffect, useState } from 'react'; -import { DataGrid, GridColDef, GridRenderCellParams, GridRowModel } from '@mui/x-data-grid'; +import { DataGrid, GridColDef, GridRowModel } from '@mui/x-data-grid'; import moment from 'moment'; -import { ColumnStates, unitSelectionOptions } from '@/config/macros'; import { Box, Button, @@ -20,8 +19,8 @@ import { Typography } from '@mui/joy'; import { DatePicker } from '@mui/x-date-pickers'; - -import { AttributeStatusOptions } from '@/config/sqlrdsdefinitions/core'; +import { areaSelectionOptions, unitSelectionOptions } from '@/config/macros'; +import { useOrgCensusContext, usePlotContext } from '@/app/contexts/userselectionprovider'; interface ReEnterDataModalProps { row: GridRowModel; @@ -30,25 +29,27 @@ interface ReEnterDataModalProps { handleSave: (selectedRow: GridRowModel) => void; columns: GridColDef[]; selectionOptions?: { value: string | number; label: string }[]; - hiddenColumns?: ColumnStates; + clusters?: Record; // New clusters prop for field grouping + hiddenColumns?: Record; } -const ReEnterDataModal: React.FC = ({ row, reEnterData, handleClose, handleSave, columns, selectionOptions, hiddenColumns }) => { +const ReEnterDataModal: React.FC = ({ + row, + reEnterData, + handleClose, + handleSave, + columns, + selectionOptions, + clusters, + hiddenColumns +}) => { const [localData, setLocalData] = useState({ ...reEnterData }); const [selectedRow, setSelectedRow] = useState(null); const [isConfirmStep, setIsConfirmStep] = useState(false); const [isRowSelected, setIsRowSelected] = useState(false); - const calculateDialogWidth = () => { - const baseWidth = 300; - const totalFlex = columns.reduce((acc, column) => acc + (column.flex || 0), 0); - const totalMinWidth = columns.reduce((acc, column) => acc + (column.minWidth || 0), 0); - const flexWidth = totalFlex ? totalFlex * 100 : 0; - - return Math.max(baseWidth + flexWidth, totalMinWidth); - }; - - const dialogWidth = calculateDialogWidth(); + const currentPlot = usePlotContext(); + const currentCensus = useOrgCensusContext(); useEffect(() => { if (reEnterData) { @@ -58,11 +59,9 @@ const ReEnterDataModal: React.FC = ({ row, reEnterData, h if ( editable && initialData[field] !== localData[field] && - (initialData[field] !== '' || - initialData[field] !== null || - initialData[field] !== undefined || - initialData[field] !== false || - initialData[field] !== 0) + initialData[field] !== '' && + initialData[field] !== null && + initialData[field] !== undefined ) { initialData[field] = ''; } @@ -71,10 +70,53 @@ const ReEnterDataModal: React.FC = ({ row, reEnterData, h } }, [row, reEnterData, columns]); + const normalizeRowData = (row: GridRowModel): GridRowModel => { + return Object.keys(row).reduce((acc, key) => { + const value = row[key]; + const column = columns.find(col => col.field === key); + + // If column is not found or field is non-editable, skip processing this field + if (!column || !column.editable) { + acc[key] = value; + return acc; + } + + // Handle specific fields like PlotID, CensusID that should not be normalized to empty or default + if (key === 'plotID' || key === 'censusID') { + // Keep PlotID and CensusID intact or use the default context values + acc[key] = value !== null && value !== undefined ? value : key === 'plotID' ? currentPlot?.plotID : currentCensus?.dateRanges[0]?.censusID; + } + // Handle normal cases for null/undefined values or fields that require normalization + else if (value === null || value === undefined) { + if (column.type === 'number') { + acc[key] = 0; // Normalize numbers to 0 + } else if (column.type === 'date') { + acc[key] = null; // Normalize date fields to null + } else if (column.type === 'singleSelect') { + const fieldSelectionOptions = getFieldSelectionOptions(key) as string[]; + if (fieldSelectionOptions.includes('m')) { + acc[key] = 'm'; // Default unit for specific fields + } else if (fieldSelectionOptions.includes('m2')) { + acc[key] = 'm2'; // Default area unit + } else { + acc[key] = ''; // Default to empty string for other single select fields + } + } else { + acc[key] = ''; // Default to empty string for other cases + } + } else { + // Keep valid values as they are + acc[key] = value; + } + + return acc; + }, {} as GridRowModel); + }; + const handleInputChange = (field: string, value: any) => { setLocalData(prevData => ({ ...prevData, - [field]: value + [field]: value === null || value === undefined ? '' : value })); }; @@ -90,7 +132,10 @@ const ReEnterDataModal: React.FC = ({ row, reEnterData, h const handleFinalConfirm = () => { if (selectedRow) { const { label, ...remaining } = selectedRow; - handleSave(remaining); + console.log('selectedRow: ', selectedRow); + const normalizedData = normalizeRowData(remaining); + console.log('normalized row: ', normalizedData); + handleSave(normalizedData); } }; @@ -102,83 +147,104 @@ const ReEnterDataModal: React.FC = ({ row, reEnterData, h return value; }; - // Filter the columns based on hiddenColumns - const filteredColumns = columns.filter(column => { - const isHidden = hiddenColumns ? hiddenColumns[column.field] === false : false; - return !isHidden; - }); + const getFieldSelectionOptions = (field: string) => { + const fieldLower = field.toLowerCase(); + if ((fieldLower.includes('coordinate') || fieldLower.includes('dimension')) && fieldLower.includes('units')) { + return unitSelectionOptions; + } + if (fieldLower.includes('area') && fieldLower.includes('units')) { + return areaSelectionOptions; + } + return selectionOptions || []; + }; - return ( - - - Confirm Changes - - {!isConfirmStep ? ( - - {filteredColumns.map(column => { - const { field, type, editable } = column; - const value = localData[field]; - if (!editable) { - return null; - } - if (type === 'singleSelect') { - let valueOptions; - if (field.toLowerCase().includes('unit')) { - valueOptions = unitSelectionOptions; - } else if (field === 'status') { - valueOptions = AttributeStatusOptions; - } else { - valueOptions = selectionOptions; - } + const renderFormFields = (fields: string[]) => + fields.map(field => { + const column = columns.find(col => col.field === field); + if (!column || !column.editable) return null; + const { headerName, type } = column; + const value = localData[field]; + const fieldOptions = getFieldSelectionOptions(field); + + if (type === 'singleSelect') { + return ( + + {headerName} + { - handleInputChange(field, newValue); - }} - > - {(valueOptions === unitSelectionOptions || valueOptions === AttributeStatusOptions) && - valueOptions.map(option => ( - - ))} - {valueOptions === selectionOptions && - valueOptions?.map(option => ( - - ))} - - + ); - } - if (type === 'date') { + } else { return ( - - {column.headerName} - { - if (newValue) handleInputChange(field, moment(newValue).utc().format('YYYY-MM-DD')); - }} - /> - + ); } - return ( - - {column.headerName} - handleInputChange(field, e.target.value)} fullWidth /> - - ); })} - + + + ); + } + + if (type === 'date') { + return ( + + {headerName} + handleInputChange(field, moment(newValue).utc().format('YYYY-MM-DD'))} + /> + + ); + } + + return ( + + {headerName} + handleInputChange(field, e.target.value)} fullWidth /> + + ); + }); + + const filteredColumns = columns.filter(column => !hiddenColumns?.[column.field] && !column.field.includes('ID')); + + const rowsData = [ + row ? { ...row, id: 'starter', label: 'Original' } : null, + reEnterData ? { ...reEnterData, id: 'original', label: 'First Modification' } : null, + localData ? { ...localData, id: 'modified', label: 'Second Modification (Re-entry)' } : null + ].filter(rowItem => rowItem && rowItem.id); // Filter out rows without an ID + + useEffect(() => { + console.log('reEnterData:', reEnterData); + console.log('localData:', localData); + }, [reEnterData, localData]); + + return ( + + + Re-Enter Data + + {!isConfirmStep ? ( + <> + {clusters && + Object.entries(clusters).map(([clusterName, fields]) => ( + + + {clusterName} + + + {renderFormFields(fields)} + + + ))} + ) : ( Please choose from the following -- @@ -193,19 +259,7 @@ const ReEnterDataModal: React.FC = ({ row, reEnterData, h = ({ row, reEnterData, h ...col, flex: col.flex || 1, minWidth: col.minWidth || 150, - renderCell: (params: GridRenderCellParams) => ( - - {selectionOptions && col.type === 'singleSelect' ? getOptionLabel(col.field, params.value) : params.value} - - ) + renderCell: (params: any) => { + const value = params.value; + const displayValue = typeof value === 'object' && value !== null ? JSON.stringify(value) : value; + return ( + + {selectionOptions && col.type === 'singleSelect' ? getOptionLabel(col.field, displayValue) : displayValue} + + ); + } })) ]} getRowId={row => row.id} diff --git a/frontend/components/processors/processorhelperfunctions.tsx b/frontend/components/processors/processorhelperfunctions.tsx index f113777e..b6980508 100644 --- a/frontend/components/processors/processorhelperfunctions.tsx +++ b/frontend/components/processors/processorhelperfunctions.tsx @@ -3,6 +3,7 @@ import { fileMappings, getConn, InsertUpdateProcessingProps, runQuery } from '@/ import { processCensus } from '@/components/processors/processcensus'; import MapperFactory from '@/config/datamapper'; import { SitesRDS, SitesResult } from '@/config/sqlrdsdefinitions/zones'; +import { capitalizeAndTransformField } from '@/config/utils'; // need to try integrating this into validation system: @@ -226,14 +227,30 @@ export function detectFieldChanges(newRow: any, oldRow: any, fieldList: string[] return fieldList.filter(field => newRow[field] !== oldRow[field]); } -export function generateUpdateQueries(schema: string, table: string, changedFields: string[], newRow: any, primaryKey: string): string[] { - if (!newRow[primaryKey]) { +export function generateUpdateQueries( + schema: string, + table: string, + changedFields: string[], + newRow: Record, // Explicitly define newRow as a Record + primaryKey: keyof Result +): string[] { + if (!newRow[primaryKey as string]) { // Skip queries where primary key is null return []; } return changedFields.map(field => { - return mysql.format(`UPDATE ?? SET ?? = ? WHERE ?? = ?`, [`${schema}.${table}`, field, newRow[field], primaryKey, newRow[primaryKey]]); + // Apply the combined capitalization and transformation function + const transformedField = capitalizeAndTransformField(field); + + // Format the query using mysql.format + return mysql.format(`UPDATE ?? SET ?? = ? WHERE ?? = ?`, [ + `${schema}.${table}`, // Table reference + transformedField, // Transformed column name + newRow[field], // Value from newRow corresponding to the field + primaryKey as string, // Primary key as a string + newRow[primaryKey as string] // Primary key value from newRow + ]); }); } @@ -303,14 +320,21 @@ export function generateInsertOperations(schema: string, newRow: any, config: Up .filter(query => query.length > 0); } -export function generateInsertQuery(schema: string, table: string, fields: string[], newRow: any): string { +export function generateInsertQuery( + schema: string, + table: string, + fields: string[], + newRow: Record // Explicitly define newRow as a Record +): string { // Create an object containing only the fields in this slice const dataToInsert = fields.reduce( (obj, field) => { - obj[field] = newRow[field]; + // Apply the combined capitalization and transformation function + const transformedField = capitalizeAndTransformField(field); + obj[transformedField] = newRow[field]; // Safely assign the value from newRow return obj; }, - {} as Record + {} as Record // Define the accumulator as a Record ); // Use mysql.format to safely construct the query @@ -325,10 +349,9 @@ export const allTaxonomiesFields = [ 'genusAuthority', 'speciesCode', 'speciesName', + 'validCode', 'subspeciesName', 'speciesAuthority', - 'currentTaxonFlag', - 'obsoleteTaxonFlag', 'fieldFamily', 'speciesDescription' ]; @@ -354,11 +377,7 @@ export const AllTaxonomiesViewQueryConfig: UpdateQueryConfig = { slices: { family: { range: [0, 1], primaryKey: 'FamilyID' }, genus: { range: [1, 3], primaryKey: 'GenusID' }, - species: { range: [3, 11], primaryKey: 'SpeciesID' }, - reference: { - range: [11, allTaxonomiesFields.length], - primaryKey: 'ReferenceID' - } + species: { range: [3, allTaxonomiesFields.length], primaryKey: 'SpeciesID' } } }; diff --git a/frontend/components/sidebar.tsx b/frontend/components/sidebar.tsx index 7a53353c..a4fc46fe 100644 --- a/frontend/components/sidebar.tsx +++ b/frontend/components/sidebar.tsx @@ -95,7 +95,7 @@ function MenuRenderToggle( }} sx={{ width: '100%', padding: 0, margin: 0 }} > - + {`Plot: ${selectedPlot?.plotName}`} - — {selectedPlot.numQuadrats ? `Quadrats: ${selectedPlot.numQuadrats}` : 'No Quadrats'} + — {selectedPlot.numQuadrats || selectedPlot.numQuadrats === 0 ? `Quadrats: ${selectedPlot.numQuadrats}` : 'No Quadrats'} @@ -355,34 +355,40 @@ export default function Sidebar(props: SidebarProps) { const selectedValue = option.value; const selectedCensus = censusListContext?.find(c => c?.plotCensusNumber?.toString() === selectedValue); + + if (!selectedCensus) { + return Select a Census; + } + + const startDate = census?.dateRanges[0]?.startDate; + const endDate = census?.dateRanges[0]?.endDate; + + const hasStartDate = startDate !== undefined && startDate !== null; + const hasEndDate = endDate !== undefined && endDate !== null; + + // Determine the message based on the presence of startDate and endDate + const dateMessage = + hasStartDate || hasEndDate ? ( + <> + {hasStartDate && `— First Record: ${new Date(startDate).toDateString()}`} + {hasEndDate && ` — Last Record: ${new Date(endDate).toDateString()}`} + + ) : ( + ' — No Measurements' + ); // Display "No Measurements" if both dates are missing + return ( - <> - {selectedCensus ? ( - - {`Census: ${selectedCensus?.plotCensusNumber}`} - - - {census !== undefined && ( - <> - {census.dateRanges[0]?.startDate !== undefined - ? `\u2014 First Record: ${new Date(census?.dateRanges[0]?.startDate).toDateString()}` - : 'No Records'} - - )} - - - {census !== undefined && ( - <>{census.dateRanges[0]?.endDate !== undefined ? `\u2014 Last Record ${new Date(census.dateRanges[0]?.endDate).toDateString()}` : ``} - )} - - - - ) : ( - Select a Census - )} - + + {`Census: ${selectedCensus?.plotCensusNumber}`} + + + {census !== undefined && dateMessage} + + + ); }; + type ToggleObject = { toggle?: boolean; setToggle?: Dispatch>; @@ -460,8 +466,8 @@ export default function Sidebar(props: SidebarProps) { {item?.dateRanges?.map((dateRange, index) => ( - - {`${dateRange.startDate ? `First Msmt: ${new Date(dateRange.startDate).toDateString()}` : 'No Measurements'}`} + + {`${dateRange.startDate ? ` — First Msmt: ${new Date(dateRange.startDate).toDateString()}` : ' — No Measurements'}`} {dateRange.endDate && ( @@ -469,7 +475,7 @@ export default function Sidebar(props: SidebarProps) { )} - {`${dateRange.endDate ? `Last Msmt: ${new Date(dateRange.endDate).toDateString()}` : ''}`} + {`${dateRange.endDate ? ` — Last Msmt: ${new Date(dateRange.endDate).toDateString()}` : ''}`} @@ -509,8 +515,8 @@ export default function Sidebar(props: SidebarProps) { > {item?.plotName} - - Quadrats: {item?.numQuadrats} + + {item?.numQuadrats ? ` — Quadrats: ${item.numQuadrats}` : ` — No Quadrats`} @@ -749,7 +755,7 @@ export default function Sidebar(props: SidebarProps) { return 'Data needed to complete census!'; } } else { - return 'Requirements Met'; + return undefined; } }; diff --git a/frontend/components/themeregistry/theme.ts b/frontend/components/themeregistry/theme.ts index 5419b7db..bfbec676 100644 --- a/frontend/components/themeregistry/theme.ts +++ b/frontend/components/themeregistry/theme.ts @@ -44,7 +44,9 @@ const theme = extendTheme({ JoyTooltip: { defaultProps: { // Automatically apply this prop globally + disableTouchListener: true, sx: { + leaveDelay: 100, pointerEvents: 'none' } } diff --git a/frontend/components/themeregistry/themeregistry.tsx b/frontend/components/themeregistry/themeregistry.tsx index 34817b21..060259ef 100644 --- a/frontend/components/themeregistry/themeregistry.tsx +++ b/frontend/components/themeregistry/themeregistry.tsx @@ -2,21 +2,22 @@ import '@/styles/globals.css'; import * as React from 'react'; import CssBaseline from '@mui/joy/CssBaseline'; -import { - Experimental_CssVarsProvider as MaterialCssVarsProvider, - experimental_extendTheme as materialExtendTheme, - THEME_ID as MATERIAL_THEME_ID -} from '@mui/material/styles'; +import { createTheme, THEME_ID as MATERIAL_THEME_ID, ThemeProvider as MaterialCssVarsProvider } from '@mui/material/styles'; import { CssVarsProvider as JoyCssVarsProvider } from '@mui/joy/styles'; - import NextAppDirEmotionCacheProvider from './emotioncache'; -const materialTheme = materialExtendTheme(); +// Define the dark mode for the Material theme +const darkTheme = createTheme({ + palette: { + mode: 'dark' + } +}); + export default function ThemeRegistry({ children }: { children: React.ReactNode }) { return ( - - + + {children} diff --git a/frontend/config/datagridhelpers.ts b/frontend/config/datagridhelpers.ts index 484c0367..ed167d2d 100644 --- a/frontend/config/datagridhelpers.ts +++ b/frontend/config/datagridhelpers.ts @@ -151,13 +151,27 @@ export function getGridID(gridType: string): string { } export interface EditToolbarCustomProps { - handleAddNewRow?: () => void; + handleAddNewRow?: () => Promise; handleRefresh?: () => Promise; handleExportAll?: (filterModel?: GridFilterModel) => Promise; filterModel?: GridFilterModel; locked?: boolean; } +export interface IsolatedDataGridCommonProps { + gridType: string; + gridColumns: GridColDef[]; + refresh: boolean; + setRefresh: Dispatch>; + initialRow?: GridRowModel; + fieldToFocus?: string; + locked?: boolean; + selectionOptions?: { value: string | number; label: string }[]; + handleOpenSpeciesLimits?: (id: GridRowId) => void; + onDataUpdate?: () => void; // Add the onDataUpdate prop + clusters?: Record; +} + export interface DataGridCommonProps { gridType: string; gridColumns: GridColDef[]; @@ -210,15 +224,23 @@ export const CellItemContainer = styled('div')({ * Function to determine if all entries in a column are null */ export function allValuesAreNull(rows: GridRowsProp, field: string): boolean { - return rows.length > 0 && rows.every(row => row[field] === null || row[field] === undefined); + return rows.length > 0 && rows.every(row => row[field] === undefined); } /** * Function to filter out columns where all entries are null, except the actions column. */ export function filterColumns(rows: GridRowsProp, columns: GridColDef[]): GridColDef[] { - return columns.filter(col => col.field === 'actions' || col.field === 'speciesLimits' || col.field === 'isValidated' || !allValuesAreNull(rows, col.field)); - // return columns; + console.log('Rows before filtering:', rows); + return columns.filter( + col => + col.field === 'actions' || + col.field === 'dimensionX' || + col.field === 'dimensionY' || + col.field === 'speciesLimits' || + col.field === 'isValidated' || + !allValuesAreNull(rows, col.field) + ); } /** diff --git a/frontend/config/macros.ts b/frontend/config/macros.ts index 10978e4a..2605b443 100644 --- a/frontend/config/macros.ts +++ b/frontend/config/macros.ts @@ -105,8 +105,11 @@ export function formatDate(isoDateString: string): string { return new Date(isoDateString).toLocaleDateString(undefined, options); } -export const unitSelectionOptions = ['km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm']; -export const areaSelectionOptions = ['km2', 'hm2', 'dam2', 'm2', 'dm2', 'cm2', 'mm2']; +export type UnitSelection = 'km' | 'hm' | 'dam' | 'm' | 'dm' | 'cm' | 'mm'; +export type AreaSelection = 'km2' | 'hm2' | 'dam2' | 'm2' | 'dm2' | 'cm2' | 'mm2'; + +export const unitSelectionOptions: UnitSelection[] = ['km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm']; +export const areaSelectionOptions: AreaSelection[] = ['km2', 'hm2', 'dam2', 'm2', 'dm2', 'cm2', 'mm2']; export type ExtendedGridColDef = GridColDef & { required?: boolean; }; diff --git a/frontend/config/sqlrdsdefinitions/views.ts b/frontend/config/sqlrdsdefinitions/views.ts index 7ea68961..7f61afb2 100644 --- a/frontend/config/sqlrdsdefinitions/views.ts +++ b/frontend/config/sqlrdsdefinitions/views.ts @@ -15,6 +15,7 @@ export type AllTaxonomiesViewRDS = { subspeciesName?: string; speciesIDLevel?: string; speciesAuthority?: string; + validCode?: string; subspeciesAuthority?: string; fieldFamily?: string; speciesDescription?: string; diff --git a/frontend/config/sqlrdsdefinitions/zones.ts b/frontend/config/sqlrdsdefinitions/zones.ts index 16e8180f..81d20eb9 100644 --- a/frontend/config/sqlrdsdefinitions/zones.ts +++ b/frontend/config/sqlrdsdefinitions/zones.ts @@ -1,7 +1,7 @@ import { IDataMapper } from '@/config/datamapper'; import { ResultType } from '@/config/utils'; import { RowValidationErrors, ValidationFunction } from '@/config/macros/formdetails'; -import { ColumnStates } from '@/config/macros'; +import { AreaSelection, areaSelectionOptions, ColumnStates, UnitSelection, unitSelectionOptions } from '@/config/macros'; export type SitesRDS = { siteID?: number; @@ -80,12 +80,12 @@ export type QuadratRDS = { quadratName?: string; startX?: number; startY?: number; - coordinateunit?: string; + coordinateUnits?: string; dimensionX?: number; dimensionY?: number; - dimensionunit?: string; + dimensionUnits?: string; area?: number; - areaunit?: string; + areaUnits?: string; quadratShape?: string; }; export type QuadratsResult = ResultType; @@ -93,13 +93,13 @@ export type Quadrat = QuadratRDS | undefined; export const validateQuadratsRow: ValidationFunction = row => { const errors: RowValidationErrors = {}; - if (!row['coordinateunit'] || (row['coordinateunit'] !== null && !['km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm'].includes(row['coordinateunit']))) { + if (!row['coordinateunit'] || (row['coordinateunit'] !== null && !unitSelectionOptions.includes(row['coordinateunit'] as UnitSelection))) { errors['coordinateunit'] = 'Invalid unit value.'; } - if (!row['dimensionunit'] || (row['dimensionunit'] !== null && !['km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm'].includes(row['dimensionunit']))) { + if (!row['dimensionunit'] || (row['dimensionunit'] !== null && !unitSelectionOptions.includes(row['dimensionunit'] as UnitSelection))) { errors['dimensionunit'] = 'Invalid unit value.'; } - if (!row['areaunit'] || (row['areaunit'] !== null && !['km2', 'hm2', 'dam2', 'm2', 'dm2', 'cm2', 'mm2'].includes(row['areaunit']))) { + if (!row['areaunit'] || (row['areaunit'] !== null && !areaSelectionOptions.includes(row['areaunit'] as AreaSelection))) { errors['areaunit'] = 'Invalid unit value.'; } @@ -130,7 +130,7 @@ export type SubquadratResult = ResultType; export const validateSubquadratsRow: ValidationFunction = row => { const errors: RowValidationErrors = {}; - if (row['unit'] && !['km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm'].includes(row['unit'])) { + if (row['unit'] && !unitSelectionOptions.includes(row['unit'] as UnitSelection)) { errors['unit'] = 'Invalid unit value.'; } diff --git a/frontend/config/utils.ts b/frontend/config/utils.ts index 71d83faa..08da77c2 100644 --- a/frontend/config/utils.ts +++ b/frontend/config/utils.ts @@ -206,3 +206,26 @@ export type CommonKeys = { }[keyof T & keyof U]; export type Common = Pick>; + +export function capitalizeFirstLetter(field: string): string { + return field.charAt(0).toUpperCase() + field.slice(1); +} + +export function transformSpecialCases(field: string): string { + if (/dbh/i.test(field)) { + return field.replace(/dbh/gi, 'DBH'); + } else if (/hom/i.test(field)) { + return field.replace(/hom/gi, 'HOM'); + } else if (/id/i.test(field)) { + return field.replace(/id/gi, 'ID'); + } else if (/cma/i.test(field)) { + return field.replace(/cma/gi, 'CMA'); + } + return field; +} + +// Combined function that first capitalizes and then applies the special cases +export function capitalizeAndTransformField(field: string): string { + const capitalized = capitalizeFirstLetter(field); + return transformSpecialCases(capitalized); +} diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts index 4f11a03d..40c3d680 100644 --- a/frontend/next-env.d.ts +++ b/frontend/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a7f1fc3b..8c3469e8 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,24 +9,24 @@ "version": "acacia", "hasInstallScript": true, "dependencies": { - "@mui/lab": "^5.0.0-alpha.173", + "@mui/lab": "^6.0.0-beta.9", "eslint": "^8.57.0", - "mysql2": "^3.11.0", + "mysql2": "^3.11.2", "@mui/joy": "^5.0.0-beta.48", - "@playwright/test": "^1.46.1", + "@playwright/test": "^1.47.0", "sharp": "^0.33.5", - "@mui/system": "^5.16.7", + "@mui/system": "^6.1.0", "prettier": "^3.3.3", "globby": "^14.0.2", - "next": "^14.2.6", + "next": "^14.2.9", "jest-mock": "^29.7.0", "dotenv": "^16.4.5", "eslint-plugin-prettier": "^5.2.1", "unzipper": "^0.12.3", - "@mui/x-data-grid": "^7.14.0", + "@mui/x-data-grid": "^7.16.0", "reflect-metadata": "^0.2.2", "react-markdown": "^9.0.1", - "@next/bundle-analyzer": "^14.2.6", + "@next/bundle-analyzer": "^14.2.9", "idb": "^8.0.0", "use-count-up": "^3.0.1", "@types/file-saver": "^2.0.7", @@ -41,27 +41,27 @@ "eslint-config-prettier": "^9.1.0", "@popperjs/core": "^2.11.8", "@octokit/types": "^13.5.0", - "node-mocks-http": "^1.15.1", + "node-mocks-http": "^1.16.0", "file-saver": "^2.0.5", "jest": "^29.7.0", "date-fns": "^3.6.0", "net": "^1.0.2", "@codemirror/lang-sql": "^6.7.1", "@react-spring/web": "^9.7.4", - "react-joyride": "^2.8.2", - "@mui/material": "^5.16.7", + "react-joyride": "^2.9.1", + "@mui/material": "^6.1.0", "@types/react-dom": "^18.3.0", - "@mui/icons-material": "^5.16.7", + "@mui/icons-material": "^6.1.0", "octokit": "^4.0.2", "node-cron": "^3.0.3", "@emotion/styled": "^11.13.0", "jsdom": "^25.0.0", "moment": "^2.30.1", "@testing-library/react": "^16.0.1", - "typescript": "^5.5.4", + "typescript": "^5.6.2", "react-dom": "^18.3.1", "papaparse": "^5.4.1", - "@types/node": "^22.5.0", + "@types/node": "^22.5.4", "ts-node": "^10.9.2", "chalk": "^5.3.0", "@types/react-dropzone": "^5.1.0", @@ -71,8 +71,8 @@ "@types/supertest": "^6.0.2", "tailwindcss": "^3.4.10", "eslint-plugin-unused-imports": "^3.2.0", - "@uiw/react-codemirror": "^4.23.0", - "@mui/x-date-pickers": "^7.14.0", + "@uiw/react-codemirror": "^4.23.2", + "@mui/x-date-pickers": "^7.16.0", "notistack": "^3.0.1", "@vitejs/plugin-react-swc": "^3.7.0", "@typescript-eslint/eslint-plugin": "^7.18.0", @@ -80,7 +80,7 @@ "@azure/storage-blob": "^12.24.0", "tailwind-variants": "^0.2.1", "@testing-library/jest-dom": "^6.5.0", - "@mui/x-data-grid-generator": "^7.14.0", + "@mui/x-data-grid-generator": "^7.16.0", "@emotion/react": "^11.13.3", "vitest": "^2.0.5", "codemirror": "^6.0.1", @@ -94,7 +94,7 @@ "npm-force-resolutions": "^0.0.10", "resize-observer-polyfill": "^1.5.1", "@mui/base": "^5.0.0-beta.40", - "@types/react": "^18.3.4" + "@types/react": "^18.3.5" }, "devDependencies": { "@monaco-editor/react": "^4.6.0", @@ -361,17 +361,6 @@ "@types/tern": "*" } }, - "node_modules/vitest/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -483,13 +472,13 @@ } }, "node_modules/@mui/x-date-pickers": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.15.0.tgz", - "integrity": "sha512-YQEQICNxUEFYp/I/yP58cqihA8yhXaXSNZ1/N0JANu2IlCwoJ4Jzi+S0s4RN7RghpiDyoSMFijROBC5HfpTjiw==", - "license": "MIT", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.16.0.tgz", + "integrity": "sha512-NjFAoI6NiJ/65LJf5A38Y+aA/zSIow+7i52QBcgryrdBlIu46nssqzohPRWNUFwnxNXhWstfcV3YAb2avCIY5A==", "dependencies": { - "@babel/runtime": "^7.25.4", + "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6", + "@mui/x-internals": "7.16.0", "@types/react-transition-group": "^4.4.11", "clsx": "^2.1.1", "prop-types": "^15.8.1", @@ -550,16 +539,14 @@ "node_modules/exceljs/node_modules/bluebird": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "license": "MIT" + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==" }, "node_modules/@mui/x-license": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@mui/x-license/-/x-license-7.15.0.tgz", - "integrity": "sha512-dmtUz3E5L1j+Wg6gZLkroCdan14wl3OKawZ+QIIcDkZDR2HoFxlkSHkwcq0oh7NsT8TFp6fIApb12pbPjVXO8g==", - "license": "SEE LICENSE IN LICENSE", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-license/-/x-license-7.16.0.tgz", + "integrity": "sha512-7vRfqyTsYNsW6G8uQqdSZ+S52SaGTYFX8yMfX7eYSUXIGn6Zc/c58yDWAfjRMiIazvTV1U2dxMXUf1XT8Sm22A==", "dependencies": { - "@babel/runtime": "^7.25.4", + "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6" }, "engines": { @@ -609,6 +596,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@mui/joy/node_modules/@mui/private-theming": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", + "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.16.6", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/postcss-js": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", @@ -628,6 +641,45 @@ "postcss": "^8.4.21" } }, + "node_modules/@mui/joy/node_modules/@mui/system": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz", + "integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.16.6", + "@mui/styled-engine": "^5.16.6", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -756,12 +808,11 @@ } }, "node_modules/playwright": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", - "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", - "license": "Apache-2.0", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", + "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", "dependencies": { - "playwright-core": "1.46.1" + "playwright-core": "1.47.0" }, "bin": { "playwright": "cli.js" @@ -1264,17 +1315,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/jest-changed-files/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/which-builtin-type": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", @@ -1534,8 +1574,7 @@ "node_modules/exceljs/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/diff": { "version": "4.0.2", @@ -1763,7 +1802,6 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -1809,8 +1847,7 @@ "node_modules/exceljs/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", @@ -2623,8 +2660,7 @@ "node_modules/lodash.isnil": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", - "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==", - "license": "MIT" + "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==" }, "node_modules/micromark-util-sanitize-uri": { "version": "2.0.0", @@ -2698,7 +2734,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/exceljs/-/exceljs-4.4.0.tgz", "integrity": "sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==", - "license": "MIT", "dependencies": { "archiver": "^5.0.0", "dayjs": "^1.8.34", @@ -2744,8 +2779,7 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "license": "MIT" + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "node_modules/aws-ssl-profiles": { "version": "1.1.2", @@ -2803,8 +2837,7 @@ "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, "node_modules/globby/node_modules/path-type": { "version": "5.0.0", @@ -3138,8 +3171,7 @@ "node_modules/lodash.isundefined": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", - "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==", - "license": "MIT" + "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==" }, "node_modules/didyoumean": { "version": "1.2.2", @@ -3289,6 +3321,37 @@ "node": ">=10" } }, + "node_modules/@mui/lab/node_modules/@mui/base": { + "version": "5.0.0-beta.58", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.58.tgz", + "integrity": "sha512-P0E7ZrxOuyYqBvVv9w8k7wm+Xzx/KRu+BGgFcR2htTsGCpJNQJCSUXNUZ50MUmSU9hzqhwbQWNXhV1MBTl6F7A==", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@floating-ui/react-dom": "^2.1.1", + "@mui/types": "^7.2.15", + "@mui/utils": "6.0.0-rc.0", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@babel/plugin-syntax-private-property-in-object": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", @@ -3317,7 +3380,6 @@ "version": "4.3.5", "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==", - "license": "MIT", "dependencies": { "@types/node": "^14.0.1", "lodash.escaperegexp": "^4.1.2", @@ -3807,6 +3869,35 @@ "node": ">=10" } }, + "node_modules/@mui/system/node_modules/@mui/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-oT8ZzMISRUhTVpdbYzY0CgrCBb3t/YEdcaM13tUnuTjZ15pdA6g5lx15ZJUdgYXV6PbJdw7tDQgMEr4uXK5TXQ==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/types": "^7.2.16", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/micromark-extension-gfm-table": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", @@ -3825,10 +3916,9 @@ } }, "node_modules/@next/env": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.7.tgz", - "integrity": "sha512-OTx9y6I3xE/eih+qtthppwLytmpJVPM5PPoJxChFsbjIEFXIayG0h/xLzefHGJviAa3Q5+Fd+9uYojKkHDKxoQ==", - "license": "MIT" + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.9.tgz", + "integrity": "sha512-hnDAoDPMii31V0ivibI8p6b023jOF1XblWTVjsDUoZKwnZlaBtJFZKDwFqi22R8r9i6W08dThUWU7Bsh2Rg8Ww==" }, "node_modules/notistack": { "version": "3.0.1", @@ -3855,8 +3945,7 @@ "node_modules/@types/format-util": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@types/format-util/-/format-util-1.0.4.tgz", - "integrity": "sha512-xrCYOdHh5zA3LUrn6CvspYwlzSWxPso11Lx32WnAG6KvLCRecKZ/Rh21PLXUkzUFsQmrGcx/traJAFjR6dVS5Q==", - "license": "MIT" + "integrity": "sha512-xrCYOdHh5zA3LUrn6CvspYwlzSWxPso11Lx32WnAG6KvLCRecKZ/Rh21PLXUkzUFsQmrGcx/traJAFjR6dVS5Q==" }, "node_modules/@sinonjs/commons": { "version": "3.0.1", @@ -3888,8 +3977,7 @@ "node_modules/@fast-csv/parse/node_modules/@types/node": { "version": "14.18.63", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", - "license": "MIT" + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==" }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", @@ -4215,8 +4303,7 @@ "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, "node_modules/eslint-config-prettier": { "version": "9.1.0", @@ -4502,7 +4589,6 @@ "version": "0.10.14", "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "license": "MIT", "dependencies": { "big-integer": "^1.6.17", "binary": "~0.3.0", @@ -4546,17 +4632,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "license": "MIT" }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", @@ -4631,18 +4706,18 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", - "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", - "license": "MIT", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.0.tgz", + "integrity": "sha512-MZ+vtaCkjamrT41+b0Er9OMenjAtP/32+L6fARL9/+BZKuV2QbR3q3TmavT2x0NhDu35IM03s4yKqj32Ziqnyg==", "dependencies": { - "@babel/runtime": "^7.23.9", - "@emotion/cache": "^11.11.0", + "@babel/runtime": "^7.25.6", + "@emotion/cache": "^11.13.1", + "@emotion/sheet": "^1.4.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", @@ -4651,7 +4726,7 @@ "peerDependencies": { "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -4765,10 +4840,9 @@ "license": "MIT" }, "node_modules/playwright-core": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", - "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", - "license": "Apache-2.0", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", + "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", "bin": { "playwright-core": "cli.js" }, @@ -4776,14 +4850,6 @@ "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/http": { "version": "0.0.1-security", "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", @@ -4995,26 +5061,25 @@ "license": "MIT" }, "node_modules/@mui/material": { - "version": "5.16.7", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.7.tgz", - "integrity": "sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/core-downloads-tracker": "^5.16.7", - "@mui/system": "^5.16.7", - "@mui/types": "^7.2.15", - "@mui/utils": "^5.16.6", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.0.tgz", + "integrity": "sha512-4MJ46vmy1xbm8x+ZdRcWm8jEMMowdS8pYlhKQzg/qoKhOcLhImZvf2Jn6z9Dj6gl+lY+C/0MxaHF/avAAGys3Q==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/core-downloads-tracker": "^6.1.0", + "@mui/system": "^6.1.0", + "@mui/types": "^7.2.16", + "@mui/utils": "^6.1.0", "@popperjs/core": "^2.11.8", - "@types/react-transition-group": "^4.4.10", - "clsx": "^2.1.0", + "@types/react-transition-group": "^4.4.11", + "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1", "react-is": "^18.3.1", "react-transition-group": "^4.4.5" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", @@ -5023,9 +5088,10 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "@mui/material-pigment-css": "^6.1.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -5034,6 +5100,9 @@ "@emotion/styled": { "optional": true }, + "@mui/material-pigment-css": { + "optional": true + }, "@types/react": { "optional": true } @@ -5155,8 +5224,7 @@ "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "license": "(MIT AND Zlib)" + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { "version": "1.1.11", @@ -5206,14 +5274,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -5262,20 +5322,6 @@ "node": ">= 18" } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@react-spring/web": { "version": "9.7.4", "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.4.tgz", @@ -5314,7 +5360,6 @@ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "deprecated": "This package is no longer supported.", - "license": "ISC", "dependencies": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -5362,8 +5407,7 @@ "node_modules/jszip/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { "version": "3.1.2", @@ -5474,13 +5518,12 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.7.tgz", - "integrity": "sha512-m6EBqrskeMUzykBrv0fDX/28lWIBGhMzOYaStp0ihkjzIYJiKUOzVYD1gULHc8XDf5EMSqoH/0/TRAgXqpQwmw==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.9.tgz", + "integrity": "sha512-0HNulLWpKTB7H5BhHCkEhcRAnWUHeAYCftrrGw3QC18+ZywTdAoPv/zEqKy/0adqt+ks4JDdlgSQ1lNKOKjo0A==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -5521,22 +5564,21 @@ } }, "node_modules/@mui/x-data-grid-premium": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid-premium/-/x-data-grid-premium-7.15.0.tgz", - "integrity": "sha512-tD6mmOl4R0I3hK1lIaQMym3WEjMUAe4m7yRGE+eu2QQCjk62tfP57lPmDvdmrj6Dlqb4t5hKTpEgKgOGjWQkRA==", - "license": "SEE LICENSE IN LICENSE", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid-premium/-/x-data-grid-premium-7.16.0.tgz", + "integrity": "sha512-KkUINGc2ZEtuAH8AaxO/2bxY6Y2z/0Ewa4lg+BYt86WcX46vamjiBcmdhtw3w3R7MEakJqETDJPMUMldNQBzdQ==", "dependencies": { - "@babel/runtime": "^7.25.4", + "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6", - "@mui/x-data-grid": "7.15.0", - "@mui/x-data-grid-pro": "7.15.0", - "@mui/x-internals": "7.15.0", - "@mui/x-license": "7.15.0", + "@mui/x-data-grid": "7.16.0", + "@mui/x-data-grid-pro": "7.16.0", + "@mui/x-internals": "7.16.0", + "@mui/x-license": "7.16.0", "@types/format-util": "^1.0.4", "clsx": "^2.1.1", "exceljs": "^4.4.0", "prop-types": "^15.8.1", - "reselect": "^4.1.8" + "reselect": "^5.1.1" }, "engines": { "node": ">=14.0.0" @@ -5596,8 +5638,7 @@ "node_modules/listenercount": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "license": "ISC" + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==" }, "node_modules/@popperjs/core": { "version": "2.11.8", @@ -5657,6 +5698,20 @@ "node": ">=6" } }, + "node_modules/lru.min": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.0.tgz", + "integrity": "sha512-86xXMB6DiuKrTqkE/lRL0drlNh568awttBPJ7D66fzDHpy6NC5r3N+Ly/lKCS2zjmeGyvFDx670z0cD0PVBwGA==", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", @@ -5739,7 +5794,6 @@ "version": "4.3.6", "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz", "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==", - "license": "MIT", "dependencies": { "@fast-csv/format": "4.3.5", "@fast-csv/parse": "4.3.6" @@ -5765,7 +5819,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "license": "MIT", "dependencies": { "immediate": "~3.0.5" } @@ -5860,7 +5913,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -5902,7 +5954,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", - "license": "MIT", "dependencies": { "archiver-utils": "^2.1.0", "async": "^3.2.4", @@ -5917,13 +5968,12 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.7.tgz", - "integrity": "sha512-BiSY5umlx9ed5RQDoHcdbuKTUkuFORDqzYKPHlLeS+STUWQKWziVOn3Ic41LuTBvqE0TRJPKpio9GSIblNR+0w==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.9.tgz", + "integrity": "sha512-IcW9dynWDjMK/0M05E3zopbRen7v0/yEaMZbHFOSS1J/w+8YG3jKywOGZWNp/eCUVtUUXs0PW+7Lpz8uLu+KQA==", "cpu": [ "ia32" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -6296,7 +6346,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" }, @@ -6442,7 +6491,6 @@ "version": "4.3.6", "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz", "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==", - "license": "MIT", "dependencies": { "@types/node": "^14.0.1", "lodash.escaperegexp": "^4.1.2", @@ -6921,10 +6969,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "license": "Apache-2.0", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7304,15 +7351,6 @@ "node": ">=8" } }, - "node_modules/mysql2/node_modules/lru-cache": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", - "license": "ISC", - "engines": { - "node": ">=16.14" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -7357,7 +7395,6 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "license": "MIT", "engines": { "node": ">=14.14" } @@ -7397,7 +7434,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "license": "MIT", "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -7600,7 +7636,6 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "license": "MIT/X11", "engines": { "node": "*" } @@ -7845,7 +7880,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "license": "MIT", "dependencies": { "glob": "^7.1.4", "graceful-fs": "^4.2.0", @@ -7952,10 +7986,9 @@ } }, "node_modules/@types/node": { - "version": "22.5.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.3.tgz", - "integrity": "sha512-njripolh85IA9SQGTAqbmnNZTdxv7X/4OYGPz8tgy5JDr8MP+uDBa921GpYEoDDnwm0Hmn5ZPeJgiiSTPoOzkQ==", - "license": "MIT", + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", "dependencies": { "undici-types": "~6.19.2" } @@ -8044,6 +8077,35 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "license": "MIT" }, + "node_modules/@mui/private-theming/node_modules/@mui/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-oT8ZzMISRUhTVpdbYzY0CgrCBb3t/YEdcaM13tUnuTjZ15pdA6g5lx15ZJUdgYXV6PbJdw7tDQgMEr4uXK5TXQ==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/types": "^7.2.16", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/object.groupby": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", @@ -8103,24 +8165,23 @@ } }, "node_modules/@mui/icons-material": { - "version": "5.16.7", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.7.tgz", - "integrity": "sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==", - "license": "MIT", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-6.1.0.tgz", + "integrity": "sha512-HxfB0jxwiMTYMN8gAnYn3avbF1aDrqBEuGIj6JDQ3YkLl650E1Wy8AIhwwyP47wdrv0at9aAR0iOO6VLb74A9w==", "dependencies": { - "@babel/runtime": "^7.23.9" + "@babel/runtime": "^7.25.6" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@mui/material": "^5.0.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@mui/material": "^6.1.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -8174,16 +8235,15 @@ } }, "node_modules/@uiw/react-codemirror": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.23.0.tgz", - "integrity": "sha512-MnqTXfgeLA3fsUUQjqjJgemEuNyoGALgsExVm0NQAllAAi1wfj+IoKFeK+h3XXMlTFRCFYOUh4AHDv0YXJLsOg==", - "license": "MIT", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.23.2.tgz", + "integrity": "sha512-MmFL6P5V1Mr81JLkJyWNedfxENKdRhsvyU7Izji9wp337m8dqRAz7rCF5XWarGKx+iQ7q2H5ryl07nLqKLSvtQ==", "dependencies": { "@babel/runtime": "^7.18.6", "@codemirror/commands": "^6.1.0", "@codemirror/state": "^6.1.1", "@codemirror/theme-one-dark": "^6.0.0", - "@uiw/codemirror-extensions-basic-setup": "4.23.0", + "@uiw/codemirror-extensions-basic-setup": "4.23.2", "codemirror": "^6.0.0" }, "funding": { @@ -8382,13 +8442,12 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.7.tgz", - "integrity": "sha512-PGbONHIVIuzWlYmLvuFKcj+8jXnLbx4WrlESYlVnEzDsa3+Q2hI1YHoXaSmbq0k4ZwZ7J6sWNV4UZfx1OeOlbQ==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.9.tgz", + "integrity": "sha512-p/v6XlOdrk06xfN9z4evLNBqftVQUWiyduQczCwSj7hNh8fWTbzdVxsEiNOcajMXJbQiaX/ZzZdFgKVmmJnnGQ==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -8418,7 +8477,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -8475,17 +8533,16 @@ "license": "MIT" }, "node_modules/@mui/x-data-grid": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.15.0.tgz", - "integrity": "sha512-S7FLp+SUz/fo+JAQcM4npnL70tGnL4qcYYMkjK4tPkPLrTnBWlm47D5OoGNzpPO1CnOAryFR5h0rdwbeHZmAWg==", - "license": "MIT", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.16.0.tgz", + "integrity": "sha512-71ZyffTeF8RPa399UkMlUbQ8T70kOrUK3fBXfinnal4mwgISlKwBN8EHNZZhyxSQ4vpWs3wHrHZ6MGQeXNUhJQ==", "dependencies": { - "@babel/runtime": "^7.25.4", + "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6", - "@mui/x-internals": "7.15.0", + "@mui/x-internals": "7.16.0", "clsx": "^2.1.1", "prop-types": "^15.8.1", - "reselect": "^4.1.8" + "reselect": "^5.1.1" }, "engines": { "node": ">=14.0.0" @@ -8595,17 +8652,16 @@ } }, "node_modules/mysql2": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.0.tgz", - "integrity": "sha512-J9phbsXGvTOcRVPR95YedzVSxJecpW5A5+cQ57rhHIFXteTP10HCs+VBjS7DHIKfEaI1zQ5tlVrquCd64A6YvA==", - "license": "MIT", + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.2.tgz", + "integrity": "sha512-3jhjAk4NHs3rcKjOiFTqmU76kdib/KDOC+lshrYa76QWkcfF1GbYGK4d5PqPljVmIAc0ChozCRmeYIlNp5bz5w==", "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.6.3", "long": "^5.2.1", - "lru-cache": "^8.0.0", + "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" @@ -8752,21 +8808,12 @@ "x64" ], "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, "node_modules/https-proxy-agent": { @@ -9031,7 +9078,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "license": "MIT", "dependencies": { "buffers": "~0.1.1", "chainsaw": "~0.1.0" @@ -9212,7 +9258,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "license": "MIT", "dependencies": { "once": "^1.4.0" } @@ -9249,10 +9294,9 @@ } }, "node_modules/react-joyride/node_modules/type-fest": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.0.tgz", - "integrity": "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw==", - "license": "(MIT OR CC0-1.0)", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "engines": { "node": ">=16" }, @@ -9396,20 +9440,6 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, - "node_modules/jest-resolve/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -9459,21 +9489,20 @@ } }, "node_modules/@mui/lab": { - "version": "5.0.0-alpha.173", - "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.173.tgz", - "integrity": "sha512-Gt5zopIWwxDgGy/MXcp6GueD84xFFugFai4hYiXY0zowJpTVnIrTQCQXV004Q7rejJ7aaCntX9hpPJqCrioshA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/base": "5.0.0-beta.40", - "@mui/system": "^5.16.5", - "@mui/types": "^7.2.15", - "@mui/utils": "^5.16.5", - "clsx": "^2.1.0", + "version": "6.0.0-beta.9", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.0-beta.9.tgz", + "integrity": "sha512-rgwgf9mNUpXxPlI3tnM3i+HNAtDZ2amAollDqbe6RZ/3fltcir/o/0zBvnZRkJIBOAk6qIGmL59GCasuQQtPKA==", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@mui/base": "5.0.0-beta.58", + "@mui/system": "^6.0.2", + "@mui/types": "^7.2.16", + "@mui/utils": "^6.0.2", + "clsx": "^2.1.1", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", @@ -9482,10 +9511,11 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@mui/material": ">=5.15.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "@mui/material": "^6.0.2", + "@mui/material-pigment-css": "^6.0.2", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -9494,6 +9524,9 @@ "@emotion/styled": { "optional": true }, + "@mui/material-pigment-css": { + "optional": true + }, "@types/react": { "optional": true } @@ -9566,8 +9599,7 @@ "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "license": "MIT" + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" }, "node_modules/ms": { "version": "2.1.2", @@ -9619,13 +9651,12 @@ "license": "BlueOak-1.0.0" }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.7.tgz", - "integrity": "sha512-UhZGcOyI9LE/tZL3h9rs/2wMZaaJKwnpAyegUVDGZqwsla6hMfeSj9ssBWQS9yA4UXun3pPhrFLVnw5KXZs3vw==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.9.tgz", + "integrity": "sha512-/kfQifl3uLYi3DlwFlzCkgxe6fprJNLzzTUFknq3M5wGYicDIbdGlxUl6oHpVLJpBB/CBY3Y//gO6alz/K4NWA==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -9789,20 +9820,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -10030,17 +10047,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -10152,8 +10158,7 @@ "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "license": "MIT" + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" }, "node_modules/babel-preset-current-node-syntax": { "version": "1.1.0", @@ -10527,8 +10532,7 @@ "node_modules/lodash.groupby": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", - "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==", - "license": "MIT" + "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==" }, "node_modules/which-boxed-primitive": { "version": "1.0.2", @@ -10549,8 +10553,7 @@ "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "license": "MIT" + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" }, "node_modules/@jest/console/node_modules/slash": { "version": "3.0.0", @@ -11317,7 +11320,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", - "license": "MIT", "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^3.4.0" @@ -11558,8 +11560,7 @@ "node_modules/lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "license": "MIT" + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" }, "node_modules/pkg-dir": { "version": "4.2.0", @@ -11669,10 +11670,9 @@ } }, "node_modules/@uiw/codemirror-extensions-basic-setup": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.23.0.tgz", - "integrity": "sha512-+k5nkRpUWGaHr1JWT8jcKsVewlXw5qBgSopm9LW8fZ6KnSNZBycz8kHxh0+WSvckmXEESGptkIsb7dlkmJT/hQ==", - "license": "MIT", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.23.2.tgz", + "integrity": "sha512-eacivkj7wzskl2HBYs4rfN0CbYlsSQh5ADtOYWTpc8Txm4ONw8RTi4/rxF6Ks2vdaovizewU5QaHximbxoNTrw==", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", @@ -11769,13 +11769,12 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.7.tgz", - "integrity": "sha512-2xoWtE13sUJ3qrC1lwE/HjbDPm+kBQYFkkiVECJWctRASAHQ+NwjMzgrfqqMYHfMxFb5Wws3w9PqzZJqKFdWcQ==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.9.tgz", + "integrity": "sha512-tS5eqwsp2nO7mzywRUuFYmefNZsUKM/mTG3exK2jIHv9TEVklE1SByB1KMhFkqlit1PxS9YK1tV8BOV90Wpbrw==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -11885,8 +11884,7 @@ "node_modules/@fast-csv/format/node_modules/@types/node": { "version": "14.18.63", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", - "license": "MIT" + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -11972,7 +11970,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -12416,7 +12413,6 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -12469,7 +12465,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -12723,7 +12718,6 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -12931,8 +12925,7 @@ "node_modules/lodash.isfunction": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", - "license": "MIT" + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" }, "node_modules/lilconfig": { "version": "2.1.0", @@ -12953,12 +12946,11 @@ } }, "node_modules/@playwright/test": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.1.tgz", - "integrity": "sha512-Fq6SwLujA/DOIvNC2EL/SojJnkKf/rAwJ//APpJJHRyMi1PdKrY3Az+4XNQ51N4RTbItbIByQ0jgd1tayq1aeA==", - "license": "Apache-2.0", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", + "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", "dependencies": { - "playwright": "1.46.1" + "playwright": "1.47.0" }, "bin": { "playwright": "cli.js" @@ -12984,20 +12976,19 @@ "license": "MIT" }, "node_modules/@mui/x-data-grid-pro": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid-pro/-/x-data-grid-pro-7.15.0.tgz", - "integrity": "sha512-Av33eHCyuW+qD4oBvS8ncTv02xdjCSal+9md/XWECgjcJ11wBqeqrdCueA5AYC8+kqvhbyL72GJStylm0vf4qw==", - "license": "SEE LICENSE IN LICENSE", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid-pro/-/x-data-grid-pro-7.16.0.tgz", + "integrity": "sha512-LsasvW7tR0aQTdiYlN14PDyhFjVxKn4qRDSOp6srhv/udzzxjgTiZ3+MEO3xAUkH24w3OIpATca2LgMlfMSsMg==", "dependencies": { - "@babel/runtime": "^7.25.4", + "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6", - "@mui/x-data-grid": "7.15.0", - "@mui/x-internals": "7.15.0", - "@mui/x-license": "7.15.0", + "@mui/x-data-grid": "7.16.0", + "@mui/x-internals": "7.16.0", + "@mui/x-license": "7.16.0", "@types/format-util": "^1.0.4", "clsx": "^2.1.1", "prop-types": "^15.8.1", - "reselect": "^4.1.8" + "reselect": "^5.1.1" }, "engines": { "node": ">=14.0.0" @@ -13052,11 +13043,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/react-floater/node_modules/@gilbarbara/deep-equal": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.1.2.tgz", - "integrity": "sha512-jk+qzItoEb0D0xSSmrKDDzf9sheQj/BAPxlgNxgmOaA3mxpUa6ndJLYGZKsJnIVEQSD8zcTbyILz7I0HcnBCRA==" - }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", @@ -13070,13 +13056,12 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.7.tgz", - "integrity": "sha512-ys2cUgZYRc+CbyDeLAaAdZgS7N1Kpyy+wo0b/gAj+SeOeaj0Lw/q+G1hp+DuDiDAVyxLBCJXEY/AkhDmtihUTA==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.9.tgz", + "integrity": "sha512-tK/RyhCmOCiXQ9IVdFrBbZOf4/1+0RSuJkebXU2uMEsusS51TjIJO4l8ZmEijH9gZa0pJClvmApRHi7JuBqsRw==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -13117,6 +13102,35 @@ "url": "https://opencollective.com/preact" } }, + "node_modules/@mui/lab/node_modules/@mui/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-oT8ZzMISRUhTVpdbYzY0CgrCBb3t/YEdcaM13tUnuTjZ15pdA6g5lx15ZJUdgYXV6PbJdw7tDQgMEr4uXK5TXQ==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/types": "^7.2.16", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@img/sharp-linuxmusl-x64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", @@ -13251,20 +13265,6 @@ "node": ">= 0.6" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@emotion/utils": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", @@ -13281,10 +13281,9 @@ } }, "node_modules/reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", - "license": "MIT" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" }, "node_modules/cliui": { "version": "8.0.1", @@ -13584,7 +13583,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", - "license": "MIT", "dependencies": { "archiver-utils": "^3.0.4", "compress-commons": "^4.1.2", @@ -13677,10 +13675,9 @@ } }, "node_modules/node-mocks-http": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.15.1.tgz", - "integrity": "sha512-X/GpUpNNiPDYUeUD183W8V4OW6OHYWI29w/QDyb+c/GzOfVEAlo6HjbW9++eXT2aV2lGg+uS+XqTD2q0pNREQA==", - "license": "MIT", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.16.0.tgz", + "integrity": "sha512-jmDjsr87ugnZ4nqBeX8ccMB1Fn04qc5Fz45XgrneJerWGV0VqS+wpu/zVkwv8LDAYHljDy5FzNvRJaOzEW9Dyw==", "dependencies": { "@types/express": "^4.17.21", "@types/node": "*", @@ -13792,13 +13789,12 @@ } }, "node_modules/@mui/x-data-grid-generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@mui/x-data-grid-generator/-/x-data-grid-generator-7.15.0.tgz", - "integrity": "sha512-WFAnCO8bQPzT6XCtiNR7VwWKfTkQkLszHeRnk3vW+nBtLfo/JNDyA4gu2zLS4qLHbQ2pDacFxdmMH6gHJ/jCMw==", - "license": "UNLICENSED", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid-generator/-/x-data-grid-generator-7.16.0.tgz", + "integrity": "sha512-cYLPBChpzWKerGfNBuz00W4kvxkYMz6KFoM+CQgALADRVeKjy4nHjFFu8Acrq+1QqM+NRKjbLlm6dmuWMh3HOg==", "dependencies": { - "@babel/runtime": "^7.25.4", - "@mui/x-data-grid-premium": "7.15.0", + "@babel/runtime": "^7.25.6", + "@mui/x-data-grid-premium": "7.16.0", "chance": "^1.1.12", "clsx": "^2.1.1", "lru-cache": "^10.4.3" @@ -13852,8 +13848,7 @@ "node_modules/lodash.escaperegexp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", - "license": "MIT" + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==" }, "node_modules/has-proto": { "version": "1.0.3", @@ -14345,7 +14340,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "license": "MIT/X11", "dependencies": { "traverse": ">=0.3.0 <0.4" }, @@ -14357,7 +14351,6 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -14423,22 +14416,21 @@ } }, "node_modules/@mui/system": { - "version": "5.16.7", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz", - "integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.16.6", - "@mui/styled-engine": "^5.16.6", - "@mui/types": "^7.2.15", - "@mui/utils": "^5.16.6", - "clsx": "^2.1.0", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.1.0.tgz", + "integrity": "sha512-NumkGDqT6EdXfcoFLYQ+M4XlTW5hH3+aK48xAbRqKPXJfxl36CBt4DLduw/Voa5dcayGus9T6jm1AwU2hoJ5hQ==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/private-theming": "^6.1.0", + "@mui/styled-engine": "^6.1.0", + "@mui/types": "^7.2.16", + "@mui/utils": "^6.1.0", + "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", @@ -14447,8 +14439,8 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -14788,7 +14780,6 @@ "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -14875,8 +14866,7 @@ "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", @@ -14937,7 +14927,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "license": "MIT", "engines": { "node": ">=0.10" } @@ -15089,12 +15078,11 @@ } }, "node_modules/@mui/x-internals": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.15.0.tgz", - "integrity": "sha512-Q/IZvZhHpe64Ost1mRbdp6ML8KQQBprwwgzqo6pZbrCaWMPB2gk2jcUwdCwnLsc+gutaEPVhZ8N7it8VZcHtbg==", - "license": "MIT", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.16.0.tgz", + "integrity": "sha512-ijer5XYmWlJqWaTmF6TGH1odG7EAupv8iDWYmDm2yVR9IQ+L2nQSuhiFClI+wmGx40KS2VKOlzDMPpF0t7/HCg==", "dependencies": { - "@babel/runtime": "^7.25.4", + "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6" }, "engines": { @@ -15378,10 +15366,9 @@ } }, "node_modules/react-joyride": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/react-joyride/-/react-joyride-2.8.2.tgz", - "integrity": "sha512-2QY8HB1G0I2OT0PKMUz7gg2HAjdkG2Bqi13r0Bb1V16PAwfb9khn4wWBTOJsGsjulbAWiQ3/0YrgNUHGFmuifw==", - "license": "MIT", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/react-joyride/-/react-joyride-2.9.1.tgz", + "integrity": "sha512-JYlM3uWbet3yPWpToPFOYyAdjAZxa0MUZYpKX/rjCm73Lj/Cyy1Lecul4Hfw/vPhYrpXhbYnR1x+DGamtWjfZQ==", "dependencies": { "@gilbarbara/deep-equal": "^0.3.1", "deep-diff": "^1.0.2", @@ -15393,7 +15380,7 @@ "scroll": "^3.0.1", "scrollparent": "^2.1.0", "tree-changes": "^0.11.2", - "type-fest": "^4.18.2" + "type-fest": "^4.26.1" }, "peerDependencies": { "react": "15 - 18", @@ -15401,12 +15388,11 @@ } }, "node_modules/next": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.7.tgz", - "integrity": "sha512-4Qy2aK0LwH4eQiSvQWyKuC7JXE13bIopEQesWE0c/P3uuNRnZCQanI0vsrMLmUQJLAto+A+/8+sve2hd+BQuOQ==", - "license": "MIT", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.9.tgz", + "integrity": "sha512-3CzBNo6BuJnRjcQvRw+irnU1WiuJNZEp+dkzkt91y4jeIDN/Emg95F+takSYiLpJ/HkxClVQRyqiTwYce5IVqw==", "dependencies": { - "@next/env": "14.2.7", + "@next/env": "14.2.9", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -15421,15 +15407,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.7", - "@next/swc-darwin-x64": "14.2.7", - "@next/swc-linux-arm64-gnu": "14.2.7", - "@next/swc-linux-arm64-musl": "14.2.7", - "@next/swc-linux-x64-gnu": "14.2.7", - "@next/swc-linux-x64-musl": "14.2.7", - "@next/swc-win32-arm64-msvc": "14.2.7", - "@next/swc-win32-ia32-msvc": "14.2.7", - "@next/swc-win32-x64-msvc": "14.2.7" + "@next/swc-darwin-arm64": "14.2.9", + "@next/swc-darwin-x64": "14.2.9", + "@next/swc-linux-arm64-gnu": "14.2.9", + "@next/swc-linux-arm64-musl": "14.2.9", + "@next/swc-linux-x64-gnu": "14.2.9", + "@next/swc-linux-x64-musl": "14.2.9", + "@next/swc-win32-arm64-msvc": "14.2.9", + "@next/swc-win32-ia32-msvc": "14.2.9", + "@next/swc-win32-x64-msvc": "14.2.9" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -15607,11 +15593,6 @@ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "license": "MIT" }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -15816,25 +15797,24 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", - "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", - "license": "MIT", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.0.tgz", + "integrity": "sha512-+L5qccs4gwsR0r1dgjqhN24QEQRkqIbfOdxILyMbMkuI50x6wNyt9XrV+J3WtjtZTMGJCrUa5VmZBE6OEPGPWA==", "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.16.6", + "@babel/runtime": "^7.25.6", + "@mui/utils": "^6.1.0", "prop-types": "^15.8.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -16022,7 +16002,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -16106,13 +16085,12 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.7.tgz", - "integrity": "sha512-+zJ1gJdl35BSAGpkCbfyiY6iRTaPrt3KTl4SF/B1NyELkqqnrNX6cp4IjjjxKpd64/7enI0kf6b9O1Uf3cL0pw==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.9.tgz", + "integrity": "sha512-8svpeTFNAMTUMKQbEzE8qRAwl9o7mNBv7LR1bmSkQvo1oy4WrNyZbhWsldOiKrc4mZ5dfQkGYsI9T75mIFMfeA==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -16265,13 +16243,12 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.7.tgz", - "integrity": "sha512-pxsI23gKWRt/SPHFkDEsP+w+Nd7gK37Hpv0ngc5HpWy2e7cKx9zR/+Q2ptAUqICNTecAaGWvmhway7pj/JLEWA==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.9.tgz", + "integrity": "sha512-gcbpoXyWZdVOBgNa5BRzynrL5UR1nb2ZT38yKgnphYU9UHjeecnylMHntrQiMg/QtONDcJPFC/PmsS47xIRYoA==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -16421,8 +16398,7 @@ "node_modules/lodash.difference": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "license": "MIT" + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==" }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -16512,8 +16488,7 @@ "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "license": "MIT" + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" }, "node_modules/react-dropzone": { "version": "14.2.3", @@ -16728,7 +16703,6 @@ "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "license": "Unlicense", "engines": { "node": ">=0.6" } @@ -16926,11 +16900,19 @@ "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "license": "ISC" }, + "node_modules/@mui/material/node_modules/@mui/core-downloads-tracker": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.0.tgz", + "integrity": "sha512-covEnIn/2er5YdtuukDRA52kmARhKrHjOvPsyTFMQApZdrTBI4h8jbEy2mxZqwMwcAFS9coonQXnEZKL1rUNdQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, "node_modules/exceljs/node_modules/compress-commons": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", - "license": "MIT", "dependencies": { "buffer-crc32": "^0.2.13", "crc32-stream": "^4.0.2", @@ -17179,10 +17161,9 @@ } }, "node_modules/@next/bundle-analyzer": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-14.2.7.tgz", - "integrity": "sha512-Zz55BLjoNKiUjr8PJIMTXFQnbUEpk8qkXP5nmEcXvOorbruQOIdmkRa3sahlJZPWTjsZNpxwImhZf2yFMVMWeg==", - "license": "MIT", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-14.2.9.tgz", + "integrity": "sha512-r+h5vdrx3+tZoMysJmDsfy3OXPqwuTTiQYytCPl5qfngHqeusV3im8Bjbmm4ZsOsIcqh/BQrChO8u7wFXavHKA==", "dependencies": { "webpack-bundle-analyzer": "4.10.1" } @@ -17301,7 +17282,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "license": "MIT", "engines": { "node": "*" } @@ -17407,8 +17387,7 @@ "node_modules/lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "license": "MIT" + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" }, "node_modules/has-flag": { "version": "4.0.0", @@ -17586,13 +17565,12 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.7.tgz", - "integrity": "sha512-gUu0viOMvMlzFRz1r1eQ7Ql4OE+hPOmA7smfZAhn8vC4+0swMZaZxa9CSIozTYavi+bJNDZ3tgiSdMjmMzRJlQ==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.9.tgz", + "integrity": "sha512-hhVFViPHLAVUJRNtwwm609p9ozWajOmRvzOZzzKXgiVGwx/CALxlMUeh+M+e0Zj6orENhWLZeilOPHpptuENsA==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -17812,7 +17790,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", - "license": "MIT", "dependencies": { "glob": "^7.2.3", "graceful-fs": "^4.2.0", @@ -18013,6 +17990,66 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "license": "MIT" }, + "node_modules/@mui/joy/node_modules/@mui/styled-engine": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", + "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/lab/node_modules/@mui/base/node_modules/@mui/utils": { + "version": "6.0.0-rc.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.0.0-rc.0.tgz", + "integrity": "sha512-tBp0ILEXDL0bbDDT8PnZOjCqSm5Dfk2N0Z45uzRw+wVl6fVvloC9zw8avl+OdX1Bg3ubs/ttKn8nRNv17bpM5A==", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/yoctocolors": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", @@ -18061,7 +18098,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -18133,8 +18169,36 @@ "node_modules/jszip/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/@mui/material/node_modules/@mui/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-oT8ZzMISRUhTVpdbYzY0CgrCBb3t/YEdcaM13tUnuTjZ15pdA6g5lx15ZJUdgYXV6PbJdw7tDQgMEr4uXK5TXQ==", + "dependencies": { + "@babel/runtime": "^7.25.6", + "@mui/types": "^7.2.16", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } } } } \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 3377b229..10613781 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,18 +28,18 @@ "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", "@mui/base": "^5.0.0-beta.40", - "@mui/icons-material": "^5.16.7", + "@mui/icons-material": "^6.1.0", "@mui/joy": "^5.0.0-beta.48", - "@mui/lab": "^5.0.0-alpha.173", - "@mui/material": "^5.16.7", - "@mui/system": "^5.16.7", - "@mui/x-data-grid": "^7.14.0", - "@mui/x-data-grid-generator": "^7.14.0", - "@mui/x-date-pickers": "^7.14.0", - "@next/bundle-analyzer": "^14.2.6", + "@mui/lab": "^6.0.0-beta.9", + "@mui/material": "^6.1.0", + "@mui/system": "^6.1.0", + "@mui/x-data-grid": "^7.16.0", + "@mui/x-data-grid-generator": "^7.16.0", + "@mui/x-date-pickers": "^7.16.0", + "@next/bundle-analyzer": "^14.2.9", "@next/eslint-plugin-next": "^14.2.6", "@octokit/types": "^13.5.0", - "@playwright/test": "^1.46.1", + "@playwright/test": "^1.47.0", "@popperjs/core": "^2.11.8", "@react-spring/web": "^9.7.4", "@testing-library/jest-dom": "^6.5.0", @@ -47,14 +47,14 @@ "@types/codemirror": "^5.60.15", "@types/file-saver": "^2.0.7", "@types/jest": "^29.5.12", - "@types/node": "^22.5.0", + "@types/node": "^22.5.4", "@types/papaparse": "^5.3.14", - "@types/react": "^18.3.4", + "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", "@types/react-dropzone": "^5.1.0", "@types/supertest": "^6.0.2", "@typescript-eslint/eslint-plugin": "^7.18.0", - "@uiw/react-codemirror": "^4.23.0", + "@uiw/react-codemirror": "^4.23.2", "@vitejs/plugin-react": "^4.3.1", "@vitejs/plugin-react-swc": "^3.7.0", "abort-controller": "^3.0.0", @@ -79,12 +79,12 @@ "jest-mock": "^29.7.0", "jsdom": "^25.0.0", "moment": "^2.30.1", - "mysql2": "^3.11.0", + "mysql2": "^3.11.2", "net": "^1.0.2", - "next": "^14.2.6", + "next": "^14.2.9", "next-auth": "^4.24.7", "node-cron": "^3.0.3", - "node-mocks-http": "^1.15.1", + "node-mocks-http": "^1.16.0", "notistack": "^3.0.1", "npm-force-resolutions": "^0.0.10", "octokit": "^4.0.2", @@ -93,7 +93,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-dropzone": "^14.2.3", - "react-joyride": "^2.8.2", + "react-joyride": "^2.9.1", "react-markdown": "^9.0.1", "reflect-metadata": "^0.2.2", "remark-gfm": "^4.0.0", @@ -104,7 +104,7 @@ "tailwindcss": "^3.4.10", "tls": "^0.0.1", "ts-node": "^10.9.2", - "typescript": "^5.5.4", + "typescript": "^5.6.2", "unzipper": "^0.12.3", "use-count-up": "^3.0.1", "vitest": "^2.0.5"