mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Merge pull request #922 from nowcommunity/fix-museum-issues
Fix museum related issues and return to table button issues
This commit is contained in:
@@ -32,13 +32,9 @@ describe('Creating new museum works', () => {
|
||||
})
|
||||
|
||||
it('Contains correct data', () => {
|
||||
const { museum: museumId, institution, used_morph, used_now, used_gene } = createdMuseum!
|
||||
const { museum: museumId, institution } = createdMuseum!
|
||||
expect(museumId).toBeDefined()
|
||||
expect(institution).toEqual('Australian Museum') // 'Institution name is different'
|
||||
expect(used_morph).toEqual(true)
|
||||
// fixRadioSelection converts null values into false
|
||||
expect(used_now).toEqual(false)
|
||||
expect(used_gene).toEqual(false)
|
||||
})
|
||||
|
||||
it('Creation fails with empty museum code', async () => {
|
||||
|
||||
@@ -8,9 +8,6 @@ export const newMuseumBasis: Museum = {
|
||||
state_code: '',
|
||||
state: '',
|
||||
country: 'Australia',
|
||||
used_morph: true,
|
||||
used_now: null,
|
||||
used_gene: null,
|
||||
}
|
||||
|
||||
export const editedMuseum: Museum = {
|
||||
@@ -21,7 +18,4 @@ export const editedMuseum: Museum = {
|
||||
state_code: 'NSW',
|
||||
state: 'New South Wales',
|
||||
country: 'Australia',
|
||||
used_morph: false,
|
||||
used_now: true,
|
||||
used_gene: null,
|
||||
}
|
||||
|
||||
@@ -32,32 +32,11 @@ describe('Updating museum works', () => {
|
||||
})
|
||||
|
||||
it('Contains correct data', () => {
|
||||
const { museum, city, state, state_code, used_morph, used_now, used_gene } = updatedMuseum!
|
||||
const { museum, city, state, state_code } = updatedMuseum!
|
||||
expect(museum).toEqual('AM')
|
||||
expect(city).toEqual('Canberra')
|
||||
expect(state).toEqual('New South Wales')
|
||||
expect(state_code).toEqual('NSW')
|
||||
expect(used_morph).toEqual(false)
|
||||
expect(used_now).toEqual(true)
|
||||
expect(used_gene).toEqual(false) // fixRadioSelection converts null values into false
|
||||
})
|
||||
|
||||
it('Updating succeeds with string values for used_fields', async () => {
|
||||
const { body: resultBody, status: putReqStatus } = await send<{ museum: string }>('museum/', 'PUT', {
|
||||
museum: { ...editedMuseum, used_morph: 'true', used_now: 'true', used_gene: 'true' },
|
||||
})
|
||||
const { museum: updatedId } = resultBody
|
||||
|
||||
expect(typeof updatedId).toEqual('string') // `Invalid result returned on write: ${createdId}`
|
||||
expect(putReqStatus).toEqual(200)
|
||||
|
||||
const { body: getReqBody, status: getReqStat } = await send<Museum>(`museum/${updatedId}`, 'GET')
|
||||
expect(getReqStat).toEqual(200)
|
||||
|
||||
const { used_morph, used_now, used_gene } = getReqBody
|
||||
expect(used_morph).toEqual(true)
|
||||
expect(used_now).toEqual(true)
|
||||
expect(used_gene).toEqual(true)
|
||||
})
|
||||
|
||||
it('Updating fails with empty institution', async () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import { Button, Box, Typography, CircularProgress, Divider, alpha, List, ListItemText } from '@mui/material'
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack'
|
||||
import SaveIcon from '@mui/icons-material/Save'
|
||||
@@ -258,6 +258,7 @@ export const ReturnButton = () => {
|
||||
const navigate = useNavigate()
|
||||
const { setPreviousTableUrls, previousTableUrls } = usePageContext()
|
||||
const { mode, setMode } = useDetailContext()
|
||||
const location = useLocation()
|
||||
|
||||
if (mode.staging) {
|
||||
return (
|
||||
@@ -282,6 +283,10 @@ export const ReturnButton = () => {
|
||||
newUrls.splice(-1)
|
||||
setPreviousTableUrls(newUrls)
|
||||
navigate(previousTableUrl, { relative: 'path' })
|
||||
} else {
|
||||
// this should only happen if the user navigates to e.g. a detail view directly with an url,
|
||||
// instead of using link in the app
|
||||
navigate(location.pathname.substring(0, location.pathname.indexOf('/', 1)), { relative: 'path' })
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -57,6 +57,8 @@ export const MuseumTab = () => {
|
||||
<EditableTable<Editable<Museum>, LocalityDetailsType>
|
||||
columns={columns.map(col => ({ ...col, accessorKey: `com_mlist.${col.accessorKey}` }))}
|
||||
field="now_mus"
|
||||
idFieldName="museum"
|
||||
url="museum"
|
||||
/>
|
||||
</Grouped>
|
||||
)
|
||||
|
||||
@@ -16,7 +16,7 @@ export const MuseumDetails = () => {
|
||||
skip: isNew,
|
||||
})
|
||||
const [editMuseumRequest, { isLoading: mutationLoading }] = useEditMuseumMutation()
|
||||
const notify = useNotify()
|
||||
const { notify } = useNotify()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const tabs: TabType[] = [
|
||||
@@ -55,7 +55,6 @@ export const MuseumDetails = () => {
|
||||
isNew={isNew}
|
||||
validator={validateMuseum}
|
||||
deleteFunction={undefined}
|
||||
hasStagingMode
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,12 +23,16 @@ export const LocalityTab = ({ isNew }: { isNew: boolean }) => {
|
||||
header: 'Min Age',
|
||||
},
|
||||
]
|
||||
if (isNew)
|
||||
|
||||
if (isNew) {
|
||||
return (
|
||||
<div>
|
||||
Link localities to this museum after finalizing it by editing a locality and navigating to the museum tab there.
|
||||
</div>
|
||||
)
|
||||
} else if (data.localities.length === 0) {
|
||||
return <div>Link localities to this museum by editing a locality and navigating to the museum tab there.</div>
|
||||
}
|
||||
|
||||
return <SimpleTable columns={columns} data={data.localities} idFieldName="lid" url="locality" />
|
||||
}
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
import { ArrayFrame } from '@/components/DetailView/common/tabLayoutHelpers'
|
||||
import { useDetailContext } from '@/components/DetailView/Context/DetailContext'
|
||||
import { modeOptionToMode, useDetailContext } from '@/components/DetailView/Context/DetailContext'
|
||||
import { useNotify } from '@/hooks/notification'
|
||||
import { Museum } from '@/shared/types'
|
||||
import { validCountries } from '@/shared/validators/countryList'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export const MuseumInfoTab = ({ isNew }: { isNew?: boolean }) => {
|
||||
const { textField, radioSelection, dropdownWithSearch } = useDetailContext<Museum>()
|
||||
const { textField, dropdownWithSearch, mode } = useDetailContext<Museum>()
|
||||
const { notify } = useNotify()
|
||||
|
||||
useEffect(() => {
|
||||
if (mode === modeOptionToMode['new']) {
|
||||
notify(
|
||||
"Due to current limitations, using an existing museum's code will overwrite that museum with the one you are currently creating. \n \
|
||||
Check that you are using a unique museum code.",
|
||||
'warning',
|
||||
null
|
||||
)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [mode])
|
||||
|
||||
const countryOptions = ['', ...validCountries]
|
||||
|
||||
@@ -15,40 +30,7 @@ export const MuseumInfoTab = ({ isNew }: { isNew?: boolean }) => {
|
||||
['Country', dropdownWithSearch('country', countryOptions, 'Country')],
|
||||
['State', textField('state')],
|
||||
['State code', textField('state_code')],
|
||||
[
|
||||
'Used morph',
|
||||
radioSelection(
|
||||
'used_morph',
|
||||
[
|
||||
{ value: 'null', display: 'No' },
|
||||
{ value: 'true', display: 'Yes' },
|
||||
],
|
||||
'used-morph'
|
||||
),
|
||||
],
|
||||
[
|
||||
'Used now',
|
||||
radioSelection(
|
||||
'used_now',
|
||||
[
|
||||
{ value: 'null', display: 'No' },
|
||||
{ value: 'true', display: 'Yes' },
|
||||
],
|
||||
'used-now'
|
||||
),
|
||||
],
|
||||
[
|
||||
'Used gene',
|
||||
radioSelection(
|
||||
'used_gene',
|
||||
[
|
||||
{ value: 'null', display: 'No' },
|
||||
{ value: 'true', display: 'Yes' },
|
||||
],
|
||||
'used-gene'
|
||||
),
|
||||
],
|
||||
['Museum code', textField('museum', { type: 'text', readonly: !isNew })],
|
||||
['Museum code', textField('museum', { type: 'text', readonly: !isNew, trim: true })],
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
@@ -47,7 +47,7 @@ export const PageContextProvider = <T extends object>({
|
||||
editRights: EditRights
|
||||
}) => {
|
||||
const [idList, setIdList] = useState<string[]>([])
|
||||
const [previousTableUrls, setPreviousTableUrls] = useState<string[]>([`/${viewName}`])
|
||||
const [previousTableUrls, setPreviousTableUrls] = useState<string[]>([])
|
||||
// TODO: replace with some default values from variables
|
||||
const [sqlLimit, setSqlLimit] = useState<number>(defaultPagination.pageSize)
|
||||
const [sqlOffset, setSqlOffset] = useState<number>(0)
|
||||
|
||||
@@ -5,9 +5,10 @@ import { ContactForm } from '../DetailView/common/ContactForm'
|
||||
import FileDownloadIcon from '@mui/icons-material/FileDownload'
|
||||
import '../../styles/TableToolBar.css'
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
import AddCircleIcon from '@mui/icons-material/AddCircle'
|
||||
import { CrossSearchExportMenuItem } from '../CrossSearch/CrossSearchExportMenuItem'
|
||||
import { usePageContext } from '../Page'
|
||||
|
||||
export const TableToolBar = <T extends MRT_RowData>({
|
||||
table,
|
||||
@@ -28,6 +29,8 @@ export const TableToolBar = <T extends MRT_RowData>({
|
||||
selectorFn?: (id: T) => void
|
||||
showNewButton?: boolean
|
||||
}) => {
|
||||
const { previousTableUrls, setPreviousTableUrls } = usePageContext<T>()
|
||||
const location = useLocation()
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
|
||||
const open = Boolean(anchorEl)
|
||||
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
@@ -44,7 +47,14 @@ export const TableToolBar = <T extends MRT_RowData>({
|
||||
<ContactForm<T> buttonText="Contact" noContext={true} />
|
||||
|
||||
{showNewButton && (
|
||||
<Button variant="outlined" component={Link} to="new" className="button" startIcon={<AddCircleIcon />}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
component={Link}
|
||||
to="new"
|
||||
className="button"
|
||||
startIcon={<AddCircleIcon />}
|
||||
onClick={() => setPreviousTableUrls([...previousTableUrls, `${location.pathname}`])}
|
||||
>
|
||||
New
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -23,7 +23,7 @@ export type LocalitySpeciesDetailsType = FixBigInt<Prisma.now_ls> & { com_specie
|
||||
export type SpeciesLocality = FixBigInt<Prisma.now_ls> & { now_loc: Prisma.now_loc }
|
||||
export type LocalityUpdate = Prisma.now_lau & { now_lr: LocalityReference[] } & { updates: UpdateLog[] }
|
||||
export type SpeciesUpdate = Prisma.now_sau & { now_sr: SpeciesReference[] } & { updates: UpdateLog[] }
|
||||
export type Museum = Prisma.com_mlist
|
||||
export type Museum = Omit<Prisma.com_mlist, 'used_morph' | 'used_now' | 'used_gene'>
|
||||
export type MuseumLocalities = Prisma.com_mlist & { localities: Prisma.now_loc[] }
|
||||
export type PersonDetailsType = Prisma.com_people & { user: Omit<Prisma.com_users, 'password, newpassword'> | null } & {
|
||||
now_user_group: string
|
||||
|
||||
@@ -19,6 +19,11 @@ export const validateMuseum = (editData: EditDataType<Museum>, fieldName: keyof
|
||||
museum: {
|
||||
name: 'Museum',
|
||||
required: true,
|
||||
asString: museumCode => {
|
||||
if (museumCode.indexOf(' ') !== -1) return 'Museum code must not contain a space'
|
||||
if (museumCode.toUpperCase() !== museumCode) return 'Museum code must only contains uppercase characters'
|
||||
return null
|
||||
},
|
||||
},
|
||||
institution: {
|
||||
name: 'Institution',
|
||||
|
||||
Reference in New Issue
Block a user