mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Added Regions with Coordinators and Countries
This commit is contained in:
@@ -4,6 +4,7 @@ import 'express-async-errors'
|
||||
import userRouter from './routes/user'
|
||||
import localityRouter from './routes/locality'
|
||||
import referenceRouter from './routes/reference'
|
||||
import regionRouter from './routes/region'
|
||||
import speciesRouter from './routes/species'
|
||||
import timeUnitRouter from './routes/timeUnit'
|
||||
import museumRouter from './routes/museum'
|
||||
@@ -30,6 +31,7 @@ if (BACKEND_MODE !== 'dev') app.use(requireLogin)
|
||||
|
||||
app.use('/locality', localityRouter)
|
||||
app.use('/reference', referenceRouter)
|
||||
app.use('/region', regionRouter)
|
||||
app.use('/species', speciesRouter)
|
||||
app.use('/time-unit', timeUnitRouter)
|
||||
app.use('/museum', museumRouter)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Router } from 'express'
|
||||
import { getAllRegions, getRegionDetails } from '../services/region'
|
||||
|
||||
const router = Router()
|
||||
|
||||
router.get('/all', async (_req, res) => {
|
||||
const regions = await getAllRegions()
|
||||
return res.status(200).send(regions)
|
||||
})
|
||||
|
||||
router.get('/:id', async (req, res) => {
|
||||
const id = parseInt(req.params.id)
|
||||
const region = await getRegionDetails(id)
|
||||
res.status(200).send(region)
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -0,0 +1,23 @@
|
||||
import { prisma } from '../utils/db'
|
||||
|
||||
export const getAllRegions = async () => {
|
||||
const result = await prisma.now_reg_coord.findMany({})
|
||||
return result
|
||||
}
|
||||
|
||||
export const getRegionDetails = async (id: number) => {
|
||||
// TODO: Check if user has access
|
||||
|
||||
const result = await prisma.now_reg_coord.findUnique({
|
||||
where: { reg_coord_id: id },
|
||||
include: {
|
||||
now_reg_coord_country: {},
|
||||
now_reg_coord_people: {
|
||||
include: {
|
||||
com_people: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
return result
|
||||
}
|
||||
@@ -21,3 +21,8 @@ export const createTestUser = async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getAllUsers = async () => {
|
||||
const result = await prisma.com_users.findMany({})
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import { NavBar } from './components/NavBar'
|
||||
import { BrowserRouter, Route, Routes } from 'react-router-dom'
|
||||
import { LocalityTable } from './components/Locality/LocalityTable'
|
||||
import { ReferenceTable } from './components/Reference/ReferenceTable'
|
||||
import { RegionTable } from './components/Region/RegionTable'
|
||||
import { RegionDetails } from './components/Region/RegionDetails'
|
||||
import { SpeciesTable } from './components/Species/SpeciesTable'
|
||||
import { TimeUnitTable } from './components/TimeUnit/TimeUnitTable'
|
||||
import { Login } from './components/Login'
|
||||
@@ -25,6 +27,8 @@ const App = () => {
|
||||
<Route element={<LocalityDetails />} path="/locality/:id" />
|
||||
<Route element={<LocalityTable />} path="/locality/" />
|
||||
<Route element={<ReferenceTable />} path="/reference/" />
|
||||
<Route element={<RegionTable />} path="/region/" />
|
||||
<Route element={<RegionDetails />} path="/region/:id" />
|
||||
<Route element={<SpeciesDetails />} path="/species/:id" />
|
||||
<Route element={<SpeciesTable />} path="/species/" />
|
||||
<Route element={<TimeUnitTable />} path="/time-unit/" />
|
||||
|
||||
Vendored
+4
@@ -14,6 +14,9 @@ export type LocalityUpdate = Prisma.now_lau & { now_lr: Prisma.now_lr }
|
||||
export type SpeciesUpdate = Prisma.now_sau & { now_lr: Prisma.now_sr }
|
||||
export type Museum = Prisma.com_mlist
|
||||
export type Project = Prisma.now_proj
|
||||
export type Region = Prisma.now_reg_coord
|
||||
export type RegionCoordinator = Prisma.now_reg_coord_people
|
||||
export type RegionCountry = Prisma.now_reg_coord_country
|
||||
export type SedimentaryStructure = Prisma.now_ss
|
||||
export type LocalitySynonym = Prisma.now_syn_loc
|
||||
export type SpeciesSynonym = Prisma.com_taxa_synonym
|
||||
@@ -70,6 +73,7 @@ export type Reference = {
|
||||
}
|
||||
|
||||
export type ReferenceDetails = Prisma.ref_ref
|
||||
export type RegionDetails = Prisma.now_reg_coord & { now_reg_coord_people: Array<Editable<RegionCoordinator>> }
|
||||
|
||||
export type TimeUnit = {
|
||||
low_bound: number
|
||||
|
||||
@@ -16,6 +16,8 @@ export const NavBar = () => {
|
||||
{ title: 'Species', url: '/species' },
|
||||
{ title: 'Reference', url: '/reference' },
|
||||
{ title: 'Time unit', url: '/time-unit' },
|
||||
{ title: 'Region', url: '/region' },
|
||||
{ title: 'Admin', url: '/admin' },
|
||||
]
|
||||
|
||||
if (user.username === null) pages.push({ title: 'Login', url: '/login' })
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useGetRegionDetailsQuery } from '../../redux/regionReducer'
|
||||
import { CircularProgress } from '@mui/material'
|
||||
import { DetailView, TabType } from '../DetailView/DetailView'
|
||||
import { CoordinatorTab } from './Tabs/CoordinatorTab'
|
||||
|
||||
export const RegionDetails = () => {
|
||||
const { id } = useParams()
|
||||
const { isLoading, isError, data } = useGetRegionDetailsQuery(id!)
|
||||
|
||||
if (isError) return <div>Error loading data</div>
|
||||
if (isLoading || !data) return <CircularProgress />
|
||||
|
||||
const tabs: TabType[] = [
|
||||
{
|
||||
title: 'Regional',
|
||||
content: <CoordinatorTab />,
|
||||
},
|
||||
]
|
||||
|
||||
return <DetailView tabs={tabs} data={data} onWrite={() => {}} validator={() => null} />
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { useMemo, ReactNode } from 'react'
|
||||
import { type MRT_ColumnDef } from 'material-react-table'
|
||||
import { useGetAllRegionsQuery } from '../../redux/regionReducer'
|
||||
import { Region } from '@/backendTypes'
|
||||
import { TableView } from '../TableView/TableView'
|
||||
import { Box, Tooltip } from '@mui/material'
|
||||
|
||||
const Cell = ({ renderedCellValue }: { renderedCellValue: ReactNode }) => (
|
||||
<Tooltip title={renderedCellValue}>
|
||||
<Box sx={{ maxWidth: '260px', WebkitMaskImage: 'linear-gradient(to right, #000 90%, transparent)' }}>
|
||||
{renderedCellValue}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
export const RegionTable = ({ selectorFn }: { selectorFn?: (id: Region) => void }) => {
|
||||
const regionQuery = useGetAllRegionsQuery()
|
||||
const columns = useMemo<MRT_ColumnDef<Region>[]>(
|
||||
() => [
|
||||
{
|
||||
id: 'id',
|
||||
accessorKey: 'reg_coord_id',
|
||||
header: 'Region Id',
|
||||
size: 20,
|
||||
},
|
||||
{
|
||||
accessorKey: 'region',
|
||||
header: 'Region',
|
||||
maxSize: 60,
|
||||
},
|
||||
],
|
||||
[]
|
||||
)
|
||||
const checkRowRestriction = () => {
|
||||
return false
|
||||
}
|
||||
|
||||
return (
|
||||
<TableView<Region>
|
||||
selectorFn={selectorFn}
|
||||
checkRowRestriction={checkRowRestriction}
|
||||
idFieldName="reg_coord_id"
|
||||
columns={columns}
|
||||
data={regionQuery.data}
|
||||
url="region"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Editable, RegionDetails, RegionCoordinator, RegionCountry } from '@/backendTypes'
|
||||
import { useDetailContext } from '@/components/DetailView/hooks'
|
||||
import { Grouped } from '@/components/DetailView/common/tabLayoutHelpers'
|
||||
import { MRT_ColumnDef } from 'material-react-table'
|
||||
import { EditableTable } from '@/components/DetailView/common/EditableTable'
|
||||
|
||||
export const CoordinatorTab = () => {
|
||||
const { editData, mode } = useDetailContext<RegionDetails>()
|
||||
const coordinator: MRT_ColumnDef<RegionCoordinator>[] = [
|
||||
{
|
||||
accessorKey: 'com_people.surname',
|
||||
header: 'Surname',
|
||||
},
|
||||
{
|
||||
accessorKey: 'com_people.first_name',
|
||||
header: 'First name',
|
||||
},
|
||||
{
|
||||
accessorKey: 'com_people.organization',
|
||||
header: 'Organization',
|
||||
},
|
||||
]
|
||||
|
||||
const country: MRT_ColumnDef<RegionCountry>[] = [
|
||||
{
|
||||
accessorKey: 'country',
|
||||
header: 'Country',
|
||||
},
|
||||
]
|
||||
|
||||
// TODO: Selecting existing User or Country
|
||||
return (
|
||||
<>
|
||||
<Grouped title="Regional Coordinators">
|
||||
{mode === 'edit'}
|
||||
<EditableTable<Editable<RegionCoordinator>, RegionDetails>
|
||||
columns={coordinator}
|
||||
data={editData.now_reg_coord_people}
|
||||
editable
|
||||
field="now_reg_coord_people"
|
||||
/>
|
||||
</Grouped>
|
||||
<Grouped title="Countries">
|
||||
{mode === 'edit'}
|
||||
<EditableTable<Editable<RegionCountry>, RegionDetails>
|
||||
columns={country}
|
||||
data={editData.now_reg_coord_country}
|
||||
editable
|
||||
field="now_reg_coord_country"
|
||||
/>
|
||||
</Grouped>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { api } from './api'
|
||||
import { Region, RegionDetails } from '@/backendTypes'
|
||||
|
||||
const regionsApi = api.injectEndpoints({
|
||||
endpoints: builder => ({
|
||||
getAllRegions: builder.query<Region[], void>({
|
||||
query: () => ({
|
||||
url: `/region/all`,
|
||||
}),
|
||||
}),
|
||||
getRegionDetails: builder.query<RegionDetails, string>({
|
||||
query: id => ({
|
||||
url: `/region/${id}`,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const { useGetAllRegionsQuery, useGetRegionDetailsQuery } = regionsApi
|
||||
Reference in New Issue
Block a user