FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects
Commit e574a5eb authored by Robin Goodall's avatar Robin Goodall :speech_balloon:
Browse files

Create and update Asset API calls to POST and PUT. Backdrop in case delayed.

parent 8cd426ab
No related branches found
No related tags found
1 merge request!11Asset Edit and Creation
......@@ -47,6 +47,9 @@ export interface AssetsContextState {
assetId: string
// Functionality for retrieving a single asset
getAsset: (id: string) => Asset | null
// Functionality for creating or updating an asset
createAsset: (draft: Asset) => Promise<void>
updateAsset: (draft: Asset) => Promise<void>
}
// Initial context state - no assets retrieved
......@@ -62,6 +65,8 @@ const INITIAL_CONTEXT_STATE = {
isLoadingAsset: false,
assetId: '',
getAsset: () => null,
createAsset: () => { return Promise.resolve() },
updateAsset: () => { return Promise.resolve() },
}
/**
......@@ -175,12 +180,50 @@ const useAssetsProviderValue = () => {
return null;
}, [state.assets, stateDispatch]);
const createAsset = React.useCallback(async (draft:Asset) => {
if (!authAPI) {
throw new Error('No authentication')
}
try {
await authAPI(ASSETS_URL, {
method: 'post',
body: JSON.stringify(draft),
})
// reset assets in state to force reload
stateDispatch({type: 'RESET_ASSETS'})
return Promise.resolve()
} catch (e) {
stateDispatch({type: 'SET_ERROR', payload: e})
return Promise.reject(e)
}
}, [authAPI, stateDispatch]);
const updateAsset = React.useCallback(async (draft:Asset) => {
if (!authAPI) {
throw new Error('No authentication')
}
try {
const response = await authAPI(draft.url, {
method: 'put',
body: JSON.stringify(draft),
})
// update asset in state
stateDispatch({type: 'ADD_ASSET', payload: response})
return Promise.resolve()
} catch (e) {
stateDispatch({type: 'SET_ERROR', payload: e})
return Promise.reject(e)
}
}, [authAPI, stateDispatch]);
return {
...state,
setOrdering,
setDepartment,
nextPage,
getAsset,
createAsset,
updateAsset,
}
};
......@@ -212,10 +255,13 @@ interface AssetGetAction {
type: "GET_ASSET"
payload: string
}
interface AssetsResetAction {
type: "RESET_ASSETS"
}
type AssetsActions = (
AssetsAddAction | AssetsErrorAction | AssetsOrderAction | AssetsDeptAction | AssetsNextPageAction |
AssetAddAction | AssetGetAction
AssetAddAction | AssetGetAction | AssetsResetAction
)
/**
......@@ -290,6 +336,11 @@ const contextReducer = (state: AssetsContextState, action: AssetsActions): Asset
assetId: action.payload,
isLoadingAsset: true
}
case 'RESET_ASSETS':
return {
...state,
assetIds: [],
}
default:
throw new Error(`Unknown action: ${action}`);
}
......
import * as React from 'react'
import { useParams, Redirect, Prompt } from 'react-router-dom'
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'
import { useParams, Redirect, Prompt, useHistory } from 'react-router-dom'
import { Box } from '@material-ui/core'
import { Box, Backdrop, CircularProgress } from '@material-ui/core'
import { GenericPage } from '.'
import AssetEditHeader from '../components/AssetEditHeader'
......@@ -13,6 +14,13 @@ import { useAssets, Asset, useAuthenticationState } from '../api'
import { DEFAULT_ASSET } from '../draft'
const useStyles = makeStyles((theme: Theme) => createStyles({
backdrop: {
color: theme.palette.primary.contrastText,
zIndex: theme.zIndex.drawer + 1,
},
}), { name: 'AssetFormPage' });
export type DraftPatch = Partial<Asset>
interface DraftContextState {
......@@ -32,8 +40,9 @@ export const useDraft = () => React.useContext(DraftContext);
// Asset Creation and Editing page
export const AssetFormPage: React.FunctionComponent = () => {
const { assetId } = useParams()
const { getAsset } = useAssets()
const { profile } = useAuthenticationState();
const { getAsset, createAsset, updateAsset } = useAssets()
const { profile } = useAuthenticationState()
const classes = useStyles()
// Scroll to top when first rendered
const scrolledToTop = React.useRef(false)
......@@ -77,13 +86,45 @@ export const AssetFormPage: React.FunctionComponent = () => {
}, [draft, dispatch, assetId, getAsset, profile])
// Save draft handler
const [isSaving, setIsSaving] = React.useState(false)
const history = useHistory();
const saveDraft = React.useCallback(()=>{
if (isModified) {
alert('Would save ' + ((draft && draft.id) ? draft.id : 'new entry'))
} else {
alert('Nothing to save for ' + ((draft && draft.id) ? draft.id : 'new entry'))
if (draft) {
if (draft.id) {
// Update existing asset
if (!isModified) {
// nothing to save, so just go back
setIsModified(false)
history.goBack()
} else {
setIsSaving(true)
updateAsset(draft)
.then(()=>{
setIsSaving(false)
setIsModified(false)
history.goBack()
})
.catch(()=>{
// failed to update - clear isSaving
setIsSaving(false)
})
}
} else if (isModified) {
// Create new asset (only if modified)
setIsSaving(true)
createAsset(draft)
.then(()=>{
setIsSaving(false)
setIsModified(false)
history.goBack()
})
.catch(()=>{
// failed to create - clear isSaving
setIsSaving(false)
})
}
}
}, [draft, isModified]);
}, [draft, isModified, setIsSaving, updateAsset, createAsset, history]);
// Whether to confirm deletion (by id)
const [idToDelete, setIdToDelete] = React.useState<string | null>(null)
......@@ -119,6 +160,9 @@ export const AssetFormPage: React.FunctionComponent = () => {
'This entry has not yet been saved. Navigating away will cause any changes you have made to be lost.'
}
/>
<Backdrop className={classes.backdrop} open={isSaving}>
<CircularProgress color="inherit" />
</Backdrop>
<GenericPage withSidebar={ false } appBarChildren={ appBar }>
<Box px={9} py={4}>
<AssetEdit asset={draft} isLoading={draft===null} onSave={saveDraft} />
......@@ -153,7 +197,6 @@ const draftDispatcher = (state: Asset | null, action: DraftActions): Asset | nul
// Cannot patch - draft isn't ready
return state;
}
console.log('Patch Draft:',action.payload)
return {...state, ...action.payload};
default:
throw new Error(`Unknown action: ${action}`);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment