mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
add put route for museums, and improve fixRadioSelection function to handle "null" strings
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { Router } from 'express'
|
||||
import { getAllMuseums, getMuseumDetails } from '../services/museum'
|
||||
import { Router, Request } from 'express'
|
||||
import { getAllMuseums, getMuseumDetails, validateEntireMuseum } from '../services/museum'
|
||||
import { fixBigInt } from '../utils/common'
|
||||
import { requireOneOf } from '../middlewares/authorizer'
|
||||
import { Role, EditDataType, EditMetaData, RegionDetails, Museum } from '../../../frontend/src/shared/types'
|
||||
import { writeMuseum } from '../services/write/museum'
|
||||
|
||||
const router = Router()
|
||||
|
||||
@@ -16,4 +19,18 @@ router.get('/:id', async (req, res) => {
|
||||
return res.status(200).send(fixBigInt(museum))
|
||||
})
|
||||
|
||||
router.put(
|
||||
'/',
|
||||
requireOneOf([Role.Admin]),
|
||||
async (req: Request<object, object, { museum: EditDataType<Museum> & EditMetaData }>, res) => {
|
||||
const { ...editedMuseum } = req.body.museum
|
||||
const validationErrors = validateEntireMuseum({ ...editedMuseum })
|
||||
if (validationErrors.length > 0) {
|
||||
return res.status(403).send(validationErrors)
|
||||
}
|
||||
const museum = await writeMuseum(editedMuseum)
|
||||
return res.status(200).send({ museum })
|
||||
}
|
||||
)
|
||||
|
||||
export default router
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Locality } from '../../../frontend/src/shared/types'
|
||||
import { Locality, Museum, EditDataType, EditMetaData } from '../../../frontend/src/shared/types'
|
||||
import { nowDb } from '../utils/db'
|
||||
import { ValidationObject } from '../../../frontend/src/shared/validators/validator'
|
||||
import Prisma from '../../prisma/generated/now_test_client'
|
||||
import { validateMuseum } from '../../../frontend/src/shared/validators/museum'
|
||||
|
||||
export const getAllMuseums = async () => {
|
||||
const result = await nowDb.com_mlist.findMany({})
|
||||
@@ -31,3 +34,13 @@ export const getMuseumDetails = async (id: string) => {
|
||||
|
||||
return combined
|
||||
}
|
||||
|
||||
export const validateEntireMuseum = (editedFields: EditDataType<Prisma.com_mlist> & EditMetaData) => {
|
||||
const keys = Object.keys(editedFields)
|
||||
const errors: ValidationObject[] = []
|
||||
for (const key of keys) {
|
||||
const error = validateMuseum(editedFields as EditDataType<Museum>, key as keyof Museum)
|
||||
if (error.error) errors.push(error)
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Museum, EditDataType } from '../../../../frontend/src/shared/types'
|
||||
import { getFieldsOfTables, nowDb } from '../../utils/db'
|
||||
import Prisma from '../../../prisma/generated/now_test_client'
|
||||
import { filterAllowedKeys, fixRadioSelection } from './writeOperations/utils'
|
||||
|
||||
export const writeMuseum = async (museum: EditDataType<Museum>) => {
|
||||
const allowedColumns = getFieldsOfTables(['com_mlist'])
|
||||
const filteredMuseum = filterAllowedKeys(museum, allowedColumns) as Prisma.com_mlist
|
||||
let museumId: string
|
||||
|
||||
if (!filteredMuseum.museum) {
|
||||
const newMuseum = await nowDb.com_mlist.create({
|
||||
data: filteredMuseum,
|
||||
})
|
||||
museumId = newMuseum.museum
|
||||
} else {
|
||||
await nowDb.com_mlist.update({
|
||||
where: { museum: museum.museum },
|
||||
data: {
|
||||
...filteredMuseum,
|
||||
used_morph: fixRadioSelection(filteredMuseum.used_morph),
|
||||
used_now: fixRadioSelection(filteredMuseum.used_now),
|
||||
used_gene: fixRadioSelection(filteredMuseum.used_gene),
|
||||
},
|
||||
})
|
||||
museumId = filteredMuseum.museum
|
||||
}
|
||||
|
||||
return museumId
|
||||
}
|
||||
@@ -46,6 +46,7 @@ export const makeListRemoved = (list: Editable<Record<string, unknown>>[]) => {
|
||||
|
||||
export const fixRadioSelection = (value: unknown) => {
|
||||
if (typeof value === 'string') {
|
||||
if (value === 'null') return null
|
||||
return value === 'true' ? true : false
|
||||
}
|
||||
if (typeof value === 'boolean') return value
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
import { useGetMuseumDetailsQuery } from '../../redux/museumReducer'
|
||||
import { useEditMuseumMutation, useGetMuseumDetailsQuery } from '../../redux/museumReducer'
|
||||
import { DetailView, TabType } from '../DetailView/DetailView'
|
||||
import { MuseumInfoTab } from './Tabs/MuseumInfoTab'
|
||||
import { emptyMuseum } from '../DetailView/common/defaultValues'
|
||||
import { validateMuseum } from '@/shared/validators/museum'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { CircularProgress } from '@mui/material'
|
||||
import { Museum } from '@/shared/types'
|
||||
import { Museum, EditDataType, ValidationErrors } from '@/shared/types'
|
||||
import { LocalityTab } from './Tabs/LocalityTab'
|
||||
import { useNotify } from '@/hooks/notification'
|
||||
|
||||
export const MuseumDetails = () => {
|
||||
const { id } = useParams()
|
||||
const isNew = id === 'new'
|
||||
const { isError, isFetching, data } = useGetMuseumDetailsQuery(id!)
|
||||
const [editMuseumRequest, { isLoading: mutationLoading }] = useEditMuseumMutation()
|
||||
const notify = useNotify()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const tabs: TabType[] = [
|
||||
{
|
||||
@@ -24,16 +29,27 @@ export const MuseumDetails = () => {
|
||||
]
|
||||
|
||||
if (isError) return <div>Error loading data</div>
|
||||
if (isFetching || !data) return <CircularProgress />
|
||||
if (isFetching || (!data && !isNew) || mutationLoading) return <CircularProgress />
|
||||
if (data) {
|
||||
document.title = `Museum - ${data.institution}`
|
||||
}
|
||||
|
||||
const onWrite = async (editData: EditDataType<Museum>) => {
|
||||
try {
|
||||
const { museum } = await editMuseumRequest(editData).unwrap()
|
||||
notify('Saved region successfully.')
|
||||
setTimeout(() => navigate(`/museum/${museum}`), 15)
|
||||
} catch (e) {
|
||||
const error = e as ValidationErrors
|
||||
notify('Following validators failed: ' + error.data.map(e => e.name).join(', '), 'error')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<DetailView<Museum>
|
||||
tabs={tabs}
|
||||
data={!data ? emptyMuseum : data}
|
||||
onWrite={undefined}
|
||||
onWrite={onWrite}
|
||||
isNew={false}
|
||||
validator={validateMuseum}
|
||||
deleteFunction={undefined}
|
||||
|
||||
@@ -4,6 +4,8 @@ import { Museum } from '@/shared/types'
|
||||
|
||||
export const MuseumInfoTab = () => {
|
||||
const { textField, radioSelection } = useDetailContext<Museum>()
|
||||
const { editData } = useDetailContext()
|
||||
|
||||
const museumInfo = [
|
||||
['Institution', textField('institution')],
|
||||
['Alt. name', textField('alt_int_name')],
|
||||
|
||||
@@ -65,6 +65,8 @@ export const api = createApi({
|
||||
'timebounds',
|
||||
'region',
|
||||
'regions',
|
||||
'museum',
|
||||
'museums',
|
||||
'person',
|
||||
'persons',
|
||||
'author',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Museum } from '@/shared/types'
|
||||
import { Museum, EditDataType } from '@/shared/types'
|
||||
import { api } from './api'
|
||||
|
||||
const museumsApi = api.injectEndpoints({
|
||||
@@ -14,7 +14,15 @@ const museumsApi = api.injectEndpoints({
|
||||
}),
|
||||
providesTags: result => (result ? [{ type: 'museum', id: result.museum }] : []),
|
||||
}),
|
||||
editMuseum: builder.mutation<Museum, EditDataType<Museum>>({
|
||||
query: museum => ({
|
||||
url: `/museum`,
|
||||
method: 'PUT',
|
||||
body: { museum },
|
||||
}),
|
||||
invalidatesTags: (result, _error, { museum }) => (result ? [{ type: 'museum', id: museum }, 'museums'] : []),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const { useGetAllMuseumsQuery, useGetMuseumDetailsQuery } = museumsApi
|
||||
export const { useGetAllMuseumsQuery, useGetMuseumDetailsQuery, useEditMuseumMutation } = museumsApi
|
||||
|
||||
Reference in New Issue
Block a user