diff --git a/src/App.tsx b/src/App.tsx index 7ca1e0e7..c00611cc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,7 +16,7 @@ import { VisibilityOff } from '@mui/icons-material' import { getDataProvider } from './providers/dataProvider' -import rcoAuthProvider, { removeToken } from './providers/authProvider' +import rcoAuthProvider, { removeUserToken } from './providers/authProvider' import { useForm } from 'react-hook-form' import * as yup from 'yup' @@ -117,7 +117,7 @@ function App(): React.ReactElement { const [openChangePasswordModal, setOpenChangePasswordModal] = useState(false) const handleOnIdle = (): void => { - removeToken() + removeUserToken() } const handleOnAction = (): void => { reset() @@ -245,6 +245,11 @@ function App(): React.ReactElement { } useEffect(() => { + // Check if session not exist. clear the user token from cookies + const storedSessionData = sessionStorage.getItem(constants.SESSION_LOGIN) + if (storedSessionData === null) { + removeUserToken() + } const storedValue = localStorage.getItem(constants.LOGGING_ENABLED) if (storedValue !== null) { setLoggingPref(storedValue === 'true') diff --git a/src/components/ProtectionRefInput.tsx b/src/components/ProtectionRefInput.tsx index fee43902..2bcac0d2 100644 --- a/src/components/ProtectionRefInput.tsx +++ b/src/components/ProtectionRefInput.tsx @@ -17,9 +17,11 @@ import { useGetList, useRecordContext, useResourceContext, - type Identifier + type Identifier, + useRedirect } from 'react-admin' import { Box } from '@mui/system' +import { R_RICH_ITEMS } from '../constants' interface Props { reference: string @@ -66,6 +68,8 @@ export default function ProtectionRefInput< getValues, reset } = useFormContext() + const redirect = useRedirect() + const [valueLabel, setValueLabel] = useState('') type SelectedIdType = T['id'] | Array @@ -163,6 +167,10 @@ export default function ProtectionRefInput< if (record?.id) { // onValueChange(getPreviousValue()) updateRecord(record.id as number, selectedData as number[]) + .then(() => { + redirect(`/${R_RICH_ITEMS}/${record?.id}/show`) + }) + .catch(console.log) } else if (id) { createRecord(id, selectedData as number[]) } diff --git a/src/constants.ts b/src/constants.ts index 6fcf9103..cb1c234e 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -14,8 +14,9 @@ export const LOCAL_STORAGE_DB_KEY = 'rco-' export const DATE_FORMAT = 'yyyy-MM-dd' export const DATETIME_FORMAT = 'dd/MMM/yyyy HH:mm' export const TOKEN_KEY = 'rco-user' - export const MUTATION_MODE = 'optimistic' +// session storage value. +export const SESSION_LOGIN = 'login' // major table/resource names export const R_USERS = 'user' @@ -108,8 +109,6 @@ export const ITEM_SAVE = 'item_save' export const CHANGE_PASSWORD_EVENT = 'change_password' - - export const cosmeticLabels = { [R_USERS]: 'User', [R_ITEMS]: 'Item', @@ -125,6 +124,5 @@ export const cosmeticLabels = { [R_CAT_CODE]: 'Cat Code', [R_CAT_HANDLE]: 'Cat Handle', [R_DEPARTMENT]: 'Department', - [R_PROTECTIVE_MARKING]: 'Protective Marking', - -} \ No newline at end of file + [R_PROTECTIVE_MARKING]: 'Protective Marking' +} diff --git a/src/hooks/useRefTable.ts b/src/hooks/useRefTable.ts index 7a3366e4..5f105414 100644 --- a/src/hooks/useRefTable.ts +++ b/src/hooks/useRefTable.ts @@ -1,14 +1,9 @@ -import { - useCreate, - useDataProvider, - // useDeleteMany, - useRedirect -} from 'react-admin' -import { R_ITEMS } from '../constants' +import { useCreate, useDataProvider, useRedirect } from 'react-admin' +import * as constants from '../constants' interface DBMethods { createRecord: (id: number, data?: number[]) => void - updateRecord: (id: number, data?: number[]) => void + updateRecord: (id: number, data?: number[]) => Promise } export default function useRefTable( @@ -17,32 +12,43 @@ export default function useRefTable( resource: string ): DBMethods { const [create] = useCreate() - // const [deleteMany] = useDeleteMany() - const redirect = useRedirect() const dataProvider = useDataProvider() + const redirect = useRedirect() - const updateRecord = (id: number, data?: number[]): void => { - dataProvider - .getList(refTable, { - pagination: { page: 1, perPage: 100 }, - sort: { field: 'id', order: 'ASC' }, - filter: { [resource]: id } - }) - .then(({ data: tableData = [] }) => { - const idsToDelete = tableData.map( - (item: Record) => item.id - ) - - if (idsToDelete.length > 0) - {dataProvider.deleteMany(refTable, { ids: idsToDelete }) - .then(() => { + const updateRecord = async ( + id: number, + data?: number[] + ): Promise => { + return await new Promise((resolve, reject): void => { + dataProvider + .getList(refTable, { + pagination: { page: 1, perPage: 100 }, + sort: { field: 'id', order: 'ASC' }, + filter: { [resource]: id } + }) + .then(({ data: tableData = [] }) => { + const idsToDelete = tableData.map( + (item: Record) => item.id + ) + if (idsToDelete.length > 0) { + dataProvider + .deleteMany(refTable, { ids: idsToDelete }) + .then(() => { + createRecord(id, data) + resolve(null) + }) + .catch((err) => { + reject(err) + }) + } else { createRecord(id, data) - }) - .catch(console.log) - } - else createRecord(id, data) - }) - .catch(console.log) + resolve(null) + } + }) + .catch((err) => { + reject(err) + }) + }) } const createRecord = (id: number, data?: number[]): void => { @@ -55,7 +61,7 @@ export default function useRefTable( } }) }) - if (resource !== R_ITEMS) redirect(`/${resource}`) + if (resource !== constants.R_ITEMS) redirect(`/${resource}`) } catch (error: any) { console.log(error) } diff --git a/src/providers/authProvider/index.ts b/src/providers/authProvider/index.ts index a424ac14..db60e693 100644 --- a/src/providers/authProvider/index.ts +++ b/src/providers/authProvider/index.ts @@ -44,7 +44,7 @@ const setToken = (token: string): void => { document.cookie = `${constants.TOKEN_KEY}=${token}; expires=${expires}; path=/ ` } -export const removeToken = (): void => { +export const removeUserToken = (): void => { removeCookie(constants.TOKEN_KEY) } @@ -144,6 +144,7 @@ const authProvider = (dataProvider: DataProvider): AuthProvider => { try { const res = await login({ password, staffNumber }) await createUserToken(res.data.data, audit) + sessionStorage.setItem('login', 'true') return await Promise.resolve(res.data.data) } catch (error) { if (isAxiosError(error)) @@ -163,7 +164,7 @@ const authProvider = (dataProvider: DataProvider): AuthProvider => { securityRelated: null, activityDetail: null }) - removeToken() + removeUserToken() await Promise.resolve() }, checkAuth: async (): Promise => { @@ -176,7 +177,7 @@ const authProvider = (dataProvider: DataProvider): AuthProvider => { checkError: async (error): Promise => { const status = error.status if (status === 401 || status === 403) { - removeToken() + removeUserToken() await Promise.reject( new Error('Server returned code ' + String(status)) ) diff --git a/src/providers/dataProvider/index.ts b/src/providers/dataProvider/index.ts index a5358064..95576b89 100644 --- a/src/providers/dataProvider/index.ts +++ b/src/providers/dataProvider/index.ts @@ -90,6 +90,11 @@ export const getDataProvider = async ( const operators = ['_neq', '_eq', '_lte', '_gte'] const SEARCH_OPERATOR = 'q' const nullOperators = ['__null', '__notnull'] +const bridgingTables = [ + constants.R_ITEMS_CODE, + constants.R_ITEMS_CAVE, + constants.R_ITEMS_HANDLE +] export const dataProvider = (apiUrl: string): DataProvider => ({ getList: async (resource: string, params: any) => { @@ -325,25 +330,26 @@ export const dataProvider = (apiUrl: string): DataProvider => ({ }) }, - // Note: Deletion is not supported - delete: async (_resource: string, _params: any) => { - throw new Error('Deletion is not supported!') - // const url = `${apiUrl}/${resource}/rows/${params.id}` - - // return await axios.delete(url).then(() => { - // return { data: params.id } - // }) + // Note: Deletion is not supported (except for bridging tables) + delete: async (resource: string, params: any) => { + if (bridgingTables.includes(resource)) { + const url = `${apiUrl}/${resource}/rows/${params.id}` + return await axios.delete(url).then(() => ({ data: params.id })) + } else { + throw new Error('Deletion is not supported!') + } }, - // Note: Deletion is not supported - deleteMany: async (_resource: string, _params: any) => { - throw new Error('Deletion is not supported!') - - // const ids = params.ids.toString() - // const url = `${apiUrl}/${resource}/rows/${ids}` - - // return await axios.delete(url).then(() => { - // return { data: params.ids } - // }) + // Note: Deletion is not supported (except for bridging tables) + deleteMany: async (resource: string, params: any) => { + if (bridgingTables.includes(resource)) { + const ids = params.ids.toString() + const url = `${apiUrl}/${resource}/rows/${ids}` + return await axios.delete(url).then(() => { + return { data: params.ids } + }) + } else { + throw new Error('Deletion is not supported!') + } } }) diff --git a/src/resources/items/ItemForm/ItemFormToolbar.tsx b/src/resources/items/ItemForm/ItemFormToolbar.tsx index ebb0aed0..34eb2394 100644 --- a/src/resources/items/ItemForm/ItemFormToolbar.tsx +++ b/src/resources/items/ItemForm/ItemFormToolbar.tsx @@ -37,11 +37,10 @@ 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 ( diff --git a/src/resources/users/UserForm.tsx b/src/resources/users/UserForm.tsx index dd8400fc..52cf27cf 100644 --- a/src/resources/users/UserForm.tsx +++ b/src/resources/users/UserForm.tsx @@ -46,7 +46,7 @@ export default function UserForm({ isEdit }: FormProps): React.ReactElement { return ( } defaultValues={defaultValues} resolver={yupResolver(schema)}>