mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Merge branch 'main' into update-region-docs
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { beforeEach, beforeAll, afterAll, describe, it, expect } from '@jest/globals'
|
||||
import { login, logout, resetDatabase, send, resetDatabaseTimeout } from '../utils'
|
||||
import { pool } from '../../utils/db'
|
||||
|
||||
describe('Deleting a region works', () => {
|
||||
beforeAll(async () => {
|
||||
await resetDatabase()
|
||||
}, resetDatabaseTimeout)
|
||||
beforeEach(async () => {
|
||||
await login()
|
||||
})
|
||||
afterAll(async () => {
|
||||
await pool.end()
|
||||
})
|
||||
|
||||
it('Deleting returns correct status and after that is not found on request', async () => {
|
||||
const deleteResult = await send<{ id: number }>('region/1', 'DELETE')
|
||||
expect(deleteResult.status).toEqual(200)
|
||||
const getResult = await send('region/1', 'GET')
|
||||
expect(getResult.status).toEqual(404) // 'Region response status was not 404 after deletion'
|
||||
})
|
||||
|
||||
it('Deleting fails without permissions', async () => {
|
||||
logout()
|
||||
const deleteResultNoPerm = await send<{ id: number }>('region/2', 'DELETE')
|
||||
expect(deleteResultNoPerm.status).toEqual(403)
|
||||
|
||||
await login('testEr')
|
||||
const deleteResultEr = await send<{ id: number }>('region/2', 'DELETE')
|
||||
expect(deleteResultEr.status).toEqual(403)
|
||||
|
||||
await login('testEu')
|
||||
const deleteResultEu = await send<{ id: number }>('region/2', 'DELETE')
|
||||
expect(deleteResultEu.status).toEqual(403)
|
||||
|
||||
await login()
|
||||
const getResultSu = await send('region/2', 'GET')
|
||||
expect(getResultSu.status).toEqual(200)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
import { beforeAll, afterAll, describe, it, expect, beforeEach } from '@jest/globals'
|
||||
import { login, logout, resetDatabase, send, resetDatabaseTimeout } from '../utils'
|
||||
import { pool } from '../../utils/db'
|
||||
|
||||
describe('Deleting a region works', () => {
|
||||
beforeAll(async () => {
|
||||
await resetDatabase()
|
||||
}, resetDatabaseTimeout)
|
||||
beforeEach(async () => {
|
||||
await login()
|
||||
})
|
||||
afterAll(async () => {
|
||||
await pool.end()
|
||||
})
|
||||
|
||||
it('Getting region data succeeds with admin privileges', async () => {
|
||||
const getResultSu = await send('region/2', 'GET')
|
||||
expect(getResultSu.status).toEqual(200)
|
||||
})
|
||||
|
||||
it('Getting region data fails without permissions', async () => {
|
||||
logout()
|
||||
const getResultNoPerm = await send('region/2', 'GET')
|
||||
expect(getResultNoPerm.status).toEqual(403)
|
||||
|
||||
await login('testEr')
|
||||
const getResultEr = await send('region/2', 'GET')
|
||||
expect(getResultEr.status).toEqual(403)
|
||||
|
||||
await login('testEu')
|
||||
const getResultEu = await send('region/2', 'GET')
|
||||
expect(getResultEu.status).toEqual(403)
|
||||
})
|
||||
})
|
||||
@@ -2,7 +2,7 @@ import { Router, Request } from 'express'
|
||||
import { getAllRegions, getRegionDetails, validateEntireRegion } from '../services/region'
|
||||
import { requireOneOf } from '../middlewares/authorizer'
|
||||
import { Role, EditDataType, EditMetaData, RegionDetails } from '../../../frontend/src/shared/types'
|
||||
import { writeRegion } from '../services/write/region'
|
||||
import { writeRegion, deleteRegion } from '../services/write/region'
|
||||
|
||||
const router = Router()
|
||||
|
||||
@@ -32,4 +32,10 @@ router.put(
|
||||
}
|
||||
)
|
||||
|
||||
router.delete('/:id', requireOneOf([Role.Admin]), async (req, res) => {
|
||||
const id = parseInt(req.params.id)
|
||||
await deleteRegion(id)
|
||||
res.status(200).send()
|
||||
})
|
||||
|
||||
export default router
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { EditDataType, RegionCountry, RegionDetails, RegionCoordinator } from '../../../../frontend/src/shared/types'
|
||||
import Prisma from '../../../prisma/generated/now_test_client'
|
||||
import { nowDb, getFieldsOfTables } from '../../utils/db'
|
||||
import { getRegionDetails } from '../region'
|
||||
import { filterAllowedKeys } from './writeOperations/utils'
|
||||
|
||||
export const writeRegionCountries = async (regionId: number, countries: EditDataType<RegionCountry[]>) => {
|
||||
@@ -72,3 +73,27 @@ export const writeRegion = async (region: EditDataType<RegionDetails>) => {
|
||||
|
||||
return regionId
|
||||
}
|
||||
|
||||
export const deleteRegion = async (regionId: number) => {
|
||||
const region = await getRegionDetails(regionId)
|
||||
|
||||
if (!region) throw new Error('Region not found')
|
||||
|
||||
await nowDb.$transaction(async prisma => {
|
||||
await prisma.now_reg_coord_country.deleteMany({
|
||||
where: { reg_coord_id: regionId },
|
||||
})
|
||||
|
||||
await prisma.now_reg_coord_people.deleteMany({
|
||||
where: { reg_coord_id: regionId },
|
||||
})
|
||||
|
||||
try {
|
||||
await prisma.now_reg_coord.delete({
|
||||
where: { reg_coord_id: regionId },
|
||||
})
|
||||
} catch (error) {
|
||||
throw new Error('Failed to delete the region')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -110,3 +110,20 @@ describe('Editing a region', () => {
|
||||
cy.get('[id=country-add-button]').should('be.disabled')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Deleting a region', () => {
|
||||
beforeEach('Login as admin', () => {
|
||||
cy.login('testSu')
|
||||
})
|
||||
|
||||
it('works and returns user to table view', () => {
|
||||
cy.visit('/region/1')
|
||||
cy.get('[id=delete-button]').should('exist').click()
|
||||
cy.on('window:confirm', str => {
|
||||
expect(str).to.eq('Are you sure you want to delete this item? This operation cannot be undone.')
|
||||
// this automatically clicks the OK button and returns to table view
|
||||
})
|
||||
cy.contains('region 44524b6e')
|
||||
cy.contains('region 4452477e').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useEditRegionMutation, useGetRegionDetailsQuery } from '../../redux/regionReducer'
|
||||
import { useEditRegionMutation, useGetRegionDetailsQuery, useDeleteRegionMutation } from '../../redux/regionReducer'
|
||||
import { CircularProgress } from '@mui/material'
|
||||
import { DetailView, TabType } from '../DetailView/DetailView'
|
||||
import { CoordinatorTab } from './Tabs/CoordinatorTab'
|
||||
import { EditDataType, RegionDetails as RegionDetailsType, ValidationErrors } from '@/shared/types'
|
||||
import { useNotify } from '@/hooks/notification'
|
||||
import { validateRegion } from '@/shared/validators/region'
|
||||
import { useEffect } from 'react'
|
||||
import { emptyRegion } from '../DetailView/common/defaultValues'
|
||||
|
||||
export const RegionDetails = () => {
|
||||
@@ -13,10 +14,21 @@ export const RegionDetails = () => {
|
||||
const isNew = id === 'new'
|
||||
const { isLoading, isError, data } = useGetRegionDetailsQuery(id!, { skip: isNew })
|
||||
const [editRegionRequest, { isLoading: mutationLoading }] = useEditRegionMutation()
|
||||
const [deleteMutation, { isSuccess: deleteSuccess, isError: deleteError }] = useDeleteRegionMutation()
|
||||
const notify = useNotify()
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(() => {
|
||||
if (deleteSuccess) {
|
||||
notify('Deleted item successfully.')
|
||||
navigate('/region')
|
||||
} 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 || (!data && !isNew) || mutationLoading) return <CircularProgress />
|
||||
|
||||
document.title = isNew ? 'New region' : data!.region
|
||||
@@ -32,6 +44,10 @@ export const RegionDetails = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const deleteFunction = async () => {
|
||||
await deleteMutation(parseInt(id!)).unwrap()
|
||||
}
|
||||
|
||||
const tabs: TabType[] = [
|
||||
{
|
||||
title: 'Regional',
|
||||
@@ -46,6 +62,7 @@ export const RegionDetails = () => {
|
||||
data={isNew ? emptyRegion : data!}
|
||||
onWrite={onWrite}
|
||||
validator={validateRegion}
|
||||
deleteFunction={deleteFunction}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,15 @@ const regionsApi = api.injectEndpoints({
|
||||
invalidatesTags: (result, _error, { reg_coord_id }) =>
|
||||
result ? [{ type: 'region', id: reg_coord_id }, 'regions'] : [],
|
||||
}),
|
||||
deleteRegion: builder.mutation<void, number>({
|
||||
query: id => ({
|
||||
url: `/region/${id}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
invalidatesTags: ['regions'],
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const { useGetAllRegionsQuery, useGetRegionDetailsQuery, useEditRegionMutation } = regionsApi
|
||||
export const { useGetAllRegionsQuery, useGetRegionDetailsQuery, useEditRegionMutation, useDeleteRegionMutation } =
|
||||
regionsApi
|
||||
|
||||
Reference in New Issue
Block a user