mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Add delete routes & services for rest of data types.
This commit is contained in:
@@ -2,7 +2,7 @@ import { Request, Router } from 'express'
|
||||
import { getAllTimeBounds, getTimeBoundDetails, getTimeBoundTimeUnits } from '../services/timeBound'
|
||||
import { fixBigInt } from '../utils/common'
|
||||
import { EditDataType, EditMetaData, TimeBoundDetailsType } from '../../../frontend/src/backendTypes'
|
||||
import { writeTimeBound } from '../services/write/timeBound'
|
||||
import { deleteTimeUnit, writeTimeBound } from '../services/write/timeBound'
|
||||
import { requireOneOf } from '../middlewares/authorizer'
|
||||
import { Role } from '../../../frontend/src/types'
|
||||
|
||||
@@ -36,4 +36,10 @@ router.put(
|
||||
}
|
||||
)
|
||||
|
||||
router.delete('/:id', requireOneOf([Role.Admin, Role.EditUnrestricted]), async (req, res) => {
|
||||
const id = parseInt(req.params.id)
|
||||
await deleteTimeUnit(id, req.user!)
|
||||
res.status(200).send()
|
||||
})
|
||||
|
||||
export default router
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Request, Router } from 'express'
|
||||
import { getAllTimeUnits, getTimeUnitDetails, getTimeUnitLocalities } from '../services/timeUnit'
|
||||
import { fixBigInt } from '../utils/common'
|
||||
import { EditDataType, EditMetaData, TimeUnitDetailsType } from '../../../frontend/src/backendTypes'
|
||||
import { getAllSequences } from '../services/sequence'
|
||||
import { writeTimeUnit } from '../services/write/timeUnit'
|
||||
import { requireOneOf } from '../middlewares/authorizer'
|
||||
import { Role } from '../../../frontend/src/types'
|
||||
import { requireOneOf } from '../middlewares/authorizer'
|
||||
import { getAllSequences } from '../services/sequence'
|
||||
import { getAllTimeUnits, getTimeUnitDetails, getTimeUnitLocalities } from '../services/timeUnit'
|
||||
import { deleteTimeUnit, writeTimeUnit } from '../services/write/timeUnit'
|
||||
import { fixBigInt } from '../utils/common'
|
||||
|
||||
const router = Router()
|
||||
|
||||
@@ -42,4 +42,10 @@ router.put(
|
||||
}
|
||||
)
|
||||
|
||||
router.delete('/:id', requireOneOf([Role.Admin, Role.EditUnrestricted]), async (req, res) => {
|
||||
const id = req.params.id
|
||||
await deleteTimeUnit(id, req.user!)
|
||||
res.status(200).send()
|
||||
})
|
||||
|
||||
export default router
|
||||
|
||||
@@ -12,7 +12,7 @@ const getSpeciesWriteHandler = (type: ActionType) => {
|
||||
table: 'com_species',
|
||||
idColumn: 'species_id',
|
||||
allowedColumns: getFieldsOfTables(['com_species', 'now_ls']),
|
||||
type: type,
|
||||
type,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
import { EditDataType, Reference, TimeBoundDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
import { EditDataType, Reference, TimeBoundDetailsType, User } from '../../../../frontend/src/backendTypes'
|
||||
import { NOW_DB_NAME } from '../../utils/config'
|
||||
import { WriteHandler } from '../writeOperations/writeHandler'
|
||||
import { getFieldsOfTables } from '../../utils/db'
|
||||
import { ActionType } from '../writeOperations/types'
|
||||
import { getTimeBoundDetails } from '../timeBound'
|
||||
|
||||
const getTimeBoundWriteHandler = (type: ActionType) => {
|
||||
return new WriteHandler({
|
||||
dbName: NOW_DB_NAME,
|
||||
table: 'now_tu_bound',
|
||||
idColumn: 'bid',
|
||||
allowedColumns: getFieldsOfTables(['now_tu_bound']),
|
||||
type: type,
|
||||
})
|
||||
}
|
||||
|
||||
export const writeTimeBound = async (
|
||||
timeBound: EditDataType<TimeBoundDetailsType>,
|
||||
@@ -9,13 +21,7 @@ export const writeTimeBound = async (
|
||||
references: Reference[] | undefined,
|
||||
authorizer: string
|
||||
) => {
|
||||
const writeHandler = new WriteHandler({
|
||||
dbName: NOW_DB_NAME,
|
||||
table: 'now_tu_bound',
|
||||
idColumn: 'bid',
|
||||
allowedColumns: getFieldsOfTables(['now_tu_bound']),
|
||||
type: timeBound.bid ? 'update' : 'add',
|
||||
})
|
||||
const writeHandler = getTimeBoundWriteHandler(timeBound.bid ? 'update' : 'add')
|
||||
|
||||
try {
|
||||
await writeHandler.start()
|
||||
@@ -31,3 +37,17 @@ export const writeTimeBound = async (
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export const deleteTimeUnit = async (id: number, user: User) => {
|
||||
const timeBound = await getTimeBoundDetails(id)
|
||||
if (!timeBound) throw new Error('Time bound not found')
|
||||
const writeHandler = getTimeBoundWriteHandler('delete')
|
||||
try {
|
||||
await writeHandler.start()
|
||||
await writeHandler.deleteObject('now_tu_bound', timeBound, ['bid'])
|
||||
await writeHandler.logUpdatesAndComplete(user.initials)
|
||||
} catch (e) {
|
||||
await writeHandler.end()
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
import { EditDataType, Reference, TimeUnitDetailsType } from '../../../../frontend/src/backendTypes'
|
||||
import { EditDataType, Reference, TimeUnitDetailsType, User } from '../../../../frontend/src/backendTypes'
|
||||
import { NOW_DB_NAME } from '../../utils/config'
|
||||
import { WriteHandler } from '../writeOperations/writeHandler'
|
||||
import { getFieldsOfTables } from '../../utils/db'
|
||||
import { ActionType } from '../writeOperations/types'
|
||||
import { getTimeUnitDetails } from '../timeUnit'
|
||||
|
||||
const getTimeUnitWriteHandler = (type: ActionType) => {
|
||||
return new WriteHandler({
|
||||
dbName: NOW_DB_NAME,
|
||||
table: 'now_time_unit',
|
||||
idColumn: 'tu_name',
|
||||
allowedColumns: getFieldsOfTables(['now_time_unit', 'now_tu_sequence']),
|
||||
type,
|
||||
})
|
||||
}
|
||||
|
||||
const createTimeUnitId = (displayName: string) => displayName.toLowerCase().replace(' ', '')
|
||||
|
||||
export const writeTimeUnit = async (
|
||||
timeUnit: EditDataType<TimeUnitDetailsType>,
|
||||
@@ -9,13 +23,7 @@ export const writeTimeUnit = async (
|
||||
references: Reference[] | undefined,
|
||||
authorizer: string
|
||||
) => {
|
||||
const writeHandler = new WriteHandler({
|
||||
dbName: NOW_DB_NAME,
|
||||
table: 'now_time_unit',
|
||||
idColumn: 'tu_name',
|
||||
allowedColumns: getFieldsOfTables(['now_time_unit', 'now_tu_sequence']),
|
||||
type: timeUnit.tu_name ? 'update' : 'add',
|
||||
})
|
||||
const writeHandler = getTimeUnitWriteHandler(timeUnit.tu_name ? 'update' : 'add')
|
||||
|
||||
const createdId = createTimeUnitId(timeUnit.tu_display_name!)
|
||||
|
||||
@@ -39,4 +47,16 @@ export const writeTimeUnit = async (
|
||||
}
|
||||
}
|
||||
|
||||
const createTimeUnitId = (displayName: string) => displayName.toLowerCase().replace(' ', '')
|
||||
export const deleteTimeUnit = async (id: string, user: User) => {
|
||||
const timeUnit = await getTimeUnitDetails(id)
|
||||
if (!timeUnit) throw new Error('Time unit not found')
|
||||
const writeHandler = getTimeUnitWriteHandler('delete')
|
||||
try {
|
||||
await writeHandler.start()
|
||||
await writeHandler.deleteObject('now_time_unit', timeUnit, ['tu_name'])
|
||||
await writeHandler.logUpdatesAndComplete(user.initials)
|
||||
} catch (e) {
|
||||
await writeHandler.end()
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,8 +119,6 @@ export class WriteHandler extends DatabaseHandler {
|
||||
await this.createObject(table, object, idColumns)
|
||||
} else if (rowState === 'removed') {
|
||||
await this.deleteObject(table, object, idColumns)
|
||||
} else {
|
||||
throw new Error('Invalid rowState in list item object while writing')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ export const LocalityDetails = () => {
|
||||
})
|
||||
const notify = useNotify()
|
||||
const [deleteMutation, { isSuccess: deleteSuccess, isError: deleteError }] = useDeleteLocalityMutation()
|
||||
|
||||
useEffect(() => {
|
||||
if (deleteSuccess) {
|
||||
notify('Deleted item successfully.')
|
||||
@@ -41,6 +42,7 @@ export const LocalityDetails = () => {
|
||||
notify('Could not delete item. Error happened.', 'error')
|
||||
}
|
||||
}, [deleteSuccess, deleteError, notify, navigate])
|
||||
|
||||
if (isError) return <div>Error loading data</div>
|
||||
if (isFetching || (!data && !isNew) || mutationLoading) return <CircularProgress />
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useEditSpeciesMutation, useGetSpeciesDetailsQuery } from '../../redux/speciesReducer'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useDeleteSpeciesMutation, useEditSpeciesMutation, useGetSpeciesDetailsQuery } from '../../redux/speciesReducer'
|
||||
import { CircularProgress } from '@mui/material'
|
||||
import { DetailView, TabType } from '../DetailView/DetailView'
|
||||
import { DietTab } from './Tabs/DietTab'
|
||||
@@ -13,15 +13,34 @@ import { TeethTab } from './Tabs/TeethTab'
|
||||
import { UpdateTab } from '../DetailView/common/UpdateTab'
|
||||
import { EditDataType, SpeciesDetailsType } from '@/backendTypes'
|
||||
import { emptySpecies } from '../DetailView/common/defaultValues'
|
||||
import { useNotify } from '@/hooks/notification'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export const SpeciesDetails = () => {
|
||||
const { id } = useParams()
|
||||
const isNew = id === 'new'
|
||||
const { isLoading, isError, isFetching, data } = useGetSpeciesDetailsQuery(id!, { skip: isNew })
|
||||
const [editSpeciesRequest] = useEditSpeciesMutation()
|
||||
const notify = useNotify()
|
||||
const navigate = useNavigate()
|
||||
const [deleteMutation, { isSuccess: deleteSuccess, isError: deleteError }] = useDeleteSpeciesMutation()
|
||||
|
||||
useEffect(() => {
|
||||
if (deleteSuccess) {
|
||||
notify('Deleted item successfully.')
|
||||
navigate('/species')
|
||||
} else if (deleteError) {
|
||||
notify('Could not delete item. Error happened.', 'error')
|
||||
}
|
||||
}, [deleteSuccess, deleteError, notify, navigate])
|
||||
|
||||
if (isError) return <div>Error loading data</div>
|
||||
if (isLoading || isFetching || (!data && !isNew)) return <CircularProgress />
|
||||
|
||||
const deleteFunction = async () => {
|
||||
await deleteMutation(parseInt(id!)).unwrap()
|
||||
}
|
||||
|
||||
const onWrite = async (editData: EditDataType<SpeciesDetailsType>) => {
|
||||
await editSpeciesRequest(editData)
|
||||
}
|
||||
@@ -76,6 +95,7 @@ export const SpeciesDetails = () => {
|
||||
name: 'unknown',
|
||||
error: null,
|
||||
})}
|
||||
deleteFunction={deleteFunction}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useEditTimeBoundMutation, useGetTimeBoundDetailsQuery } from '../../redux/timeBoundReducer'
|
||||
import { EditDataType, TimeBoundDetailsType } from '@/backendTypes.js'
|
||||
import { useNotify } from '@/hooks/notification.ts'
|
||||
import { CircularProgress } from '@mui/material'
|
||||
import { useEffect } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import {
|
||||
useDeleteTimeBoundMutation,
|
||||
useEditTimeBoundMutation,
|
||||
useGetTimeBoundDetailsQuery,
|
||||
} from '../../redux/timeBoundReducer'
|
||||
import { emptyTimeBound } from '../DetailView/common/defaultValues.ts'
|
||||
import { UpdateTab } from '../DetailView/common/UpdateTab.tsx'
|
||||
import { DetailView, TabType } from '../DetailView/DetailView'
|
||||
import { BoundTab } from './Tabs/BoundTab'
|
||||
import { TimeUnitTab } from './Tabs/TimeUnitTab.tsx'
|
||||
import { UpdateTab } from '../DetailView/common/UpdateTab.tsx'
|
||||
import { EditDataType, TimeBoundDetailsType } from '@/backendTypes.js'
|
||||
import { emptyTimeBound } from '../DetailView/common/defaultValues.ts'
|
||||
|
||||
export const TimeBoundDetails = () => {
|
||||
const { id } = useParams()
|
||||
@@ -15,9 +21,27 @@ export const TimeBoundDetails = () => {
|
||||
skip: isNew,
|
||||
})
|
||||
const [editTimeBoundRequest] = useEditTimeBoundMutation()
|
||||
|
||||
const notify = useNotify()
|
||||
const navigate = useNavigate()
|
||||
const [deleteMutation, { isSuccess: deleteSuccess, isError: deleteError }] = useDeleteTimeBoundMutation()
|
||||
|
||||
useEffect(() => {
|
||||
if (deleteSuccess) {
|
||||
notify('Deleted item successfully.')
|
||||
navigate('/time-bound')
|
||||
} else if (deleteError) {
|
||||
notify('Could not delete item. Error happened.', 'error')
|
||||
}
|
||||
}, [deleteSuccess, deleteError, notify, navigate])
|
||||
|
||||
if (isError) return <div>Error loading data</div>
|
||||
if (isLoading || isFetching || (!data && !isNew)) return <CircularProgress />
|
||||
|
||||
const deleteFunction = async () => {
|
||||
await deleteMutation(parseInt(id!)).unwrap()
|
||||
}
|
||||
|
||||
const onWrite = async (editedTimeBound: EditDataType<TimeBoundDetailsType>) => {
|
||||
await editTimeBoundRequest(editedTimeBound)
|
||||
}
|
||||
@@ -48,6 +72,7 @@ export const TimeBoundDetails = () => {
|
||||
name: 'unknown',
|
||||
error: null,
|
||||
})}
|
||||
deleteFunction={deleteFunction}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,21 +1,45 @@
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useEditTimeUnitMutation, useGetTimeUnitDetailsQuery } from '../../redux/timeUnitReducer'
|
||||
import { EditDataType, TimeUnitDetailsType } from '@/backendTypes'
|
||||
import { useNotify } from '@/hooks/notification'
|
||||
import { CircularProgress } from '@mui/material'
|
||||
import { useEffect } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import {
|
||||
useDeleteTimeUnitMutation,
|
||||
useEditTimeUnitMutation,
|
||||
useGetTimeUnitDetailsQuery,
|
||||
} from '../../redux/timeUnitReducer'
|
||||
import { emptyTimeUnit } from '../DetailView/common/defaultValues'
|
||||
import { UpdateTab } from '../DetailView/common/UpdateTab'
|
||||
import { DetailView, TabType } from '../DetailView/DetailView'
|
||||
import { LocalityTab } from './Tabs/LocalityTab'
|
||||
import { TimeUnitTab } from './Tabs/TimeUnitTab'
|
||||
import { UpdateTab } from '../DetailView/common/UpdateTab'
|
||||
import { EditDataType, TimeUnitDetailsType } from '@/backendTypes'
|
||||
import { emptyTimeUnit } from '../DetailView/common/defaultValues'
|
||||
|
||||
export const TimeUnitDetails = () => {
|
||||
const { id } = useParams()
|
||||
const isNew = id === 'new'
|
||||
const { isLoading, isError, isFetching, data } = useGetTimeUnitDetailsQuery(encodeURIComponent(id!), { skip: isNew })
|
||||
const [editTimeUnitRequest] = useEditTimeUnitMutation()
|
||||
|
||||
const notify = useNotify()
|
||||
const navigate = useNavigate()
|
||||
const [deleteMutation, { isSuccess: deleteSuccess, isError: deleteError }] = useDeleteTimeUnitMutation()
|
||||
|
||||
useEffect(() => {
|
||||
if (deleteSuccess) {
|
||||
notify('Deleted item successfully.')
|
||||
navigate('/time-unit')
|
||||
} else if (deleteError) {
|
||||
notify('Could not delete item. Error happened.', 'error')
|
||||
}
|
||||
}, [deleteSuccess, deleteError, notify, navigate])
|
||||
|
||||
if (isError) return <div>Error loading data</div>
|
||||
if (isLoading || isFetching || (!data && !isNew)) return <CircularProgress />
|
||||
|
||||
const deleteFunction = async () => {
|
||||
await deleteMutation(id!).unwrap()
|
||||
}
|
||||
|
||||
const onWrite = async (editData: EditDataType<TimeUnitDetailsType>) => {
|
||||
await editTimeUnitRequest(editData)
|
||||
}
|
||||
@@ -43,6 +67,7 @@ export const TimeUnitDetails = () => {
|
||||
data={isNew ? emptyTimeUnit : data!}
|
||||
onWrite={onWrite}
|
||||
validator={() => ({ name: '', error: null })}
|
||||
deleteFunction={deleteFunction}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,14 @@ const speciesApi = api.injectEndpoints({
|
||||
invalidatesTags: (result, _error, { species_id }) =>
|
||||
result ? [{ type: 'species', id: species_id }, 'specieslist'] : [],
|
||||
}),
|
||||
deleteSpecies: builder.mutation<void, number>({
|
||||
query: id => ({
|
||||
url: `/species/${id}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const { useGetAllSpeciesQuery, useGetSpeciesDetailsQuery, useEditSpeciesMutation } = speciesApi
|
||||
export const { useGetAllSpeciesQuery, useGetSpeciesDetailsQuery, useEditSpeciesMutation, useDeleteSpeciesMutation } =
|
||||
speciesApi
|
||||
|
||||
@@ -28,6 +28,12 @@ const timeboundsApi = api.injectEndpoints({
|
||||
}),
|
||||
invalidatesTags: (result, _error, { bid }) => (result ? [{ type: 'timebound', id: bid }, 'timebounds'] : []),
|
||||
}),
|
||||
deleteTimeBound: builder.mutation<void, number>({
|
||||
query: id => ({
|
||||
url: `/time-bound/${id}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -36,4 +42,5 @@ export const {
|
||||
useGetTimeBoundDetailsQuery,
|
||||
useGetTimeBoundTimeUnitsQuery,
|
||||
useEditTimeBoundMutation,
|
||||
useDeleteTimeBoundMutation,
|
||||
} = timeboundsApi
|
||||
|
||||
@@ -34,6 +34,13 @@ const timeunitsApi = api.injectEndpoints({
|
||||
invalidatesTags: (result, _error, { tu_name }) =>
|
||||
result ? [{ type: 'timeunit', id: tu_name }, 'timeunits'] : [],
|
||||
}),
|
||||
deleteTimeUnit: builder.mutation<void, string>({
|
||||
query: id => ({
|
||||
url: `/time-unit/${id}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
invalidatesTags: ['timeunits'],
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -43,4 +50,5 @@ export const {
|
||||
useGetTimeUnitDetailsQuery,
|
||||
useEditTimeUnitMutation,
|
||||
useGetSequencesQuery,
|
||||
useDeleteTimeUnitMutation,
|
||||
} = timeunitsApi
|
||||
|
||||
Reference in New Issue
Block a user