Skip to content

Commit

Permalink
Biweekly Feedback Meeting Changes (#206)
Browse files Browse the repository at this point in the history
* pruning deprecated data and refining the overall system. failedmeasurements recording system added. formdownload system fixed to handle undefined filtermodel implementation

* fixing completion modal system.

* export modal completed. merging in.

* table structures, triggers, and stored procedures updated to automatically track changes in the measurementssummary table. editing the measurementssummary table will now automatically update host tables and then reset the measurementssummary table, calling the refresh procedure.

* re-incorporating row edit functionality into the view data interface. will continue to expand this to make it more intuitive

* CRUD system reimplemented for msv. editing modal that moves through the system added.

* Updating stored procedures: adding handling for duplicate primary key errors appearing sometimes in view reload

* adding duration formatting to moment in proj

* upload interface simplified. Basic animation visual introduced to demonstrate runstate and ETC timer completed

* export modal updated and added to isolated datagrid baseline. tested to confirm function

* msv editing modal simplified to loading bar.

* minor correction in export modal -- msv

* adding accessibility tools and baseline accessibility updates. Saving changes here and beginning attempt to lift application to v15 of next

* windows formatting changes

* lift progress: eslint has been (temporarily) successfully lifted to v9 and runs via npx eslint. testing remains to determine if this can be extended to nextjs

* saving changes. The lift to v15 seems to be temporarily stable. eslint v9 seems to be working as well, and deprecated packages have either been replaced with similar compatible modules or rewritten to work with the new versions.

* monaco-editor library removed and replaced with codemirror. Package has been removed from system in its entirety. Upgrade to v15/etc looks stable

* removing deprecated files.
  • Loading branch information
siddheshraze authored Feb 3, 2025
1 parent 214cc6e commit 1e660f5
Show file tree
Hide file tree
Showing 84 changed files with 9,710 additions and 7,851 deletions.
22 changes: 0 additions & 22 deletions frontend/.eslintrc.cjs

This file was deleted.

16 changes: 15 additions & 1 deletion frontend/.prettierrc.json → frontend/.prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,19 @@
"endOfLine": "lf",
"printWidth": 160,
"tabWidth": 2,
"useTabs": false
"useTabs": false,
"overrides": [
{
"files": "*.scss",
"options": {
"singleQuote": false
}
},
{
"files": "*.html",
"options": {
"printWidth": 120
}
}
]
}
24 changes: 20 additions & 4 deletions frontend/app/(hub)/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,19 @@ export default function DashboardPage() {
}
>
<AccordionGroup>
<Accordion disabled={isLoading || changelog.id === undefined}>
<AccordionSummary>
<Box sx={{ display: 'flex', flex: 1, width: '100%', alignItems: 'center', flexDirection: 'row' }}>
<Accordion
disabled={isLoading || changelog.id === undefined}
aria-label={'The 5 most recent changes found in the changelog (if they exist)'}
>
<AccordionSummary role={'none'}>
<Box
sx={{ display: 'flex', flex: 1, width: '100%', alignItems: 'center', flexDirection: 'row' }}
aria-label={
changelog.changeTimestamp
? `Change at index ${index}. The changelog timestamp is ${changelog.changeTimestamp}`
: 'No change found'
}
>
<Skeleton loading={changelog.operation === undefined} sx={{ width: '95%' }} animation={'wave'}>
<Typography level={'title-md'} fontWeight={'bold'} sx={{ width: '100%' }}>
{changelog.operation} ON {changelog.tableName} at {moment(changelog?.changeTimestamp).format('YYYY-MM-DD HH:mm:ss')}
Expand All @@ -240,7 +250,13 @@ export default function DashboardPage() {
</Box>
</AccordionSummary>
<AccordionDetails>
<Box>
<Box
aria-label={
changelog.changeTimestamp
? `Details of change at index ${index}. The changelog timestamp is ${changelog.changeTimestamp}`
: 'No change details present.'
}
>
<Typography level={'body-md'}>Updating:</Typography>
<Stack direction={'row'}>
<Card>
Expand Down
10 changes: 10 additions & 0 deletions frontend/app/(hub)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import HelpOutlineOutlinedIcon from '@mui/icons-material/HelpOutlineOutlined';
import { useLockAnimation } from '../contexts/lockanimationcontext';
import { createAndUpdateCensusList } from '@/config/sqlrdsdefinitions/timekeeping';
import { AcaciaVersionTypography } from '@/styles/versions/acaciaversion';
import ReactDOM from 'react-dom';

const Sidebar = dynamic(() => import('@/components/sidebar'), { ssr: false });
const Header = dynamic(() => import('@/components/header'), { ssr: false });
Expand Down Expand Up @@ -320,6 +321,14 @@ export default function HubLayout({ children }: { children: React.ReactNode }) {

const theme = useTheme();

useEffect(() => {
if (process.env.NODE_ENV !== 'production') {
import('@axe-core/react').then(axe => {
axe.default(React, ReactDOM, 1000);
});
}
}, []);

return (
<>
<Box
Expand Down Expand Up @@ -414,6 +423,7 @@ export default function HubLayout({ children }: { children: React.ReactNode }) {
</Typography>
</Stack>
<IconButton
aria-label={'Click here to open the feedback modal and create a Github issue for developer review'}
onClick={() => setIsFeedbackModalOpen(true)}
className={isPulsing ? 'animate-pulse-no-opacity' : ''}
sx={{
Expand Down
44 changes: 18 additions & 26 deletions frontend/app/(login)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';
import React, { useEffect, useState } from 'react';
import { useSession } from 'next-auth/react';
import { animated, useTransition } from '@react-spring/web';
import { motion, AnimatePresence } from 'framer-motion';
import styles from '@/styles/styles.module.css';
import Box from '@mui/joy/Box';
import UnauthenticatedSidebar from '@/components/unauthenticatedsidebar';
Expand All @@ -12,38 +12,30 @@ const slides = ['background-1.jpg', 'background-2.jpg', 'background-3.jpg', 'bac
export default function LoginPage() {
const { data: _session, status } = useSession();
const [index, setIndex] = useState(0);
const transitions = useTransition(index, {
key: index,
from: { opacity: 0 },
enter: { opacity: 0.5 },
leave: { opacity: 0 },
config: { duration: 5000 },
onRest: (_a, _b, item) => {
if (index === item) {
setIndex(state => (state + 1) % slides.length);
}
},
exitBeforeEnter: true
});

// feedback received -- endless loop will consume too many resources and needs to be removed. Single loop through all slides should suffice.
useEffect(() => {
setInterval(() => setIndex(state => (state + 1) % slides.length), 5000);
}, []);
const timer = setTimeout(() => {
setIndex(prevIndex => (prevIndex + 1) % slides.length);
}, 5000);

return () => clearTimeout(timer); // Cleanup on unmount
}, [index]);

if (status === 'unauthenticated') {
return (
<Box sx={{ display: 'flex', minHeight: '100vh', minWidth: '100vh' }}>
{transitions((style, i) => (
<animated.div
<Box sx={{ display: 'flex', minHeight: '100vh', minWidth: '100vh', position: 'relative' }}>
<AnimatePresence mode="wait">
<motion.div
key={slides[index]}
className={styles.bg}
style={{
...style,
backgroundImage: `url(${slides[i]})`
}}
data-testid={`${slides[i]}`}
style={{ backgroundImage: `url(${slides[index]})` }}
data-testid={`${slides[index]}`}
initial={{ opacity: 0 }}
animate={{ opacity: 0.5 }}
exit={{ opacity: 0 }}
transition={{ duration: 1.5 }}
/>
))}
</AnimatePresence>
<UnauthenticatedSidebar />
</Box>
);
Expand Down
40 changes: 40 additions & 0 deletions frontend/app/api/batchedupload/[schema]/[[...slugs]]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { NextRequest, NextResponse } from 'next/server';
import { HTTPResponses } from '@/config/macros';
import { FailedMeasurementsRDS } from '@/config/sqlrdsdefinitions/core';
import connectionmanager from '@/config/connectionmanager';
import { format } from 'mysql2/promise';

export async function POST(request: NextRequest, props: { params: Promise<{ schema: string; slugs?: string[] }> }) {
const params = await props.params;
let errorRows: FailedMeasurementsRDS[] = await request.json();
const schema = params.schema;
const slugs = params.slugs;
if (!errorRows || errorRows.length === 0 || !schema || !slugs || slugs.length !== 2) {
return new NextResponse(JSON.stringify({ message: 'Missing requirements!' }), { status: HTTPResponses.INVALID_REQUEST });
}
const [plotID, censusID] = slugs.map(Number);
if (isNaN(plotID) || isNaN(censusID)) {
return new NextResponse(JSON.stringify({ message: 'Invalid plotID or censusID!' }), { status: HTTPResponses.INVALID_REQUEST });
}

// Add plotID and censusID to each row
errorRows = errorRows.map(row => ({
...row,
plotID,
censusID
}));

const connectionManager = connectionmanager.getInstance();
const columns = Object.keys(errorRows[0]).filter(col => col !== 'id' && col !== 'failedMeasurementID');
const values = errorRows.map(row => columns.map(col => row[col as keyof FailedMeasurementsRDS]));

const insertQuery = format(`INSERT INTO ?? (${columns.map(() => '??').join(', ')}) VALUES ?`, [`${schema}.failedmeasurements`, ...columns, values]);

try {
await connectionManager.executeQuery(insertQuery);
return new NextResponse(JSON.stringify({ message: 'Insert to SQL successful' }), { status: HTTPResponses.OK });
} catch (error: any) {
console.error('Database Error:', error);
return new NextResponse(JSON.stringify({ message: 'Database error', error: error.message }), { status: HTTPResponses.INTERNAL_SERVER_ERROR });
}
}
6 changes: 3 additions & 3 deletions frontend/app/api/bulkcrud/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ConnectionManager from '@/config/connectionmanager';
import { Plot } from '@/config/sqlrdsdefinitions/zones';
import { OrgCensus } from '@/config/sqlrdsdefinitions/timekeeping';

export async function POST(request: NextRequest, { params }: { params: { dataType: string; slugs?: string[] } }) {
export async function POST(request: NextRequest) {
const body = await request.json();
const dataType: string = body.gridType;
const schema: string = body.schema;
Expand All @@ -23,8 +23,8 @@ export async function POST(request: NextRequest, { params }: { params: { dataTyp
const connectionManager = ConnectionManager.getInstance();
let transactionID: string | undefined = undefined;
try {
transactionID = await connectionManager.beginTransaction();
for (const rowID in rows) {
transactionID = await connectionManager.beginTransaction();
const rowData = rows[rowID];
const props: InsertUpdateProcessingProps = {
schema,
Expand All @@ -37,8 +37,8 @@ export async function POST(request: NextRequest, { params }: { params: { dataTyp
fullName: undefined
};
await insertOrUpdate(props);
await connectionManager.commitTransaction(transactionID ?? '');
}
await connectionManager.commitTransaction(transactionID ?? '');
return new NextResponse(JSON.stringify({ message: 'Insert to SQL successful' }), { status: HTTPResponses.OK });
} catch (e: any) {
await connectionManager.rollbackTransaction(transactionID ?? '');
Expand Down
3 changes: 2 additions & 1 deletion frontend/app/api/catalog/[firstName]/[lastName]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { NextRequest, NextResponse } from 'next/server';
import { HTTPResponses } from '@/config/macros';
import ConnectionManager from '@/config/connectionmanager';

export async function GET(_request: NextRequest, { params }: { params: { firstName: string; lastName: string } }) {
export async function GET(_request: NextRequest, props: { params: Promise<{ firstName: string; lastName: string }> }) {
const params = await props.params;
const { firstName, lastName } = params;
if (!firstName || !lastName) throw new Error('no first or last name provided!');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { HTTPResponses } from '@/config/macros';
import MapperFactory from '@/config/datamapper';
import ConnectionManager from '@/config/connectionmanager';

export async function GET(request: NextRequest, { params }: { params: { changelogType: string; options?: string[] } }) {
export async function GET(request: NextRequest, props: { params: Promise<{ changelogType: string; options?: string[] }> }) {
const params = await props.params;
const schema = request.nextUrl.searchParams.get('schema');
if (!schema) throw new Error('schema not found');
if (!params.changelogType) throw new Error('changelogType not provided');
Expand Down
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 });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import ConnectionManager from '@/config/connectionmanager';

// datatype: table name
// expecting 1) schema 2) plotID 3) plotCensusNumber
export async function GET(_request: NextRequest, { params }: { params: { dataType: string; slugs?: string[] } }) {
export async function GET(_request: NextRequest, props: { params: Promise<{ dataType: string; slugs?: string[] }> }) {
const params = await props.params;
if (!params.slugs || !params.dataType) throw new Error('missing slugs');
const [schema, plotID, plotCensusNumber] = params.slugs;
if (
Expand Down
3 changes: 2 additions & 1 deletion frontend/app/api/fetchall/[[...slugs]]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ const buildQuery = (schema: string, fetchType: string, plotID?: string, plotCens
};

// ordering: PCQ
export async function GET(request: NextRequest, { params }: { params: { slugs?: string[] } }) {
export async function GET(request: NextRequest, props: { params: Promise<{ slugs?: string[] }> }) {
const params = await props.params;
const schema = request.nextUrl.searchParams.get('schema');
if (!schema || schema === 'undefined') {
throw new Error('Schema selection was not provided to API endpoint');
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/api/filehandlers/downloadallfiles/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export async function GET(request: NextRequest) {
name: blob.name,
user: blob.metadata?.user,
formType: blob.metadata?.FormType,
fileErrors: blob.metadata?.FileErrorState ? JSON.parse(<string>blob.metadata?.FileErrorState) : '',
fileErrors: blob.metadata?.FileErrorState ? JSON.parse(blob.metadata?.FileErrorState as string) : '',
date: blob.properties.lastModified
});
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/api/filehandlers/storageload/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export async function POST(request: NextRequest) {
const user = request.nextUrl.searchParams.get('user');
const formType = request.nextUrl.searchParams.get('formType');
const file = formData.get(fileName ?? 'file') as File | null;
const fileRowErrors = formData.get('fileRowErrors') ? JSON.parse(<string>formData.get('fileRowErrors')) : [];
const fileRowErrors = formData.get('fileRowErrors') ? JSON.parse(formData.get('fileRowErrors') as string) : [];

if (
file === null ||
Expand Down
Loading

0 comments on commit 1e660f5

Please sign in to comment.