Skip to content

Commit

Permalink
extensive core schema changes. Triggers and changelog system implemen…
Browse files Browse the repository at this point in the history
…ted across the board to address need for non-duplicative update system -- users will be iteratively updating rows as they complete a census. B/c of this, makign rows immutable will cause too much duplication. In place of this, the changelog system has been implemented.
  • Loading branch information
siddheshraze committed Jul 1, 2024
1 parent 5c324be commit 20c5426
Show file tree
Hide file tree
Showing 15 changed files with 368 additions and 306 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# dependencies
/node_modules
/liquibase
/.pnp
.pnp.js
/.idea/*
Expand Down Expand Up @@ -49,3 +50,4 @@ next-env.d.ts
/frontend/.vscode
/documentation/.obsidian
/documentation/.obsidian/*
frontend/liquibase/
52 changes: 35 additions & 17 deletions frontend/components/datagrids/applications/quadratsdatagrid.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
"use client";
import {GridRowModes, GridRowModesModel, GridRowsProp} from "@mui/x-data-grid";
import {AlertProps} from "@mui/material";
import React, { useState} from "react";
import {QuadratsGridColumns as BaseQuadratsGridColumns, initialQuadratRDSRow} from '@/config/sqlrdsdefinitions/tables/quadratrds';
import { GridRowModes, GridRowModesModel, GridRowsProp } from "@mui/x-data-grid";
import { AlertProps } from "@mui/material";
import React, { useState } from "react";
import { initialQuadratRDSRow, QuadratsGridColumnSet } from '@/config/sqlrdsdefinitions/tables/quadratrds';
import { useOrgCensusContext, usePlotContext, } from "@/app/contexts/userselectionprovider";
import {randomId} from "@mui/x-data-grid-generator";
import { randomId } from "@mui/x-data-grid-generator";
import DataGridCommons from "@/components/datagrids/datagridcommons";
import {Box, Button, Typography} from "@mui/joy";
import {useSession} from "next-auth/react";
import { Box, Button, Stack, Typography } from "@mui/joy";
import { useSession } from "next-auth/react";
import UploadParentModal from "@/components/uploadsystemhelpers/uploadparentmodal";
import Link from 'next/link';
import { GridColDef } from "@mui/x-data-grid";
import { unitSelectionOptions } from "@/config/macros";

export default function QuadratsDataGrid() {
const [rows, setRows] = React.useState([initialQuadratRDSRow] as GridRowsProp);
Expand All @@ -26,13 +28,29 @@ export default function QuadratsDataGrid() {
});
const [isNewRowAdded, setIsNewRowAdded] = useState<boolean>(false);
const [shouldAddRowAfterFetch, setShouldAddRowAfterFetch] = useState(false);
const {data: session} = useSession();
const { data: session } = useSession();
const [isUploadModalOpen, setIsUploadModalOpen] = useState(false);
const [uploadFormType, setUploadFormType] = useState<'quadrats'>('quadrats');
const [a, b] = QuadratsGridColumnSet;

const currentPlot = usePlotContext();
const currentCensus = useOrgCensusContext();

const quadratsUnitColumn: GridColDef = {
field: 'unit',
headerName: 'Unit',
headerClassName: 'header',
flex: 0.3,
renderHeader: () => <Stack direction={'column'} sx={{ alignItems: 'center', justifyContent: 'center' }}>
<Typography level='body-sm' fontWeight={'xl'}>Quadrat</Typography>
<Typography level='body-xs'>Units</Typography>
</Stack>,
align: 'center',
editable: true,
type: 'singleSelect',
valueOptions: unitSelectionOptions
}

const addNewRowToGrid = () => {
const id = randomId();
const nextQuadratID = (rows.length > 0
Expand All @@ -51,12 +69,12 @@ export default function QuadratsDataGrid() {
// Set editing mode for the new row
setRowModesModel(oldModel => ({
...oldModel,
[id]: {mode: GridRowModes.Edit, fieldToFocus: 'quadratName'},
[id]: { mode: GridRowModes.Edit, fieldToFocus: 'quadratName' },
}));
};
return (
<>
<Box sx={{display: 'flex', alignItems: 'center', mb: 3, width: '100%'}}>
<Box sx={{ display: 'flex', alignItems: 'center', mb: 3, width: '100%' }}>
<Box sx={{
width: '100%',
display: 'flex',
Expand All @@ -66,16 +84,16 @@ export default function QuadratsDataGrid() {
borderRadius: '4px',
p: 2
}}>
<Box sx={{flexGrow: 1}}>
<Box sx={{ flexGrow: 1 }}>
{session?.user.userStatus !== 'fieldcrew' && (
<Typography level={"title-lg"} sx={{color: "#ffa726"}}>
<Typography level={"title-lg"} sx={{ color: "#ffa726" }}>
Note: ADMINISTRATOR VIEW
</Typography>
)}
<Typography level={"title-md"} sx={{color: "#ffa726"}}>
<Typography level={"title-md"} sx={{ color: "#ffa726" }}>
Note: This is a locked view and will not allow modification.
</Typography>
<Typography level={"body-md"} sx={{color: "#ffa726"}}>
<Typography level={"body-md"} sx={{ color: "#ffa726" }}>
Please use this view as a way to confirm changes made to measurements.
</Typography>
</Box>
Expand All @@ -89,17 +107,17 @@ export default function QuadratsDataGrid() {
</Button>
{/* Link to Quadrat Personnel Data Grid */}
<Link href="/fixeddatainput/quadratpersonnel" passHref>
<Button variant="solid" color="primary" sx={{ml: 2}}>View Quadrat Personnel</Button>
<Button variant="solid" color="primary" sx={{ ml: 2 }}>View Quadrat Personnel</Button>
</Link>
</Box>
</Box>
<UploadParentModal isUploadModalOpen={isUploadModalOpen} handleCloseUploadModal={() => {
setIsUploadModalOpen(false);
setRefresh(true);
}} formType={uploadFormType}/>
}} formType={uploadFormType} />
<DataGridCommons
gridType="quadrats"
gridColumns={BaseQuadratsGridColumns}
gridColumns={[...a, quadratsUnitColumn, ...b]}
rows={rows}
setRows={setRows}
rowCount={rowCount}
Expand Down
18 changes: 13 additions & 5 deletions frontend/components/datagrids/datagridcommons.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { GridActionsCellItem, GridColDef, GridEventListener, GridRowEditStopReasons, GridRowId, GridRowModel, GridRowModes, GridRowModesModel, GridToolbar, GridToolbarContainer, GridToolbarProps, ToolbarPropsOverrides, useGridApiRef, GridCellParams, } from '@mui/x-data-grid';
import { GridActionsCellItem, GridColDef, GridEventListener, GridRowEditStopReasons, GridRowId, GridRowModel, GridRowModes, GridRowModesModel, GridToolbar, GridToolbarContainer, GridToolbarProps, ToolbarPropsOverrides, useGridApiRef, GridCellParams, GridFilterModel, } from '@mui/x-data-grid';
import { Alert, Button, Snackbar, } from '@mui/material';
import AddIcon from '@mui/icons-material/Add';
import EditIcon from '@mui/icons-material/Edit';
Expand All @@ -25,10 +25,10 @@ import ConfirmationDialog from './confirmationdialog';

