mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Use one UpdateTab component for all; add tests for it
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -11,4 +11,6 @@ module.exports = defineConfig({
|
||||
requestTimeout: 80000,
|
||||
responseTimeout: 80000,
|
||||
},
|
||||
viewportHeight: 900,
|
||||
viewportWidth: 1200,
|
||||
});
|
||||
|
||||
@@ -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}`}>
|
||||
|
||||
+36
-16
@@ -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" />,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user