-
Notifications
You must be signed in to change notification settings - Fork 643
/
record-action.tsx
117 lines (100 loc) · 3.89 KB
/
record-action.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import React, { useState, useEffect, useCallback } from 'react'
import { useRouteMatch } from 'react-router'
import { Loader } from '@admin-bro/design-system'
import BaseActionComponent from '../app/base-action-component'
import ApiClient from '../../utils/api-client'
import { RecordActionParams } from '../../../backend/utils/view-helpers/view-helpers'
import { ActionJSON, RecordJSON } from '../../interfaces'
import { NoResourceError, NoActionError, NoRecordError } from '../app/error-message'
import Wrapper from './utils/wrapper'
import { ActionHeader } from '../app'
import { useNotice, useResource, useTranslation } from '../../hooks'
import DrawerPortal from '../app/drawer-portal'
import { ActionResponse, RecordActionResponse } from '../../../backend/actions/action.interface'
import mergeRecordResponse from '../../hooks/use-record/merge-record-response'
const api = new ApiClient()
const RecordAction: React.FC = () => {
const [record, setRecord] = useState<RecordJSON>()
const [loading, setLoading] = useState(true)
const match = useRouteMatch<RecordActionParams>()
const addNotice = useNotice()
const { translateMessage } = useTranslation()
const { actionName, recordId, resourceId } = match.params
const resource = useResource(resourceId)
const action = record && record.recordActions.find(r => r.name === actionName)
const fetchRecord = (): void => {
setLoading(true)
api.recordAction(match.params).then((response) => {
setLoading(false)
if (response.data.notice && response.data.notice.type === 'error') {
addNotice(response.data.notice)
}
setRecord(response.data.record)
}).catch((error) => {
addNotice({
message: translateMessage('errorFetchingRecord', resourceId),
type: 'error',
})
throw error
})
}
useEffect(() => {
fetchRecord()
}, [actionName, recordId, resourceId])
const handleActionPerformed = useCallback((oldRecord: RecordJSON, response: ActionResponse) => {
if (response.record) {
setRecord(mergeRecordResponse(oldRecord, response as RecordActionResponse))
} else {
fetchRecord()
}
}, [fetchRecord])
if (!resource) {
return (<NoResourceError resourceId={resourceId} />)
}
// When the user visits this route (record action) from a different, than the current one, record.
// It renders everything with a new resource. The old record remains until useEffect fetches data
// from the API. that is why we have to check if the current record has correct record.id.
// Alternative approach would be to setRecord(undefined) before the fetch, but it is async and
// we cannot be sure that the component wont be rendered (it will be at least once) with the
// wrong data.
const hasDifferentRecord = record && record.id && record.id.toString() !== recordId
if (loading || hasDifferentRecord) {
const actionFromResource = resource.actions.find(r => r.name === actionName)
return actionFromResource?.showInDrawer ? (<DrawerPortal><Loader /></DrawerPortal>) : <Loader />
}
if (!action) {
return (<NoActionError resourceId={resourceId} actionName={actionName} />)
}
if (!record) {
return (<NoRecordError resourceId={resourceId} recordId={recordId} />)
}
if (action.showInDrawer) {
return (
<DrawerPortal width={action.containerWidth}>
<BaseActionComponent
action={action as ActionJSON}
resource={resource}
record={record}
/>
</DrawerPortal>
)
}
return (
<Wrapper width={action.containerWidth}>
<ActionHeader
resource={resource}
action={action}
record={record}
actionPerformed={(response: ActionResponse): void => (
handleActionPerformed(record, response)
)}
/>
<BaseActionComponent
action={action}
resource={resource}
record={record}
/>
</Wrapper>
)
}
export default RecordAction