Skip to content

Commit

Permalink
export modal updated and added to isolated datagrid baseline. tested …
Browse files Browse the repository at this point in the history
…to confirm function
  • Loading branch information
siddheshraze committed Jan 29, 2025
1 parent ff7ca20 commit c88d3ed
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 96 deletions.
57 changes: 57 additions & 0 deletions frontend/app/api/clearcensus/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { NextRequest, NextResponse } from 'next/server';
import { HTTPResponses } from '@/config/macros';
import ConnectionManager from '@/config/connectionmanager';

export async function GET(request: NextRequest) {
const schema = request.nextUrl.searchParams.get('schema');
const censusIDParam = request.nextUrl.searchParams.get('censusID');
if (!schema || !censusIDParam) {
return new NextResponse('Missing required parameters', { status: HTTPResponses.SERVICE_UNAVAILABLE });
}
const censusID = parseInt(censusIDParam);
const connectionManager = ConnectionManager.getInstance();
const transactionID = await connectionManager.beginTransaction();
try {
let query = `DELETE FROM ${schema}.cmverrors WHERE CoreMeasurementID IN (SELECT CoreMeasurementID FROM ${schema}.coremeasurements WHERE CensusID = ${censusID});`;
await connectionManager.executeQuery(query);
query = `DELETE FROM ${schema}.cmattributes WHERE CoreMeasurementID IN (SELECT CoreMeasurementID FROM ${schema}.coremeasurements WHERE CensusID = ${censusID});`;
await connectionManager.executeQuery(query);
query = `DELETE FROM ${schema}.coremeasurements WHERE CensusID = ${censusID};`;
await connectionManager.executeQuery(query);
query = `DELETE FROM ${schema}.quadratpersonnel WHERE PersonnelID IN (SELECT PersonnelID FROM ${schema}.personnel WHERE CensusID = ${censusID});`;
await connectionManager.executeQuery(query);
query = `DELETE FROM ${schema}.personnel WHERE CensusID = ${censusID};`;
await connectionManager.executeQuery(query);
query = `DELETE FROM ${schema}.specieslimits WHERE CensusID = ${censusID};`;
await connectionManager.executeQuery(query);
query = `DELETE FROM ${schema}.censusquadrat WHERE CensusID = ${censusID};`;
await connectionManager.executeQuery(query);
query = `DELETE FROM ${schema}.quadrats WHERE QuadratID IN (SELECT QuadratID FROM ${schema}.censusquadrat WHERE CensusID = ${censusID});`;
await connectionManager.executeQuery(query);
query = `DELETE FROM ${schema}.census WHERE CensusID = ${censusID};`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.cmverrors AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.cmattributes AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.coremeasurements AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.quadratpersonnel AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.personnel AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.specieslimits AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.censusquadrat AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.quadrats AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
query = `ALTER TABLE ${schema}.census AUTO_INCREMENT = 1;`;
await connectionManager.executeQuery(query);
await connectionManager.commitTransaction(transactionID);
return NextResponse.json({ message: 'Census cleared successfully' }, { status: HTTPResponses.OK });
} catch (e: any) {
await connectionManager.rollbackTransaction(transactionID);
return new NextResponse(e.message, { status: HTTPResponses.SERVICE_UNAVAILABLE });
}
}
216 changes: 173 additions & 43 deletions frontend/components/datagrids/isolateddatagridcommons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,33 @@ import {
GridToolbarProps,
GridToolbarQuickFilter,
ToolbarPropsOverrides,
useGridApiContext,
useGridApiRef
} from '@mui/x-data-grid';
import { Alert, AlertProps, Button, Checkbox, IconButton, Snackbar } from '@mui/material';
import { Alert, AlertProps, Snackbar } from '@mui/material';
import RefreshIcon from '@mui/icons-material/Refresh';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useOrgCensusContext, usePlotContext, useQuadratContext, useSiteContext } from '@/app/contexts/userselectionprovider';
import { useDataValidityContext } from '@/app/contexts/datavalidityprovider';
import { useSession } from 'next-auth/react';
import { HTTPResponses, UnifiedValidityFlags } from '@/config/macros';
import { Dropdown, Menu, MenuButton, MenuItem, Stack, Tooltip, Typography } from '@mui/joy';
import {
Button,
Checkbox,
Chip,
DialogActions,
DialogContent,
DialogTitle,
FormLabel,
IconButton,
Modal,
ModalDialog,
Skeleton,
Stack,
Switch,
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';
Expand All @@ -54,6 +71,9 @@ import { FormType, getTableHeaders } from '@/config/macros/formdetails';
import { applyFilterToColumns } from '@/components/datagrids/filtrationsystem';
import { ClearIcon } from '@mui/x-date-pickers';
import CloudDownloadIcon from '@mui/icons-material/CloudDownload';
import GridOnIcon from '@mui/icons-material/GridOn';
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
import Divider from '@mui/joy/Divider';

type EditToolbarProps = EditToolbarCustomProps & GridToolbarProps & ToolbarPropsOverrides;

Expand All @@ -67,11 +87,15 @@ const EditToolbar = (props: EditToolbarProps) => {
handleToggleHideEmptyColumns,
hidingEmptyColumns,
filterModel,
dynamicButtons = []
dynamicButtons = [],
gridColumns,
gridType
} = props;
if (!handleAddNewRow || !handleRefresh || !handleQuickFilterChange || !handleExportAll || !handleToggleHideEmptyColumns) return <></>;
const [inputValue, setInputValue] = useState('');
const [isTyping, setIsTyping] = useState(false);
const [openExportModal, setOpenExportModal] = useState(false);
const [exportType, setExportType] = useState<'csv' | 'form'>('csv');

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
Expand Down Expand Up @@ -119,6 +143,16 @@ const EditToolbar = (props: EditToolbarProps) => {
URL.revokeObjectURL(url);
}

const apiRef = useGridApiContext();
const csvHeaders = gridColumns
?.filter(column => !Object.keys(apiRef.current.state.columns.columnVisibilityModel).includes(column.field))
.map(column => column.field);

let formHeaders: string[];
if (gridType === 'alltaxonomiesview') {
formHeaders = getTableHeaders(FormType.species).map(header => header.label);
} else formHeaders = getTableHeaders(gridType as FormType).map(header => header.label);

return (
<GridToolbarContainer>
<Box
Expand Down Expand Up @@ -151,51 +185,32 @@ const EditToolbar = (props: EditToolbarProps) => {
sx={{ ml: 2 }}
/>
<Tooltip title={'Clear filter'} placement={'right'}>
<IconButton
aria-label={'clear filter'}
disabled={inputValue === ''}
onClick={handleClearInput}
size={'small'}
edge={'end'}
sx={{ marginLeft: 1 }}
>
<IconButton aria-label={'clear filter'} disabled={inputValue === ''} onClick={handleClearInput} size={'sm'} sx={{ marginLeft: 1 }}>
<ClearIcon fontSize={'small'} />
</IconButton>
</Tooltip>
</Box>
</Tooltip>
<Button variant={'text'} color={'primary'} startIcon={<RefreshIcon />} onClick={async () => await handleRefresh()}>
<Button variant={'plain'} color={'primary'} startDecorator={<RefreshIcon />} onClick={async () => await handleRefresh()}>
Refresh
</Button>
<Dropdown>
<MenuButton
variant={'plain'}
color={'primary'}
endDecorator={
<CloudDownloadIcon
sx={{
fontSize: '1.5rem',
verticalAlign: 'middle'
}}
/>
}
>
Export...
</MenuButton>
<Menu variant={'soft'} color={'primary'} placement={'bottom-start'}>
<MenuItem variant={'soft'} color={'primary'} onClick={async () => await handleExportAll()}>
All data as JSON
</MenuItem>
<MenuItem variant={'soft'} color={'primary'} onClick={handleExportCSV}>
All Data as CSV
</MenuItem>
<MenuItem variant={'soft'} color={'primary'} onClick={exportFilterModel}>
Filter Settings
</MenuItem>
</Menu>
</Dropdown>
<Button
variant={'plain'}
color={'primary'}
endDecorator={
<CloudDownloadIcon
sx={{
fontSize: '1.5rem',
verticalAlign: 'middle'
}}
/>
}
onClick={() => setOpenExportModal(true)}
>
Export as CSV...
</Button>
<Typography>
<Checkbox checked={hidingEmptyColumns} onChange={event => handleToggleHideEmptyColumns(event.target.checked)} />
<Checkbox checked={hidingEmptyColumns} onChange={(event: { target: { checked: boolean } }) => handleToggleHideEmptyColumns(event.target.checked)} />
<strong>{hidingEmptyColumns ? `Hiding Empty Columns` : `Hide Empty Columns`}</strong>
</Typography>
</Box>
Expand All @@ -206,19 +221,132 @@ const EditToolbar = (props: EditToolbarProps) => {
{button.tooltip ? (
<>
<Tooltip title={button.tooltip} placement={'bottom'} arrow>
<Button key={index} onClick={button.onClick} variant={'contained'} color={'primary'}>
<Button key={index} onClick={button.onClick} variant={'outlined'} color={'neutral'}>
{button.label}
</Button>
</Tooltip>
</>
) : (
<Button key={index} onClick={button.onClick} variant={'contained'} color={'primary'}>
<Button key={index} onClick={button.onClick} variant={'outlined'} color={'neutral'}>
{button.label}
</Button>
)}
</>
))}
</Stack>
<Modal
open={openExportModal}
onClose={() => setOpenExportModal(false)}
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
<ModalDialog
role={'alertdialog'}
sx={{
width: '90%',
maxWidth: '60vh',
maxHeight: '90vh',
overflowY: 'auto',
p: 3
}}
>
<DialogTitle>
<Typography level={'h3'}>Exporting Data</Typography>
</DialogTitle>
<DialogContent
sx={{
mt: 1,
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
overflowY: 'auto'
}}
>
<Stack direction={'row'} sx={{ width: '100%', justifyContent: 'space-between', alignItems: 'center' }}>
<Stack direction={'column'}>
<Typography level={'body-md'}>Desired Format Type:</Typography>
<Typography level={'body-sm'}>You can export data in either of these formats:</Typography>
<Stack direction={'row'}>
<Chip>
<strong>Table CSV</strong>
</Chip>
<Chip>
<strong>Form CSV</strong>
</Chip>
</Stack>
</Stack>
<Switch
size={'lg'}
checked={exportType === 'csv'}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => (event.target.checked ? setExportType('csv') : setExportType('form'))}
endDecorator={
<Stack direction={'column'} sx={{ alignItems: 'center', justifyContent: 'center' }}>
<Skeleton loading={exportType !== 'csv'} variant={'circular'} width={'1.5em'} height={'1.5em'}>
<GridOnIcon />
</Skeleton>
<Typography level={'body-sm'}>
<Skeleton loading={exportType !== 'csv'}>CSV</Skeleton>
</Typography>
</Stack>
}
startDecorator={
<Stack direction={'column'} sx={{ alignItems: 'center', justifyContent: 'center' }}>
<Skeleton loading={exportType !== 'form'} variant={'circular'} width={'1.5em'} height={'1.5em'}>
<PictureAsPdfIcon />
</Skeleton>
<Typography level={'body-sm'}>
<Skeleton loading={exportType !== 'form'}>Form</Skeleton>
</Typography>
</Stack>
}
sx={{
marginRight: '1.5em',
transform: 'scale(1.25)',
transformOrigin: 'center'
}}
/>
</Stack>
<Divider sx={{ my: 1 }} />
<FormLabel>Export Headers:</FormLabel>
<Box
sx={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(125px, 0.5fr))',
gap: '0.5rem',
mb: 1,
width: '100%',
boxSizing: 'border-box'
}}
>
{exportType === 'csv'
? csvHeaders?.map((header, index) => (
<Chip key={index} variant={'soft'} color={'primary'}>
{header}
</Chip>
))
: formHeaders.map((label, index) => (
<Chip key={index} variant={'soft'} color={'primary'}>
{label}
</Chip>
))}
</Box>
</DialogContent>
<DialogActions>
<Button
onClick={async () => {
exportType === 'csv' ? await handleExportCSV() : await handleExportAll();
setOpenExportModal(false);
}}
>
Export
</Button>
<Button onClick={() => setOpenExportModal(false)}>Cancel</Button>
</DialogActions>
</ModalDialog>
</Modal>
</GridToolbarContainer>
);
};
Expand Down Expand Up @@ -1186,7 +1314,9 @@ export default function IsolatedDataGridCommons(props: Readonly<IsolatedDataGrid
handleToggleHideEmptyColumns: handleToggleHidingColumns,
handleQuickFilterChange: onQuickFilterChange,
filterModel: filterModel,
dynamicButtons: dynamicButtons
dynamicButtons: dynamicButtons,
gridColumns: gridColumns,
gridType: gridType
}
}}
getRowHeight={() => 'auto'}
Expand Down
Loading

0 comments on commit c88d3ed

Please sign in to comment.