Some validator ui changes, date handling etc.

This commit is contained in:
kaarleol
2024-11-15 14:40:29 +01:00
committed by Aaro Koivukangas
parent fe8eecd2f2
commit bcce65143a
6 changed files with 152 additions and 111 deletions
+9
View File
@@ -40,6 +40,15 @@ export const getReferenceDetails = async (id: number) => {
where: { rid: id },
include: { ref_authors: true, ref_journal: true },
})
//changing exact_date to yyyy-mm-dd string since frontend uses that + we don't want to display ISO string in frontend
if (result && result.exact_date) {
const date = new Date(result.exact_date)
const formattedDate = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
return { ...result, exact_date: formattedDate }
}
return result
}
+3 -1
View File
@@ -217,7 +217,9 @@ export type TimeUnit = {
export type EditMetaData = { comment?: string; references?: Reference[] }
/* Reference */
export type ReferenceDetailsType = Prisma.ref_ref & {
export type ReferenceDetailsType = Omit<Prisma.ref_ref, 'exact_date'> & {
exact_date: string | null
} & {
ref_authors: {
rid: number
au_num: number
@@ -10,7 +10,7 @@ import {
import { useDetailContext } from '../Context/DetailContext'
import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'
import { useState } from 'react'
import { useState, useEffect } from 'react'
const defaultPagination: MRT_PaginationState = { pageIndex: 0, pageSize: 15 }
@@ -42,7 +42,25 @@ export const EditableTable = <
useObject?: boolean
}) => {
const [pagination, setPagination] = useState<MRT_PaginationState>(defaultPagination)
const { editData, setEditData, mode, data } = useDetailContext<ParentType>()
const { editData, setEditData, mode, data, validator, fieldsWithErrors, setFieldsWithErrors } =
useDetailContext<ParentType>()
const { error } = validator(editData, field)
useEffect(() => {
const errorField = String(field)
if (error && !fieldsWithErrors.includes(errorField)) {
// saves invalid field into array of errors in context
setFieldsWithErrors(prevErrors => {
return [...prevErrors, errorField]
})
} else if (!error && fieldsWithErrors.includes(errorField)) {
// removes valid field from the array
setFieldsWithErrors(prevErrors => {
return prevErrors.filter(err => err !== errorField)
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [error])
if (tableData === null || editTableData === null) return <CircularProgress />
@@ -28,8 +28,10 @@ function checkIndexes(editData: EditDataType<ReferenceDetailsType>): boolean {
}
export const AuthorTab: React.FC<AuthorTabProps> = ({ field_num_param, tab_name = 'Authors' }) => {
const { mode, editData, setEditData } = useDetailContext<ReferenceDetailsType>()
const { mode, editData, setEditData, fieldsWithErrors } = useDetailContext<ReferenceDetailsType>()
const { data: authorData, isError } = useGetReferenceAuthorsQuery(mode.read ? skipToken : undefined)
const hasError = fieldsWithErrors.includes('ref_authors')
useEffect(() => {
// Check and update indexes of authors only if they are incorrect
if (checkIndexes(editData)) {
@@ -73,69 +75,71 @@ export const AuthorTab: React.FC<AuthorTabProps> = ({ field_num_param, tab_name
]
return (
<Grouped title={tab_name ? tab_name : 'Authors'}>
{!mode.read && (
<Box display="flex" gap={1}>
<EditingForm<ReferenceAuthorType, ReferenceDetailsType>
buttonText="Add new author"
formFields={formFields}
editAction={(newAuthor: ReferenceAuthorType) => {
const updatedAuthors = [
...editData.ref_authors,
{
...newAuthor,
rid: editData.rid,
au_num: editData.ref_authors.filter(author => author.field_id === field_num_param).length + 1,
field_id: field_num_param,
rowState: 'new' as RowState,
},
]
<Box border={hasError ? `1px solid #d32f2f` : 'none'} borderRadius={1}>
<Grouped title={tab_name ? tab_name : 'Authors'}>
{!mode.read && (
<Box display="flex" gap={1}>
<EditingForm<ReferenceAuthorType, ReferenceDetailsType>
buttonText="Add new author"
formFields={formFields}
editAction={(newAuthor: ReferenceAuthorType) => {
const updatedAuthors = [
...editData.ref_authors,
{
...newAuthor,
rid: editData.rid,
au_num: editData.ref_authors.filter(author => author.field_id === field_num_param).length + 1,
field_id: field_num_param,
rowState: 'new' as RowState,
},
]
setEditData({
...editData,
ref_authors: [...updatedAuthors],
})
visible_ref_authors = updatedAuthors.filter(
author => author.field_id?.toString() == field_num_param?.toString()
)
}}
/>
<SelectingTable<ReferenceAuthorType, ReferenceDetailsType>
buttonText="Select Author"
data={authorData}
isError={isError}
columns={authorColumns}
fieldName="ref_authors"
idFieldName="data_id"
editingAction={(newAuthor: ReferenceAuthorType) => {
const updatedAuthors = [
...editData.ref_authors,
{
...newAuthor,
rid: editData.rid,
au_num: editData.ref_authors.filter(author => author.field_id === field_num_param).length + 1,
field_id: field_num_param,
rowState: 'new' as RowState,
},
]
setEditData({
...editData,
ref_authors: [...updatedAuthors],
})
visible_ref_authors = updatedAuthors.filter(
author => author.field_id?.toString() == field_num_param?.toString()
)
}}
/>
<SelectingTable<ReferenceAuthorType, ReferenceDetailsType>
buttonText="Select Author"
data={authorData}
isError={isError}
columns={authorColumns}
fieldName="ref_authors"
idFieldName="data_id"
editingAction={(newAuthor: ReferenceAuthorType) => {
const updatedAuthors = [
...editData.ref_authors,
{
...newAuthor,
rid: editData.rid,
au_num: editData.ref_authors.filter(author => author.field_id === field_num_param).length + 1,
field_id: field_num_param,
rowState: 'new' as RowState,
},
]
setEditData({
...editData,
ref_authors: [...updatedAuthors],
})
visible_ref_authors = updatedAuthors.filter(
author => author.field_id?.toString() == field_num_param?.toString()
)
}}
/>
</Box>
)}
<EditableTable<ReferenceAuthorType, ReferenceDetailsType>
columns={referenceAuthorColumns}
field="ref_authors"
visible_data={visible_ref_authors}
useDefinedIndex={true}
/>
</Grouped>
setEditData({
...editData,
ref_authors: [...updatedAuthors],
})
visible_ref_authors = updatedAuthors.filter(
author => author.field_id?.toString() == field_num_param?.toString()
)
}}
/>
</Box>
)}
<EditableTable<ReferenceAuthorType, ReferenceDetailsType>
columns={referenceAuthorColumns}
field="ref_authors"
visible_data={visible_ref_authors}
useDefinedIndex={true}
/>
</Grouped>
</Box>
)
}
@@ -15,8 +15,9 @@ interface JournalTabProps {
}
export const JournalTab: React.FC<JournalTabProps> = ({ tab_name = 'Journal' }) => {
const { mode, editData, setEditData } = useDetailContext<ReferenceDetailsType>()
const { mode, editData, setEditData, fieldsWithErrors } = useDetailContext<ReferenceDetailsType>()
const { data: journalData, isError } = useGetReferenceJournalsQuery(mode.read ? skipToken : undefined)
const hasError = fieldsWithErrors.includes('ref_journal')
let visible_ref_journal: Array<ReferenceJournalType> = []
if (editData.ref_journal && Object.keys(editData.ref_journal).length !== 0) {
visible_ref_journal = [Object.assign({}, editData.ref_journal)]
@@ -66,44 +67,46 @@ export const JournalTab: React.FC<JournalTabProps> = ({ tab_name = 'Journal' })
]
return (
<Grouped title={tab_name ? tab_name : 'Journal'}>
{!mode.read && (
<Box display="flex" gap={1}>
<EditingForm<ReferenceJournalType, ReferenceDetailsType>
buttonText="Add new journal"
formFields={formFields}
editAction={(newJournal: ReferenceJournalType) => {
setEditData({
...editData,
journal_id: undefined,
ref_journal: { ...newJournal, journal_id: undefined, rowState: 'new' },
})
}}
/>
<SelectingTable<ReferenceJournalType, ReferenceDetailsType>
buttonText="Select Journal"
data={journalData}
isError={isError}
columns={journalColumns}
fieldName="ref_journal"
idFieldName="journal_id"
useObject={true}
editingAction={(newJournal: ReferenceJournalType) => {
setEditData({
...editData,
journal_id: newJournal.journal_id,
ref_journal: { ...newJournal, rowState: 'new' },
})
}}
/>
</Box>
)}
<EditableTable<ReferenceJournalType, ReferenceDetailsType>
columns={referenceJournalColumns}
field="ref_journal"
visible_data={visible_ref_journal}
useObject={true}
/>
</Grouped>
<Box border={hasError ? `1px solid #d32f2f` : 'none'} borderRadius={1}>
<Grouped title={tab_name ? tab_name : 'Journal'}>
{!mode.read && (
<Box display="flex" gap={1}>
<EditingForm<ReferenceJournalType, ReferenceDetailsType>
buttonText="Add new journal"
formFields={formFields}
editAction={(newJournal: ReferenceJournalType) => {
setEditData({
...editData,
journal_id: undefined,
ref_journal: { ...newJournal, journal_id: undefined, rowState: 'new' },
})
}}
/>
<SelectingTable<ReferenceJournalType, ReferenceDetailsType>
buttonText="Select Journal"
data={journalData}
isError={isError}
columns={journalColumns}
fieldName="ref_journal"
idFieldName="journal_id"
useObject={true}
editingAction={(newJournal: ReferenceJournalType) => {
setEditData({
...editData,
journal_id: newJournal.journal_id,
ref_journal: { ...newJournal, rowState: 'new' },
})
}}
/>
</Box>
)}
<EditableTable<ReferenceJournalType, ReferenceDetailsType>
columns={referenceJournalColumns}
field="ref_journal"
visible_data={visible_ref_journal}
useObject={true}
/>
</Grouped>
</Box>
)
}
+10 -5
View File
@@ -88,7 +88,10 @@ const dateCheck: (dateString: string) => ValidationError = (dateString: string)
return null
}
const orCheck = (data: EditDataType<ReferenceDetailsType>): ValidationError => {
const orCheck = (
data: EditDataType<ReferenceDetailsType>,
fieldName: keyof EditDataType<ReferenceDetailsType>
): ValidationError => {
let fields: (keyof EditDataType<ReferenceDetailsType>)[] = []
if (data.ref_type_id && [1, 2].includes(data.ref_type_id)) {
@@ -107,6 +110,8 @@ const orCheck = (data: EditDataType<ReferenceDetailsType>): ValidationError => {
fields = ['gen_notes']
}
if (!fields.includes(fieldName)) return null
const hasValue = fields.some(field => {
const value = data[field]
return value != null && typeof value === 'string' && value.length > 0
@@ -127,28 +132,28 @@ export const validateReference = (
name: 'title_primary',
useEditData: true,
miscCheck: (obj: object) => {
return orCheck(obj as EditDataType<ReferenceDetailsType>)
return orCheck(obj as EditDataType<ReferenceDetailsType>, (fieldName = 'title_primary'))
},
},
title_secondary: {
name: 'title_secondary',
useEditData: true,
miscCheck: (obj: object) => {
return orCheck(obj as EditDataType<ReferenceDetailsType>)
return orCheck(obj as EditDataType<ReferenceDetailsType>, (fieldName = 'title_secondary'))
},
},
title_series: {
name: 'title_series',
useEditData: true,
miscCheck: (obj: object) => {
return orCheck(obj as EditDataType<ReferenceDetailsType>)
return orCheck(obj as EditDataType<ReferenceDetailsType>, (fieldName = 'title_series'))
},
},
gen_notes: {
name: 'gen_notes',
useEditData: true,
miscCheck: (obj: object) => {
return orCheck(obj as EditDataType<ReferenceDetailsType>)
return orCheck(obj as EditDataType<ReferenceDetailsType>, (fieldName = 'gen_notes'))
},
},
ref_type_id: {