diff --git a/src/components/DateFilter.tsx b/src/components/DateFilter.tsx index d66d5f19..dc2abcc3 100644 --- a/src/components/DateFilter.tsx +++ b/src/components/DateFilter.tsx @@ -37,12 +37,9 @@ const getFilter = (value: Values, source: string, format: string): Filter[] => { return formattedDate } - const now = formatter(DateTime.now()) const gteKeyName: string = `${source}_gte` const lteKeyName: string = `${source}_lte` - const todayFilter: Filter = { key: lteKeyName, value: now } - const resetTodayFilter: Filter = { key: source, value: undefined } const resetGTFilter: Filter = { key: gteKeyName, value: undefined } const resetLTFilter: Filter = { key: lteKeyName, value: undefined } @@ -63,7 +60,10 @@ const getFilter = (value: Values, source: string, format: string): Filter[] => { case 'past_week': return [ resetTodayFilter, - todayFilter, + { + key: lteKeyName, + value: DateTime.now().endOf('day').toISO() ?? '' + }, { key: gteKeyName, value: minusFromNow('week') @@ -72,7 +72,10 @@ const getFilter = (value: Values, source: string, format: string): Filter[] => { case 'past_month': return [ resetTodayFilter, - todayFilter, + { + key: lteKeyName, + value: DateTime.now().endOf('day').toISO() ?? '' + }, { key: gteKeyName, value: minusFromNow('month') @@ -81,7 +84,10 @@ const getFilter = (value: Values, source: string, format: string): Filter[] => { case 'past_year': return [ resetTodayFilter, - todayFilter, + { + key: lteKeyName, + value: DateTime.now().endOf('day').toISO() ?? '' + }, { key: gteKeyName, value: minusFromNow('year') diff --git a/src/components/Layout/Footer.tsx b/src/components/Layout/Footer.tsx index 2a399106..6dee69a0 100644 --- a/src/components/Layout/Footer.tsx +++ b/src/components/Layout/Footer.tsx @@ -3,7 +3,10 @@ import preval from 'preval.macro' const Footer = (): React.ReactElement => { const buildDate = preval`module.exports = new Date().toISOString().slice(0, 19).replace('T', ' ')` - const trimmedAppBuildDate = buildDate.substring(0, buildDate.length - 3) + const trimmedAppBuildDate = `Build Date: ${buildDate.substring( + 0, + buildDate.length - 3 + )}` return (
source='fullAddress' /> source='active' looseValue /> source='createdAt' /> - source='Remarks' /> + source='remarks' /> ) diff --git a/src/resources/addresses/index.tsx b/src/resources/addresses/index.tsx index 8ae0f30f..b7acdcbf 100644 --- a/src/resources/addresses/index.tsx +++ b/src/resources/addresses/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Create, Edit, Show } from 'react-admin' +import { Create, Edit, Show, useRedirect } from 'react-admin' import * as constants from '../../constants' const AddressList = React.lazy(async () => await import('./AddressList')) const AddressForm = React.lazy(async () => await import('./AddressForm')) @@ -13,8 +13,15 @@ const AddressCreate = (): React.ReactElement => { } export const AddressEdit = (): React.ReactElement => { + const redirect = useRedirect() return ( - + { + redirect(`/${constants.R_ADDRESSES}/${data?.id}/show`) + } + }}> ) diff --git a/src/resources/audit/AuditList.tsx b/src/resources/audit/AuditList.tsx index da9e77ad..78c82ef6 100644 --- a/src/resources/audit/AuditList.tsx +++ b/src/resources/audit/AuditList.tsx @@ -7,7 +7,6 @@ import { DateTimeInput, useListContext, AutocompleteArrayInput, - TextInput, FunctionField, DatagridConfigurable, type DatagridConfigurableProps, @@ -15,7 +14,9 @@ import { ExportButton, useGetList, Link, - BooleanField + BooleanField, + NumberInput, + SelectInput } from 'react-admin' import * as constants from '../../constants' import ActivityTypes from '../../utils/activity-types' @@ -24,11 +25,29 @@ import SourceField from '../../components/SourceField' import SourceInput from '../../components/SourceInput' import StyledTopToolbar from '../../components/StyledTopToolbar' import { useLocation } from 'react-router-dom' +import { useConfigData } from '../../utils/useConfigData' interface Props { label: string source: string } +export const availableResources = [ + constants.R_USERS, + constants.R_ITEMS, + constants.R_BATCHES, + constants.R_DESTRUCTION, + constants.R_VAULT_LOCATION, + constants.R_DISPATCH, + constants.R_PROJECTS, + constants.R_MEDIA_TYPE, + constants.R_PLATFORMS, + constants.R_ORGANISATION, + constants.R_CAT_CAVE, + constants.R_CAT_CODE, + constants.R_CAT_HANDLE, + constants.R_DEPARTMENT, + constants.R_PROTECTIVE_MARKING +] const SecurityRelatedFilter = ({ label, @@ -42,39 +61,7 @@ const SecurityRelatedFilter = ({ return } - const choices = ActivityTypes.map((v) => ({ name: v.label, id: v.label })) -const filters = [ - , - , - , - , - , - , - , - , - -] - const resourcesRefKey: Record = { [constants.R_BATCHES]: 'batchNumber', [constants.R_ITEMS]: 'itemNumber', @@ -199,6 +186,67 @@ export default function AuditList({ : 'simple-audit-list' const filteredData = location.state?.filter + const ConfigData = useConfigData() + const labelledResources = availableResources.map((resource) => ({ + id: resource, + name: + resource === constants.R_PROJECTS + ? ConfigData?.projectName + : constants.cosmeticLabels[ + resource as keyof typeof constants.cosmeticLabels + ] + })) + + const filters = [ + , + , + , + , + , + + , + , + , + + ] + const renderResource = (record: Audit): string => { + const resourceName = labelledResources.find( + (r) => r.id === record.resource + )?.name + return String(resourceName ?? record.resource) + } return ( - source='resource' label='Resource' /> + + + source='resource' + label='Resource' + render={renderResource} + /> {!omit.includes('dataId') && ( - label='Name' + label='Subject ' render={(record) => { return ( record.dataId && @@ -258,7 +311,7 @@ export default function AuditList({ source value for different kinds of resource */} {!omit.includes('subjectId') && ( - label='Subject Item' + label='Object' render={(record) => { return ( record.subjectId && diff --git a/src/resources/batches/index.tsx b/src/resources/batches/index.tsx index 59719b40..c9a6de7c 100644 --- a/src/resources/batches/index.tsx +++ b/src/resources/batches/index.tsx @@ -55,8 +55,16 @@ const Actions = (): React.ReactElement => { } const BatchEdit = (): React.ReactElement => { + const redirect = useRedirect() return ( - }> + } + mutationOptions={{ + onSuccess: (data: { batchNumber: string; id: number }): void => { + redirect(`/${constants.R_BATCHES}/${data?.id}/show`) + } + }}> ) diff --git a/src/resources/destruction/DestructionForm.tsx b/src/resources/destruction/DestructionForm.tsx index b072f37f..91ba7a19 100644 --- a/src/resources/destruction/DestructionForm.tsx +++ b/src/resources/destruction/DestructionForm.tsx @@ -12,7 +12,6 @@ import { useUpdate } from 'react-admin' import * as constants from '../../constants' -import DatePicker from '../../components/DatePicker' import { yupResolver } from '@hookform/resolvers/yup' import * as yup from 'yup' import { ConditionalReferenceInput } from '../batches/BatchForm' @@ -38,7 +37,7 @@ const DestructionFormToolbar = ( return ( - + ) } @@ -155,16 +154,6 @@ export default function DestructionForm(props: Props): React.ReactElement { toolbar={} resolver={yupResolver(schema)} onSubmit={handleSubmit as any}> - {isEdit && ( { } const DestructionEdit = (): React.ReactElement => { + const redirect = useRedirect() return ( - + { + redirect(`/${constants.R_DESTRUCTION}/${data?.id}/show`) + } + }}> ) diff --git a/src/resources/dispatch/index.tsx b/src/resources/dispatch/index.tsx index 9146cb61..038c12b4 100644 --- a/src/resources/dispatch/index.tsx +++ b/src/resources/dispatch/index.tsx @@ -24,8 +24,15 @@ const DispatchCreate = (): React.ReactElement => { } export const DispatchEdit = (): React.ReactElement => { + const redirect = useRedirect() return ( - + { + redirect(`/${constants.R_DISPATCH}/${data.id}/show`) + } + }}> ) diff --git a/src/resources/items/ItemForm/ItemFormToolbar.tsx b/src/resources/items/ItemForm/ItemFormToolbar.tsx index 6d0b9e8c..ebb0aed0 100644 --- a/src/resources/items/ItemForm/ItemFormToolbar.tsx +++ b/src/resources/items/ItemForm/ItemFormToolbar.tsx @@ -37,10 +37,11 @@ interface ActionsProps { const Actions = (props: ActionsProps): React.ReactElement => { const { onSuccess, setOpenRemarks, vLocationAudits } = props - + const redirect = useRedirect() const onSuccessWithRemarksClose = (data: any): void => { onSuccess(data) setOpenRemarks(false) + redirect(`/${constants.R_RICH_ITEMS}/${data?.id}/show`) } return ( @@ -71,10 +72,11 @@ interface Props { onSave: (event: React.SyntheticEvent) => void setOpenRemarks: React.Dispatch openRemarks: boolean + isEdit: boolean } const ItemFormToolbar = (props: Props): React.ReactElement => { - const { onSuccess, onSave, openRemarks, setOpenRemarks } = props + const { onSuccess, onSave, openRemarks, setOpenRemarks, isEdit } = props const { notify } = useContext(NotificationContext) const { reset, getValues, setValue } = useFormContext() const [alwaysEnable, setAlwaysEnable] = useState(false) @@ -141,7 +143,7 @@ const ItemFormToolbar = (props: Props): React.ReactElement => { itemId ) setTimeout(() => { - if (!clone) { + if (!clone && !isEdit) { redirect(path) } }, 0) diff --git a/src/resources/items/ItemForm/index.tsx b/src/resources/items/ItemForm/index.tsx index 0f2193e2..9ebf7ff7 100644 --- a/src/resources/items/ItemForm/index.tsx +++ b/src/resources/items/ItemForm/index.tsx @@ -156,6 +156,7 @@ export default function ItemForm({ isEdit }: FormProps): React.ReactElement { openRemarks={openRemarks} setOpenRemarks={setOpenRemarks} onSave={onSave} + isEdit /> }> & { footer?: React.FunctionComponent headStyle?: Record @@ -99,7 +99,7 @@ export default function ItemsReport( const { footer, children, headStyle = {}, sx = {}, ...rest } = props return ( ) } - -const referenceFields: RefFieldType[] = [ - { - name: 'vaultLocation', - resource: constants.R_VAULT_LOCATION, - source: 'name', - label: 'Vault Location' - }, - { - name: 'createdBy_eq', - resource: constants.R_USERS, - source: 'name', - label: 'Created By' - }, - { - name: 'createdBy', - resource: constants.R_USERS, - source: 'name', - label: 'Created By' - }, - { - name: 'protectiveMarking', - resource: constants.R_PROTECTIVE_MARKING, - source: 'name', - label: 'Protective Marking' - }, - { - name: 'batch', - resource: constants.R_BATCHES, - source: 'batchNumber', - label: 'Batch' - } -] - const fields: FieldType[] = [ { name: 'mediaType', @@ -206,6 +172,52 @@ export function ItemAssetReport(props: Props): React.ReactElement { } const { data } = useGetIdentity() + const configDate = useConfigData() + + const referenceFields: RefFieldType[] = [ + { + name: 'vaultLocation', + resource: constants.R_VAULT_LOCATION, + source: 'name', + label: 'Vault Location' + }, + { + name: 'createdBy_eq', + resource: constants.R_USERS, + source: 'name', + label: 'Created By' + }, + { + name: 'createdBy', + resource: constants.R_USERS, + source: 'name', + label: 'Created By' + }, + { + name: 'protectiveMarking', + resource: constants.R_PROTECTIVE_MARKING, + source: 'name', + label: 'Protective Marking' + }, + { + name: 'batch', + resource: constants.R_BATCHES, + source: 'batchNumber', + label: 'Batch' + }, + { + name: 'project', + resource: constants.R_PROJECTS, + source: 'name', + label: configDate?.projectName ?? 'Default Label' + }, + { + name: 'platform', + resource: constants.R_PLATFORMS, + source: 'name', + label: 'Platform' + } + ] const handleOpen = (open: boolean) => () => { setOpen(open) diff --git a/src/resources/platforms/index.tsx b/src/resources/platforms/index.tsx index f1407072..965816a2 100644 --- a/src/resources/platforms/index.tsx +++ b/src/resources/platforms/index.tsx @@ -1,5 +1,12 @@ import React from 'react' -import { SimpleForm, TextInput, BooleanInput, Create, Edit } from 'react-admin' +import { + SimpleForm, + TextInput, + BooleanInput, + Create, + Edit, + useRedirect +} from 'react-admin' import { yupResolver } from '@hookform/resolvers/yup' import * as yup from 'yup' import PlatformList from './PlatformList' @@ -42,8 +49,16 @@ const PlatformCreate = ({ name }: PropType): React.ReactElement => { const PlatformEdit = ({ name }: PropType): React.ReactElement => { const cName: string = name + const redirect = useRedirect() + return ( - + { + redirect(`/${cName}/${data?.id}/show`) + } + }}> ) diff --git a/src/resources/projects/index.tsx b/src/resources/projects/index.tsx index ddd4f499..4db180fd 100644 --- a/src/resources/projects/index.tsx +++ b/src/resources/projects/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Create, Edit } from 'react-admin' +import { Create, Edit, useRedirect } from 'react-admin' import ProjectForm from './ProjectForm' import * as constants from '../../constants' @@ -15,8 +15,15 @@ const ProjectCreate = (): React.ReactElement => { } const ProjectEdit = (): React.ReactElement => { + const redirect = useRedirect() return ( - + { + redirect(`/${constants.R_PROJECTS}/${data?.id}/show`) + } + }}> ) diff --git a/src/resources/reference-data/ReferenceDataForm.tsx b/src/resources/reference-data/ReferenceDataForm.tsx index beab9297..b4835821 100644 --- a/src/resources/reference-data/ReferenceDataForm.tsx +++ b/src/resources/reference-data/ReferenceDataForm.tsx @@ -79,7 +79,7 @@ const FormContent = ({ {name === constants.R_MEDIA_TYPE ? ( ) : null} diff --git a/src/resources/reference-data/ReferenceDataShow.tsx b/src/resources/reference-data/ReferenceDataShow.tsx index a7fbcf48..3e159497 100644 --- a/src/resources/reference-data/ReferenceDataShow.tsx +++ b/src/resources/reference-data/ReferenceDataShow.tsx @@ -23,6 +23,7 @@ const Actions = ({ resource }: ShowActionProps): React.ReactElement => { const redirect = useRedirect() return ( + { redirect( @@ -58,9 +59,14 @@ export default function ReferenceDataShow({ variant='h6' source='name' /> {name === R_MEDIA_TYPE ? ( - - - + + + +   + (Note: Item-size is + stored to facilitate future shelf loading calculations) + + ) : null} source='active' looseValue /> diff --git a/src/resources/reference-data/index.tsx b/src/resources/reference-data/index.tsx index 0ed1252b..2f11f985 100644 --- a/src/resources/reference-data/index.tsx +++ b/src/resources/reference-data/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Create, Edit } from 'react-admin' +import { Create, Edit, useRedirect } from 'react-admin' import ReferenceDataForm from './ReferenceDataForm' import * as constants from '../../constants' interface PropType { @@ -17,11 +17,16 @@ const RerferenceDataCreate = ({ name }: PropType): React.ReactElement => { export const ReferenceDataEdit = ({ name }: PropType): React.ReactElement => { const cName: string = name + const redirect = useRedirect() return ( { + redirect(`/${cName}/${data?.id}/show`) + } + }} resource={cName}> diff --git a/src/resources/users/UserForm.tsx b/src/resources/users/UserForm.tsx index c7f97032..dd8400fc 100644 --- a/src/resources/users/UserForm.tsx +++ b/src/resources/users/UserForm.tsx @@ -1,5 +1,11 @@ import React from 'react' -import { SimpleForm, TextInput, useEditContext, SelectInput } from 'react-admin' +import { + SimpleForm, + TextInput, + useEditContext, + SelectInput, + DateTimeInput +} from 'react-admin' import { yupResolver } from '@hookform/resolvers/yup' import * as yup from 'yup' import EditToolBar from '../../components/EditToolBar' @@ -59,6 +65,11 @@ export default function UserForm({ isEdit }: FormProps): React.ReactElement { /> + ) } diff --git a/src/resources/users/UserShow.tsx b/src/resources/users/UserShow.tsx index c4ab9eb9..65195ee7 100644 --- a/src/resources/users/UserShow.tsx +++ b/src/resources/users/UserShow.tsx @@ -364,25 +364,11 @@ const UserShowComp = ({ export default function UserShow(): React.ReactElement { const [record, setRecord] = useState() const { hasAccess } = useCanAccess() - const [filteredData, setFilteredData] = useState([]) const hasWriteAccess = hasAccess(R_USERS, { write: true }) - const { isLoading, data } = useGetList(R_AUDIT, {}) + const { isLoading } = useGetList(R_AUDIT, {}) const audit = useAudit() const navigate = useNavigate() - useEffect(() => { - if (data != null) - setFilteredData( - data.filter((audit) => { - return ( - audit.user === record?.id || - audit.subjectId === record?.id || - (audit.dataId === record?.id && audit.resource === R_USERS) - ) - }) - ) - }, [data, record, isLoading]) - if (isLoading) return return ( @@ -394,7 +380,14 @@ export default function UserShow(): React.ReactElement { { - navigate('/audit', { state: { data: filteredData } }) + if (record) { + navigate( + `/audit?filter=${JSON.stringify({ + resource: constants.R_USERS, + dataId: record.id ?? '' + })}` + ) + } }} /> diff --git a/src/resources/users/index.tsx b/src/resources/users/index.tsx index 1c942da6..c37f2b03 100644 --- a/src/resources/users/index.tsx +++ b/src/resources/users/index.tsx @@ -1,5 +1,5 @@ -import React, { useState } from 'react' -import { Create, Edit, useEditContext } from 'react-admin' +import React, { useEffect, useState } from 'react' +import { Create, Edit, useEditContext, useRedirect } from 'react-admin' import UserForm from './UserForm' import * as constants from '../../constants' import useAudit from '../../hooks/useAudit' @@ -20,10 +20,9 @@ const UserCreate = (): React.ReactElement => { } const UserEdit = (): React.ReactElement => { - const path: string = `/${constants.R_USERS}` const audit = useAudit() const [prev, setPrev] = useState() - + const redirect = useRedirect() return ( { subjectResource: null, subjectId: null }) + redirect(`/${constants.R_USERS}/${data?.id}/show`) } }} mutationMode={constants.MUTATION_MODE} - resource={constants.R_USERS} - redirect={path}> + resource={constants.R_USERS}> ) @@ -55,8 +54,11 @@ interface EditValType { const EditVal = ({ setPrev }: EditValType): React.ReactElement => { const { record } = useEditContext() - console.log(record) - setPrev(record) + + useEffect(() => { + setPrev(record as User) + }, [record, setPrev]) + return } diff --git a/src/resources/vault-locations/index.tsx b/src/resources/vault-locations/index.tsx index 029a4fd3..29c55ec9 100644 --- a/src/resources/vault-locations/index.tsx +++ b/src/resources/vault-locations/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Create, Edit } from 'react-admin' +import { Create, Edit, useRedirect } from 'react-admin' import VaultLocationForm from './VaultLocationForm' import VaultLocationList from './VaultLocationList' import ReferenceDataShow from '../reference-data/ReferenceDataShow' @@ -14,8 +14,15 @@ const VaultLocationCreate = (): React.ReactElement => { } export const VaultLocationEdit = (): React.ReactElement => { + const redirect = useRedirect() return ( - + { + redirect(`/${constants.R_VAULT_LOCATION}/${data?.id}/show`) + } + }}> ) diff --git a/src/types.d.ts b/src/types.d.ts index 014d2926..99b8e222 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -261,7 +261,7 @@ interface Address { createdAt: string fullAddress: string active: boolean - Remarks: string + remarks: string } interface Dispatch { diff --git a/src/utils/init-data.ts b/src/utils/init-data.ts index 985d06e1..71ce63d6 100644 --- a/src/utils/init-data.ts +++ b/src/utils/init-data.ts @@ -96,7 +96,7 @@ export const getAddresses = ( id: index + 1, fullAddress: `${ctr} Some St, Some Town, Some County, DD${ctr} ${ctr}EF`, createdAt: DateTime.now().toISO() ?? '', - Remarks: '', + remarks: '', active } }) diff --git a/src/utils/password-validation.schema.ts b/src/utils/password-validation.schema.ts index 6484895a..19468de8 100644 --- a/src/utils/password-validation.schema.ts +++ b/src/utils/password-validation.schema.ts @@ -94,7 +94,7 @@ const common = yup .matches(/[0-9]/, 'Password must contain at least one numeric digit') .matches( /[!@#$%^&*(),.?":{}|<>]/, - 'Password must contain at least one special character' + 'Special character required - !@#$%^&*(),.?":{}|<>' ) .test( 'no-common-patterns',