type EditToolbarProps = EditToolbarCustomProps & GridToolbarProps & ToolbarPropsOverrides;

const EditToolbar = ({ handleAddNewRow, handleRefresh, handleExportAll, locked }: EditToolbarProps) => {
const EditToolbar = ({ handleAddNewRow, handleRefresh, handleExportAll, locked, filterModel }: EditToolbarProps) => {
const handleExportClick = async () => {
if (!handleExportAll) return;
const fullData = await handleExportAll();
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');
Expand Down Expand Up @@ -85,6 +85,7 @@ export default function DataGridCommons(props: Readonly<DataGridCommonProps>) {
const [pendingAction, setPendingAction] = useState<PendingAction>({ actionType: '', actionId: null });
const [promiseArguments, setPromiseArguments] = useState<{ resolve: (value: GridRowModel) => void, reject: (reason?: any) => void, newRow: GridRowModel, oldRow: GridRowModel } | null>(null);
const [isSaveHighlighted, setIsSaveHighlighted] = useState(false);
const [filterModel, setFilterModel] = useState<GridFilterModel>({ items: [] });

const currentPlot = usePlotContext();
const currentCensus = useOrgCensusContext();
Expand Down Expand Up @@ -135,7 +136,11 @@ export default function DataGridCommons(props: Readonly<DataGridCommonProps>) {
const fullDataQuery = `/api/fetchall/${gridType}` + partialQuery + `?schema=${currentSite?.schemaName}`;

try {
const response = await fetch(fullDataQuery, { method: 'GET' });
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;
Expand Down Expand Up @@ -588,6 +593,8 @@ export default function DataGridCommons(props: Readonly<DataGridCommonProps>) {
paginationModel={paginationModel}
rowCount={rowCount}
pageSizeOptions={[paginationModel.pageSize]}
filterModel={filterModel}
onFilterModelChange={(newFilterModel) => setFilterModel(newFilterModel)}
initialState={{
columns: {
columnVisibilityModel: getColumnVisibilityModel(gridType),
Expand All @@ -601,7 +608,8 @@ export default function DataGridCommons(props: Readonly<DataGridCommonProps>) {
locked: locked,
handleAddNewRow: handleAddNewRow,
handleRefresh: handleRefresh,
handleExportAll: fetchFullData
handleExportAll: fetchFullData,
filterModel: filterModel
}
}}
autoHeight
Expand Down
5 changes: 3 additions & 2 deletions frontend/components/datagrids/datagridmacros.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import styled from "@emotion/styled";
import { AlertProps } from "@mui/material";
import { GridColDef, GridRowsProp, GridRowModesModel, GridRowId, GridSortDirection, GridRowModel } from "@mui/x-data-grid";
import { GridColDef, GridRowsProp, GridRowModesModel, GridRowId, GridSortDirection, GridRowModel, GridFilterModel } from "@mui/x-data-grid";
import { Dispatch, SetStateAction } from "react";

export interface EditToolbarCustomProps {
handleAddNewRow?: () => void;
handleRefresh?: () => Promise<void>;
handleExportAll?: () => Promise<void>;
handleExportAll?: (filterModel?: GridFilterModel) => Promise<void>;
filterModel?: GridFilterModel;
locked?: boolean;
}

Expand Down
48 changes: 29 additions & 19 deletions frontend/components/datagrids/msvdatagrid.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { GridActionsCellItem, GridCellParams, GridColDef, GridEventListener, GridRowEditStopReasons, GridRowId, GridRowModel, GridRowModes, GridRowModesModel, GridSortModel, GridToolbar, GridToolbarContainer, GridToolbarProps, GridValidRowModel, ToolbarPropsOverrides} from '@mui/x-data-grid';
import { Alert, Button, Checkbox, FormControlLabel, FormGroup, Snackbar} from '@mui/material';
import { GridActionsCellItem, GridCellParams, GridColDef, GridEventListener, GridFilterModel, GridRowEditStopReasons, GridRowId, GridRowModel, GridRowModes, GridRowModesModel, GridSortModel, GridToolbar, GridToolbarContainer, GridToolbarProps, GridValidRowModel, ToolbarPropsOverrides } from '@mui/x-data-grid';
import { Alert, Button, Checkbox, FormControlLabel, FormGroup, Snackbar } from '@mui/material';
import AddIcon from '@mui/icons-material/Add';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/DeleteOutlined';
Expand All @@ -11,9 +11,9 @@ import RefreshIcon from '@mui/icons-material/Refresh';
import Box from "@mui/joy/Box";
import { Stack, Tooltip, Typography } from "@mui/joy";
import { StyledDataGrid } from "@/config/styleddatagrid";
import { createDeleteQuery, createFetchQuery, createPostPatchQuery, getGridID,} from "@/config/datagridhelpers";
import { createDeleteQuery, createFetchQuery, createPostPatchQuery, getGridID, } from "@/config/datagridhelpers";
import { CMError } from "@/config/macros/uploadsystemmacros";
import { useOrgCensusContext, usePlotContext, useQuadratContext, useSiteContext} from "@/app/contexts/userselectionprovider";
import { useOrgCensusContext, usePlotContext, useQuadratContext, useSiteContext } from "@/app/contexts/userselectionprovider";
import { redirect } from 'next/navigation';
import { CoreMeasurementsRDS } from '@/config/sqlrdsdefinitions/tables/coremeasurementsrds';
import moment from 'moment';
Expand All @@ -33,10 +33,10 @@ import { useSession } from 'next-auth/react';

type EditToolbarProps = EditToolbarCustomProps & GridToolbarProps & ToolbarPropsOverrides;

const EditToolbar = ({ handleAddNewRow, handleRefresh, handleExportAll, handleExportErrors, locked }: EditToolbarProps) => {
const EditToolbar = ({ handleAddNewRow, handleRefresh, handleExportAll, handleExportErrors, locked, filterModel }: EditToolbarProps) => {
const handleExportClick = async () => {
if (!handleExportAll) return;
const fullData = await handleExportAll();
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');
Expand All @@ -49,7 +49,7 @@ const EditToolbar = ({ handleAddNewRow, handleRefresh, handleExportAll, handleEx

const handleExportErrorsClick = async () => {
if (!handleExportErrors) return;
const errorData = await handleExportErrors();
const errorData = await handleExportErrors(filterModel);
const blob = new Blob([JSON.stringify(errorData, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
Expand Down Expand Up @@ -115,6 +115,7 @@ export default function MeasurementSummaryGrid(props: Readonly<MeasurementSummar
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
const [locked, setLocked] = useState(false);
const [promiseArguments, setPromiseArguments] = useState<{ resolve: (value: GridRowModel) => void, reject: (reason?: any) => void, newRow: GridRowModel, oldRow: GridRowModel } | null>(null);
const [filterModel, setFilterModel] = useState<GridFilterModel>({ items: [] });

// custom states -- msvdatagrid
const [deprecatedRows, setDeprecatedRows] = useState<GridValidRowModel[]>([]); // new state to track deprecated rows
Expand Down Expand Up @@ -699,7 +700,7 @@ export default function MeasurementSummaryGrid(props: Readonly<MeasurementSummar
const fullDataQuery = `/api/fetchall/${'measurementssummaryview'}` + partialQuery + `?schema=${currentSite?.schemaName}`;

try {
const response = await fetch(fullDataQuery, { method: 'GET' });
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;
Expand All @@ -719,10 +720,10 @@ export default function MeasurementSummaryGrid(props: Readonly<MeasurementSummar
return { ...row, errors };
});
return formattedErrorRows;
};
};

const modifiedColumns = gridColumns.map(column => {
if (column.field !== 'measurementssummaryview') {
if (column.field !== 'measurementDate') {
return column;
}
return {
Expand Down Expand Up @@ -800,33 +801,42 @@ export default function MeasurementSummaryGrid(props: Readonly<MeasurementSummar
};
const stemUnitsColumn: GridColDef = {
field: 'stemUnits',
headerName: 'U',
headerName: 'Stem Units',
headerClassName: 'header',
flex: 0.4,
renderHeader: () => <Typography level='body-xs'>U</Typography>,
align: 'left',
renderHeader: () => <Stack direction={'column'} sx={{alignItems: 'center', justifyContent: 'center'}}>
<Typography level='body-sm' fontWeight={'xl'}>Stem</Typography>
<Typography level='body-xs'>Units</Typography>
</Stack>,
align: 'center',
editable: true,
type: 'singleSelect',
valueOptions: unitSelectionOptions
};
const dbhUnitsColumn: GridColDef = {
field: 'dbhUnits',
headerName: 'U',
headerName: 'DBH Units',
headerClassName: 'header',
flex: 0.4,
renderHeader: () => <Typography level='body-xs'>U</Typography>,
align: 'left',
renderHeader: () => <Stack direction={'column'} sx={{alignItems: 'center', justifyContent: 'center'}}>
<Typography level='body-sm' fontWeight={'xl'}>DBH</Typography>
<Typography level='body-xs'>Units</Typography>
</Stack>,
align: 'center',
editable: true,
type: 'singleSelect',
valueOptions: unitSelectionOptions
};
const homUnitsColumn: GridColDef = {
field: 'homUnits',
headerName: 'U',
headerName: 'HOM Units',
headerClassName: 'header',
flex: 0.4,
renderHeader: () => <Typography level='body-xs'>U</Typography>,
align: 'left',
renderHeader: () => <Stack direction={'column'} sx={{alignItems: 'center', justifyContent: 'center'}}>
<Typography level='body-sm' fontWeight={'xl'}>HOM</Typography>
<Typography level='body-xs'>Units</Typography>
</Stack>,
align: 'center',
editable: true,
type: 'singleSelect',
valueOptions: unitSelectionOptions
Expand Down
Loading

0 comments on commit 20c5426

Please sign in to comment.