Use one UpdateTab component for all; add tests for it

This commit is contained in:
arttu
2024-06-18 19:47:57 +03:00
parent 0c631c6fa7
commit 2024485b8b
15 changed files with 138 additions and 152 deletions
+21 -2
View File
@@ -1,4 +1,4 @@
import { nowDb } from '../utils/db'
import { logDb, nowDb } from '../utils/db'
export const getAllSpecies = async (onlyPublic: boolean) => {
const where = onlyPublic ? { sp_status: false } : {}
@@ -43,12 +43,31 @@ export const getSpeciesDetails = async (id: number) => {
com_taxa_synonym: {},
now_sau: {
include: {
now_sr: true,
now_sr: {
include: {
ref_ref: {
include: {
ref_authors: true,
ref_journal: true,
},
},
},
},
},
},
},
})
if (!result) return null
const suids = result.now_sau.map(sau => sau.suid)
const logResult = await logDb.log.findMany({ where: { suid: { in: suids } } })
result.now_sau = result.now_sau.map(sau => ({
...sau,
updates: logResult.filter(logRow => logRow.suid === sau.suid),
}))
return result
}
+22 -2
View File
@@ -1,4 +1,4 @@
import { nowDb } from '../utils/db'
import { logDb, nowDb } from '../utils/db'
export const getAllTimeBounds = async () => {
const result = await nowDb.now_tu_bound.findMany({
@@ -20,11 +20,31 @@ export const getTimeBoundDetails = async (id: number) => {
include: {
now_bau: {
include: {
now_br: true,
now_br: {
include: {
ref_ref: {
include: {
ref_authors: true,
ref_journal: true,
},
},
},
},
},
},
},
})
if (!result) return null
const buids = result.now_bau.map(bau => bau.buid)
const logResult = await logDb.log.findMany({ where: { buid: { in: buids } } })
result.now_bau = result.now_bau.map(bau => ({
...bau,
updates: logResult.filter(logRow => logRow.buid === bau.buid),
}))
return result
}
+23 -2
View File
@@ -1,4 +1,4 @@
import { nowDb } from '../utils/db'
import { logDb, nowDb } from '../utils/db'
export const getAllTimeUnits = async () => {
const result = await nowDb.now_time_unit.findMany({
@@ -42,11 +42,32 @@ export const getTimeUnitDetails = async (id: string) => {
now_tu_bound_now_time_unit_up_bndTonow_tu_bound: {},
now_tau: {
include: {
now_tr: true,
now_tr: {
include: {
ref_ref: {
include: {
ref_authors: true,
ref_journal: true,
},
},
},
},
},
},
},
})
if (!result) return null
const tuids = result.now_tau.map(tau => tau.tuid)
const logResult = await logDb.log.findMany({ where: { suid: { in: tuids } } })
result.now_tau = result.now_tau.map(tau => ({
...tau,
updates: logResult.filter(logRow => logRow.tuid === tau.tuid),
}))
return result
}
+2
View File
@@ -11,4 +11,6 @@ module.exports = defineConfig({
requestTimeout: 80000,
responseTimeout: 80000,
},
viewportHeight: 900,
viewportWidth: 1200,
});
+23
View File
@@ -0,0 +1,23 @@
const baseUrl = 'http://localhost:5173'
/*
This suite is meant to add tests for individual features, including things such as
visiting specific url's directly.
*/
describe('Test individual features across the app', () => {
it('Locality update tab opens, detailed modal works, view-link works', () => {
cy.visit(`${baseUrl}/locality/24750?tab=10`)
cy.contains('2006-10-16')
cy.contains('A new geomagnetic polarity time scale for the Late Cretaceous and Cenozoic Geology 1992')
cy.get('[data-cy="update-details-button"]').first().click()
cy.contains('now_syn_loc')
cy.contains('24750')
cy.contains(`Romanya d'Emporda`)
cy.contains('Add')
cy.contains('A new geomagnetic polarity time scale for the Late Cretaceous and Cenozoic Geology 1992')
cy.contains('View').click()
cy.contains('Reference type')
})
})
@@ -13,10 +13,12 @@ export const EditingModal = ({
buttonText,
children,
onSave,
dataCy,
}: {
buttonText: string
children: ReactNode | ReactNode[]
onSave?: () => Promise<boolean>
dataCy?: string
}) => {
const [open, setOpen] = useState(false)
const closeWithSave = async () => {
@@ -28,7 +30,7 @@ export const EditingModal = ({
return (
<Box>
<Button onClick={() => setOpen(true)} variant="contained" sx={{ marginBottom: '1em' }}>
<Button data-cy={dataCy} onClick={() => setOpen(true)} variant="contained" sx={{ marginBottom: '1em' }}>
{buttonText}
</Button>
<Modal open={open} aria-labelledby={`modal-${buttonText}`} aria-describedby={`modal-${buttonText}`}>
@@ -1,10 +1,10 @@
import { LocalityDetailsType, LocalityReference, LocalityUpdate, ReferenceDetailsType, UpdateLog } from '@/backendTypes'
import { ReferenceDetailsType, UpdateLog } from '@/backendTypes'
import { useDetailContext } from '@/components/DetailView/Context/DetailContext'
import { EditingModal } from '@/components/DetailView/common/EditingModal'
import { SimpleTable } from '@/components/DetailView/common/SimpleTable'
import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers'
import { Card, Stack } from '@mui/material'
import { MRT_ColumnDef, MRT_Row } from 'material-react-table'
import { MRT_ColumnDef, MRT_Row, MRT_RowData } from 'material-react-table'
import { Link } from 'react-router-dom'
const ReferenceList = ({ references, big }: { references: ReferenceDetailsType[]; big: boolean }) => {
@@ -29,51 +29,71 @@ const ReferenceList = ({ references, big }: { references: ReferenceDetailsType[]
)
}
export const UpdateTab = () => {
const { data } = useDetailContext<LocalityDetailsType>()
export const UpdateTab = <T, UpdateType extends MRT_RowData & { updates: UpdateLog[] }>({
prefix,
refFieldName,
updatesFieldName,
}: {
prefix: string
refFieldName: keyof UpdateType
updatesFieldName: keyof T
}) => {
const { data } = useDetailContext<T>()
const formatDate = (date: Date | null) => {
if (!date) return 'No date'
return new Date(date).toISOString().split('T')[0]
}
const columns: MRT_ColumnDef<LocalityUpdate>[] = [
const columns: MRT_ColumnDef<UpdateType>[] = [
{
accessorKey: 'lau_date',
accessorKey: `${prefix}_date`,
header: 'Date',
Cell: ({ cell }) => formatDate(cell.getValue() as Date | null),
},
{
accessorKey: 'lau_authorizer',
accessorKey: `${prefix}_authorizer`,
header: 'Editor',
},
{
accessorKey: 'lau_coordinator',
accessorKey: `${prefix}_coordinator`,
header: 'Coordinator',
},
{
accessorKey: 'now_lr',
accessorKey: refFieldName as string,
header: 'Reference',
Cell: ({ row }: { row: MRT_Row<LocalityUpdate> }) => (
<ReferenceList references={row.original.now_lr.map(lr => lr.ref_ref)} big={false} />
Cell: ({ row }: { row: MRT_Row<UpdateType> }) => (
<ReferenceList
references={(row.original[refFieldName] as { ref_ref: ReferenceDetailsType }[]).map(item => item.ref_ref)}
big={false}
/>
),
},
{
header: 'Details',
Cell: ({ row }: { row: MRT_Row<LocalityUpdate> }) => (
<DetailsModal updates={row.original.updates} references={row.original.now_lr} />
Cell: ({ row }: { row: MRT_Row<UpdateType> }) => (
<DetailsModal
updates={row.original.updates}
references={row.original[refFieldName] as { ref_ref: ReferenceDetailsType }[]}
/>
),
},
]
return (
<Grouped title="Updates">
<SimpleTable columns={columns} data={data.now_lau} />
<SimpleTable columns={columns} data={data[updatesFieldName] as UpdateType[]} />
</Grouped>
)
}
const DetailsModal = ({ updates, references }: { updates: UpdateLog[]; references: LocalityReference[] }) => {
const DetailsModal = <RefType extends { ref_ref: ReferenceDetailsType }>({
updates,
references,
}: {
updates: UpdateLog[]
references: RefType[]
}) => {
const columns: MRT_ColumnDef<UpdateLog>[] = [
{
header: 'Table',
@@ -98,7 +118,7 @@ const DetailsModal = ({ updates, references }: { updates: UpdateLog[]; reference
]
return (
<EditingModal buttonText="Details">
<EditingModal buttonText="Details" dataCy="update-details-button">
<ReferenceList references={references.map(ref => ref.ref_ref)} big />
<SimpleTable columns={columns} data={updates} />
</EditingModal>
@@ -12,9 +12,9 @@ import { MuseumTab } from './Tabs/MuseumTab'
import { ProjectTab } from './Tabs/ProjectTab'
import { SpeciesTab } from './Tabs/SpeciesTab'
import { TaphonomyTab } from './Tabs/TaphonomyTab'
import { UpdateTab } from './Tabs/UpdateTab'
import { EditDataType, LocalityDetailsType } from '@/backendTypes'
import { validateLocality } from '@/validators/locality'
import { UpdateTab } from '../DetailView/common/UpdateTab'
export const LocalityDetails = () => {
const { id } = useParams()
@@ -70,7 +70,7 @@ export const LocalityDetails = () => {
},
{
title: 'Updates',
content: <UpdateTab />,
content: <UpdateTab refFieldName="now_lr" updatesFieldName="now_lau" prefix="lau" />,
},
]
@@ -10,7 +10,7 @@ import { SizeTab } from './Tabs/SizeTab'
import { SynonymTab } from './Tabs/SynonymTab'
import { TaxonomyTab } from './Tabs/TaxonomyTab'
import { TeethTab } from './Tabs/TeethTab'
import { UpdateTab } from './Tabs/UpdateTab'
import { UpdateTab } from '../DetailView/common/UpdateTab'
export const SpeciesDetails = () => {
const { id } = useParams()
@@ -54,7 +54,7 @@ export const SpeciesDetails = () => {
},
{
title: 'Updates',
content: <UpdateTab />,
content: <UpdateTab refFieldName="now_sr" updatesFieldName="now_sau" prefix="sau" />,
},
]
@@ -1,41 +0,0 @@
import { SpeciesDetailsType, SpeciesUpdate } from '@/backendTypes'
import { useDetailContext } from '@/components/DetailView/Context/DetailContext'
import { SimpleTable } from '@/components/DetailView/common/SimpleTable'
import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers'
import { Box } from '@mui/material'
import { MRT_ColumnDef } from 'material-react-table'
export const UpdateTab = () => {
const { data } = useDetailContext<SpeciesDetailsType>()
const formatDate = (date: Date | null) => {
if (!date) return 'No date'
return new Date(date).toISOString().split('T')[0]
}
const columns: MRT_ColumnDef<SpeciesUpdate>[] = [
{
accessorKey: 'sau_date',
header: 'Date',
Cell: ({ cell }) => formatDate(cell.getValue() as Date | null),
},
{
accessorKey: 'sau_authorizer',
header: 'Editor',
},
{
accessorKey: 'sau_coordinator',
header: 'Coordinator',
},
{
accessorKey: 'now_sr',
header: 'Reference',
Cell: () => <Box>not implemented</Box>,
},
]
return (
<Grouped title="Updates">
<SimpleTable columns={columns} data={data.now_sau} />
</Grouped>
)
}
@@ -1,39 +0,0 @@
import { Editable, TimeBoundDetailsType, TimeBoundUpdate } from '@/backendTypes'
import { EditableTable } from '@/components/DetailView/common/EditableTable'
import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers'
import { Box } from '@mui/material'
import { MRT_ColumnDef } from 'material-react-table'
export const UpdateTab = () => {
const formatDate = (date: Date | null) => {
if (!date) return 'No date'
return new Date(date).toISOString().split('T')[0]
}
const columns: MRT_ColumnDef<TimeBoundUpdate>[] = [
{
accessorKey: 'bau_date',
header: 'Date',
Cell: ({ cell }) => formatDate(cell.getValue() as Date | null),
},
{
accessorKey: 'bau_authorizer',
header: 'Editor',
},
{
accessorKey: 'bau_coordinator',
header: 'Coordinator',
},
{
accessorKey: 'now_br',
header: 'Reference',
Cell: () => <Box>not implemented</Box>,
},
]
return (
<Grouped title="Updates">
<EditableTable<Editable<TimeBoundUpdate>, TimeBoundDetailsType> columns={columns} field="now_bau" />
</Grouped>
)
}
@@ -4,7 +4,7 @@ import { CircularProgress } from '@mui/material'
import { DetailView, TabType } from '../DetailView/DetailView'
import { BoundTab } from './Tabs/BoundTab'
import { TimeUnitTab } from './Tabs/TimeUnitTab.tsx'
import { UpdateTab } from './Tabs/UpdateTab'
import { UpdateTab } from '../DetailView/common/UpdateTab.tsx'
export const TimeBoundDetails = () => {
const { id } = useParams()
@@ -24,7 +24,7 @@ export const TimeBoundDetails = () => {
},
{
title: 'Updates',
content: <UpdateTab />,
content: <UpdateTab refFieldName="now_br" updatesFieldName="now_bau" prefix="bau" />,
},
]
@@ -1,41 +0,0 @@
import { TimeUnitDetailsType, TimeUnitUpdate } from '@/backendTypes'
import { useDetailContext } from '@/components/DetailView/Context/DetailContext'
import { SimpleTable } from '@/components/DetailView/common/SimpleTable'
import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers'
import { Box } from '@mui/material'
import { MRT_ColumnDef } from 'material-react-table'
export const UpdateTab = () => {
const { data } = useDetailContext<TimeUnitDetailsType>()
const formatDate = (date: Date | null) => {
if (!date) return 'No date'
return new Date(date).toISOString().split('T')[0]
}
const columns: MRT_ColumnDef<TimeUnitUpdate>[] = [
{
accessorKey: 'tau_date',
header: 'Date',
Cell: ({ cell }) => formatDate(cell.getValue() as Date | null),
},
{
accessorKey: 'tau_authorizer',
header: 'Editor',
},
{
accessorKey: 'tau_coordinator',
header: 'Coordinator',
},
{
accessorKey: 'now_tr',
header: 'Reference',
Cell: () => <Box>not implemented</Box>,
},
]
return (
<Grouped title="Updates">
<SimpleTable columns={columns} data={data.now_tau} />
</Grouped>
)
}
@@ -4,7 +4,7 @@ import { CircularProgress } from '@mui/material'
import { DetailView, TabType } from '../DetailView/DetailView'
import { LocalityTab } from './Tabs/LocalityTab'
import { TimeUnitTab } from './Tabs/TimeUnitTab'
import { UpdateTab } from './Tabs/UpdateTab'
import { UpdateTab } from '../DetailView/common/UpdateTab'
export const TimeUnitDetails = () => {
const { id } = useParams()
@@ -24,7 +24,7 @@ export const TimeUnitDetails = () => {
},
{
title: 'Updates',
content: <UpdateTab />,
content: <UpdateTab refFieldName="now_tr" updatesFieldName="now_tau" prefix="tau" />,
},
]