@devtron-labs/devtron-fe-common-lib 0.0.39 → 0.0.40-beta-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Common/Common.service.d.ts +2 -2
- package/dist/Common/Constants.d.ts +1 -0
- package/dist/Common/RJSF/Form.d.ts +4 -0
- package/dist/Common/RJSF/common/FieldRow.d.ts +3 -0
- package/dist/Common/RJSF/common/types.d.ts +8 -0
- package/dist/Common/RJSF/config.d.ts +4 -0
- package/dist/Common/RJSF/constants.d.ts +5 -0
- package/dist/Common/RJSF/index.d.ts +2 -0
- package/dist/Common/RJSF/templates/ArrayFieldItemTemplate.d.ts +3 -0
- package/dist/Common/RJSF/templates/ArrayFieldTemplate.d.ts +3 -0
- package/dist/Common/RJSF/templates/BaseInput.d.ts +3 -0
- package/dist/Common/RJSF/templates/ButtonTemplates/AddButton.d.ts +3 -0
- package/dist/Common/RJSF/templates/ButtonTemplates/RemoveButton.d.ts +3 -0
- package/dist/Common/RJSF/templates/ButtonTemplates/SubmitButton.d.ts +3 -0
- package/dist/Common/RJSF/templates/ButtonTemplates/index.d.ts +3 -0
- package/dist/Common/RJSF/templates/Description.d.ts +3 -0
- package/dist/Common/RJSF/templates/Field.d.ts +3 -0
- package/dist/Common/RJSF/templates/FieldErrorTemplate.d.ts +3 -0
- package/dist/Common/RJSF/templates/ObjectFieldTemplate.d.ts +3 -0
- package/dist/Common/RJSF/templates/TitleField.d.ts +3 -0
- package/dist/Common/RJSF/templates/WrapIfAdditionalTemplate.d.ts +3 -0
- package/dist/Common/RJSF/templates/index.d.ts +10 -0
- package/dist/Common/RJSF/types.d.ts +3 -0
- package/dist/Common/RJSF/utils.d.ts +14 -0
- package/dist/Common/RJSF/widgets/Checkbox.d.ts +3 -0
- package/dist/Common/RJSF/widgets/Select.d.ts +3 -0
- package/dist/Common/RJSF/widgets/index.d.ts +2 -0
- package/dist/Common/Types.d.ts +36 -2
- package/dist/Common/index.d.ts +1 -0
- package/dist/index.js +567 -222
- package/package.json +4 -1
- package/src/Assets/Icon/ic-chevron-down.svg +5 -0
- package/src/Common/Common.service.ts +223 -76
- package/src/Common/Constants.ts +1 -0
- package/src/Common/ImageTags.tsx +11 -2
- package/src/Common/RJSF/Form.tsx +29 -0
- package/src/Common/RJSF/common/FieldRow.tsx +31 -0
- package/src/Common/RJSF/common/types.ts +9 -0
- package/src/Common/RJSF/config.ts +37 -0
- package/src/Common/RJSF/constants.ts +5 -0
- package/src/Common/RJSF/index.ts +2 -0
- package/src/Common/RJSF/rjsfForm.scss +17 -0
- package/src/Common/RJSF/templates/ArrayFieldItemTemplate.tsx +33 -0
- package/src/Common/RJSF/templates/ArrayFieldTemplate.tsx +77 -0
- package/src/Common/RJSF/templates/BaseInput.tsx +16 -0
- package/src/Common/RJSF/templates/ButtonTemplates/AddButton.tsx +18 -0
- package/src/Common/RJSF/templates/ButtonTemplates/RemoveButton.tsx +10 -0
- package/src/Common/RJSF/templates/ButtonTemplates/SubmitButton.tsx +18 -0
- package/src/Common/RJSF/templates/ButtonTemplates/index.ts +3 -0
- package/src/Common/RJSF/templates/Description.tsx +12 -0
- package/src/Common/RJSF/templates/Field.tsx +30 -0
- package/src/Common/RJSF/templates/FieldErrorTemplate.tsx +25 -0
- package/src/Common/RJSF/templates/ObjectFieldTemplate.tsx +96 -0
- package/src/Common/RJSF/templates/TitleField.tsx +9 -0
- package/src/Common/RJSF/templates/WrapIfAdditionalTemplate.tsx +51 -0
- package/src/Common/RJSF/templates/index.ts +10 -0
- package/src/Common/RJSF/types.ts +4 -0
- package/src/Common/RJSF/utils.ts +59 -0
- package/src/Common/RJSF/widgets/Checkbox.tsx +44 -0
- package/src/Common/RJSF/widgets/Select.tsx +76 -0
- package/src/Common/RJSF/widgets/index.ts +2 -0
- package/src/Common/Types.ts +44 -2
- package/src/Common/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devtron-labs/devtron-fe-common-lib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.40-beta-1",
|
|
4
4
|
"description": "Supporting common component library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -41,6 +41,9 @@
|
|
|
41
41
|
"@sentry/browser": "^7.31.1"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
|
+
"@rjsf/core": "^5.13.3",
|
|
45
|
+
"@rjsf/utils": "^5.13.3",
|
|
46
|
+
"@rjsf/validator-ajv8": "^5.13.3",
|
|
44
47
|
"react": "^17.0.2",
|
|
45
48
|
"react-dom": "^17.0.2",
|
|
46
49
|
"react-router": "^5.3.0",
|
|
@@ -2,7 +2,19 @@ import moment from 'moment';
|
|
|
2
2
|
import {get, post} from './Api';
|
|
3
3
|
import { ROUTES } from './Constants'
|
|
4
4
|
import { sortCallback } from './Helper';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
TeamList,
|
|
7
|
+
ResponseType,
|
|
8
|
+
DeploymentNodeType,
|
|
9
|
+
CDModalTab,
|
|
10
|
+
FilterStates,
|
|
11
|
+
CDMaterialServiceEnum,
|
|
12
|
+
CDMaterialServiceQueryParams,
|
|
13
|
+
CDMaterialResponseType,
|
|
14
|
+
CDMaterialsMetaInfo,
|
|
15
|
+
CDMaterialsApprovalInfo,
|
|
16
|
+
CDMaterialFilterQuery,
|
|
17
|
+
} from './Types'
|
|
6
18
|
|
|
7
19
|
export const getTeamListMin = (): Promise<TeamList> => {
|
|
8
20
|
// ignore active field
|
|
@@ -30,7 +42,7 @@ interface UserRole extends ResponseType {
|
|
|
30
42
|
}
|
|
31
43
|
}
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
const stageMap = {
|
|
34
46
|
PRECD: 'PRE',
|
|
35
47
|
CD: 'DEPLOY',
|
|
36
48
|
POSTCD: 'POST',
|
|
@@ -51,83 +63,218 @@ export function setImageTags(request, pipelineId: number, artifactId: number){
|
|
|
51
63
|
return post(`${ROUTES.IMAGE_TAGGING}/${pipelineId}/${artifactId}`,request )
|
|
52
64
|
}
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (!response.result) {
|
|
68
|
-
return {
|
|
69
|
-
materials: [],
|
|
66
|
+
const processURL = (url: string, params: object) => {
|
|
67
|
+
const validParams = Object.keys(params).filter((key) => {
|
|
68
|
+
return params[key] != null
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
if (!validParams.length) {
|
|
72
|
+
return url
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const queryString = validParams
|
|
76
|
+
.map((key) => {
|
|
77
|
+
if (Array.isArray(params[key])) {
|
|
78
|
+
return `${key}=${params[key].join(',')}`
|
|
70
79
|
}
|
|
80
|
+
return `${key}=${params[key]}`
|
|
81
|
+
})
|
|
82
|
+
.join('&')
|
|
83
|
+
|
|
84
|
+
return `${url}?${queryString}`
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const cdMaterialListModal = (artifacts: any[], offset: number, artifactId?: number, artifactStatus?: string) => {
|
|
88
|
+
if (!artifacts || !artifacts.length) return []
|
|
89
|
+
|
|
90
|
+
const markFirstSelected = offset === 0
|
|
91
|
+
const startIndex = offset
|
|
92
|
+
let isImageMarked = false
|
|
93
|
+
|
|
94
|
+
const materials = artifacts.map((material, index) => {
|
|
95
|
+
let artifactStatusValue = ''
|
|
96
|
+
const filterState = material.filterState ?? FilterStates.ALLOWED
|
|
97
|
+
|
|
98
|
+
if (artifactId && artifactStatus && material.id === artifactId) {
|
|
99
|
+
artifactStatusValue = artifactStatus
|
|
71
100
|
}
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
101
|
+
|
|
102
|
+
const selectImage =
|
|
103
|
+
!isImageMarked && markFirstSelected && filterState === FilterStates.ALLOWED ? !material.vulnerable : false
|
|
104
|
+
if (selectImage) {
|
|
105
|
+
isImageMarked = true
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
index: startIndex + index,
|
|
110
|
+
id: material.id,
|
|
111
|
+
deployedTime: material.deployed_time
|
|
112
|
+
? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
|
|
113
|
+
: 'Not Deployed',
|
|
114
|
+
deployedBy: material.deployedBy,
|
|
115
|
+
wfrId: material.wfrId,
|
|
116
|
+
tab: CDModalTab.Changes,
|
|
117
|
+
image: extractImage(material.image),
|
|
118
|
+
showChanges: false,
|
|
119
|
+
vulnerabilities: [],
|
|
120
|
+
buildTime: material.build_time || '',
|
|
121
|
+
isSelected: selectImage,
|
|
122
|
+
showSourceInfo: false,
|
|
123
|
+
deployed: material.deployed || false,
|
|
124
|
+
latest: material.latest || false,
|
|
125
|
+
vulnerabilitiesLoading: true,
|
|
126
|
+
scanned: material.scanned,
|
|
127
|
+
scanEnabled: material.scanEnabled,
|
|
128
|
+
vulnerable: material.vulnerable,
|
|
129
|
+
runningOnParentCd: material.runningOnParentCd,
|
|
130
|
+
artifactStatus: artifactStatusValue,
|
|
131
|
+
userApprovalMetadata: material.userApprovalMetadata,
|
|
132
|
+
triggeredBy: material.triggeredBy,
|
|
133
|
+
isVirtualEnvironment: material.isVirtualEnvironment,
|
|
134
|
+
imageComment: material.imageComment,
|
|
135
|
+
imageReleaseTags: material.imageReleaseTags,
|
|
136
|
+
// It is going to be null but required in type so can't remove
|
|
137
|
+
lastExecution: material.lastExecution,
|
|
138
|
+
materialInfo: material.material_info
|
|
139
|
+
? material.material_info.map((mat) => {
|
|
140
|
+
return {
|
|
141
|
+
modifiedTime: mat.modifiedTime
|
|
142
|
+
? moment(mat.modifiedTime).format('ddd, DD MMM YYYY, hh:mm A')
|
|
143
|
+
: '',
|
|
144
|
+
commitLink: createGitCommitUrl(mat.url, mat.revision),
|
|
145
|
+
author: mat.author || '',
|
|
146
|
+
message: mat.message || '',
|
|
147
|
+
revision: mat.revision || '',
|
|
148
|
+
tag: mat.tag || '',
|
|
149
|
+
webhookData: mat.webhookData || '',
|
|
150
|
+
url: mat.url || '',
|
|
151
|
+
branch:
|
|
152
|
+
(material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
|
|
153
|
+
? material.ciConfigureSourceValue
|
|
154
|
+
: mat.branch) || '',
|
|
155
|
+
type: material.ciConfigureSourceType || '',
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
: [],
|
|
159
|
+
filterState,
|
|
160
|
+
appliedFiltersTimestamp: material.appliedFiltersTimestamp ?? '',
|
|
161
|
+
appliedFilters: material.appliedFilters ?? [],
|
|
162
|
+
appliedFiltersState: material.appliedFiltersState ?? FilterStates.ALLOWED,
|
|
163
|
+
createdTime: material.createdTime ?? '',
|
|
164
|
+
dataSource: material.data_source ?? '',
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
return materials
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const processCDMaterialsApprovalInfo = (enableApproval: boolean, cdMaterialsResult): CDMaterialsApprovalInfo => {
|
|
171
|
+
if (!enableApproval) {
|
|
172
|
+
return {
|
|
173
|
+
approvalUsers: [],
|
|
174
|
+
userApprovalConfig: null,
|
|
175
|
+
requestedUserId: 0,
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
approvalUsers: cdMaterialsResult.approvalUsers,
|
|
181
|
+
userApprovalConfig: cdMaterialsResult.userApprovalConfig,
|
|
182
|
+
requestedUserId: cdMaterialsResult.requestedUserId,
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const processCDMaterialsMetaInfo = (cdMaterialsResult): CDMaterialsMetaInfo => {
|
|
187
|
+
if (!cdMaterialsResult) {
|
|
188
|
+
return {
|
|
189
|
+
tagsEditable: false,
|
|
190
|
+
appReleaseTagNames: [],
|
|
191
|
+
hideImageTaggingHardDelete: false,
|
|
192
|
+
resourceFilters: [],
|
|
193
|
+
totalCount: 0,
|
|
194
|
+
canApproverDeploy: cdMaterialsResult.canApproverDeploy ?? false,
|
|
130
195
|
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
appReleaseTagNames: cdMaterialsResult.appReleaseTagNames,
|
|
200
|
+
tagsEditable: cdMaterialsResult.tagsEditable,
|
|
201
|
+
hideImageTaggingHardDelete: cdMaterialsResult.hideImageTaggingHardDelete,
|
|
202
|
+
resourceFilters: cdMaterialsResult.resourceFilters ?? [],
|
|
203
|
+
totalCount: cdMaterialsResult.totalCount ?? 0,
|
|
204
|
+
canApproverDeploy: cdMaterialsResult.canApproverDeploy ?? false,
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const processCDMaterialServiceResponse = (
|
|
209
|
+
cdMaterialsResult,
|
|
210
|
+
stage: DeploymentNodeType,
|
|
211
|
+
offset: number,
|
|
212
|
+
filter: CDMaterialFilterQuery,
|
|
213
|
+
): CDMaterialResponseType => {
|
|
214
|
+
if (!cdMaterialsResult) {
|
|
215
|
+
return {
|
|
216
|
+
materials: [],
|
|
217
|
+
...processCDMaterialsMetaInfo(cdMaterialsResult),
|
|
218
|
+
...processCDMaterialsApprovalInfo(false, cdMaterialsResult),
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const materials = cdMaterialListModal(
|
|
223
|
+
cdMaterialsResult.ci_artifacts,
|
|
224
|
+
offset ?? 0,
|
|
225
|
+
cdMaterialsResult.latest_wf_artifact_id,
|
|
226
|
+
cdMaterialsResult.latest_wf_artifact_status,
|
|
227
|
+
)
|
|
228
|
+
const approvalInfo = processCDMaterialsApprovalInfo(
|
|
229
|
+
stage === DeploymentNodeType.CD || stage === DeploymentNodeType.APPROVAL,
|
|
230
|
+
cdMaterialsResult,
|
|
231
|
+
)
|
|
232
|
+
const metaInfo = processCDMaterialsMetaInfo(cdMaterialsResult)
|
|
233
|
+
|
|
234
|
+
// TODO: On update of service would remove from here
|
|
235
|
+
const filteredMaterials =
|
|
236
|
+
filter && filter === CDMaterialFilterQuery.RESOURCE
|
|
237
|
+
? materials.filter((material) => {
|
|
238
|
+
return material.filterState === FilterStates.ALLOWED
|
|
239
|
+
})
|
|
240
|
+
: materials
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
materials: filteredMaterials,
|
|
244
|
+
...approvalInfo,
|
|
245
|
+
...metaInfo,
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const getSanitizedQueryParams = (queryParams: CDMaterialServiceQueryParams): CDMaterialServiceQueryParams => {
|
|
250
|
+
const { filter, ...rest } = queryParams
|
|
251
|
+
return rest
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export const genericCDMaterialsService = (
|
|
255
|
+
serviceType: CDMaterialServiceEnum,
|
|
256
|
+
cdMaterialID: number,
|
|
257
|
+
stage: DeploymentNodeType,
|
|
258
|
+
signal: AbortSignal,
|
|
259
|
+
queryParams: CDMaterialServiceQueryParams = {},
|
|
260
|
+
): Promise<CDMaterialResponseType> => {
|
|
261
|
+
// TODO: On update of service would remove from here
|
|
262
|
+
const manipulatedParams = getSanitizedQueryParams(queryParams)
|
|
263
|
+
|
|
264
|
+
let URL
|
|
265
|
+
switch (serviceType) {
|
|
266
|
+
case CDMaterialServiceEnum.ROLLBACK:
|
|
267
|
+
URL = processURL(`${ROUTES.CD_MATERIAL_GET}/${cdMaterialID}/material/rollback`, manipulatedParams)
|
|
268
|
+
break
|
|
269
|
+
|
|
270
|
+
// Meant for handling getCDMaterialList
|
|
271
|
+
default:
|
|
272
|
+
URL = processURL(`${ROUTES.CD_MATERIAL_GET}/${cdMaterialID}/material`, { ...manipulatedParams, stage: stageMap[stage] })
|
|
273
|
+
break
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return get(URL, { signal }).then((response) => {
|
|
277
|
+
return processCDMaterialServiceResponse(response.result, stage, queryParams.offset, queryParams.filter)
|
|
131
278
|
})
|
|
132
279
|
}
|
|
133
280
|
|
package/src/Common/Constants.ts
CHANGED
package/src/Common/ImageTags.tsx
CHANGED
|
@@ -18,8 +18,10 @@ import { showError, stopPropagation } from './Helper'
|
|
|
18
18
|
import { TippyCustomized } from './TippyCustomized'
|
|
19
19
|
import { setImageTags } from './Common.service'
|
|
20
20
|
import Tippy from '@tippyjs/react'
|
|
21
|
+
import { Progressing } from './Progressing'
|
|
21
22
|
|
|
22
23
|
export const ImageTagsContainer = ({
|
|
24
|
+
// Setting it to zero in case of external pipeline
|
|
23
25
|
ciPipelineId,
|
|
24
26
|
artifactId,
|
|
25
27
|
imageComment,
|
|
@@ -47,6 +49,7 @@ export const ImageTagsContainer = ({
|
|
|
47
49
|
const [hardDeleteTags, setHardDeleteTags] = useState<ReleaseTag[]>([])
|
|
48
50
|
const [descriptionValidationMessage, setDescriptionValidationMessage] = useState<string>('')
|
|
49
51
|
const [textInput, setTextInput] = useState<string>('')
|
|
52
|
+
const [loading, setLoading] = useState<boolean>(false)
|
|
50
53
|
|
|
51
54
|
|
|
52
55
|
useEffect(() => {
|
|
@@ -213,7 +216,8 @@ export const ImageTagsContainer = ({
|
|
|
213
216
|
}
|
|
214
217
|
|
|
215
218
|
// set loading state true
|
|
216
|
-
|
|
219
|
+
setLoading(true)
|
|
220
|
+
setImageTags(payload, ciPipelineId ?? 0, artifactId)
|
|
217
221
|
.then((res) => {
|
|
218
222
|
const tags = res.result?.imageReleaseTags?.map((tag) => ({
|
|
219
223
|
id: tag.id,
|
|
@@ -249,6 +253,9 @@ export const ImageTagsContainer = ({
|
|
|
249
253
|
showError(err)
|
|
250
254
|
}
|
|
251
255
|
})
|
|
256
|
+
.finally(()=>{
|
|
257
|
+
setLoading(false)
|
|
258
|
+
})
|
|
252
259
|
}
|
|
253
260
|
|
|
254
261
|
const renderInfoCard = (): JSX.Element => {
|
|
@@ -425,6 +432,7 @@ export const ImageTagsContainer = ({
|
|
|
425
432
|
stopPropagation(e)
|
|
426
433
|
handleCancel()
|
|
427
434
|
}}
|
|
435
|
+
disabled={loading}
|
|
428
436
|
>
|
|
429
437
|
Cancel
|
|
430
438
|
</button>
|
|
@@ -436,8 +444,9 @@ export const ImageTagsContainer = ({
|
|
|
436
444
|
stopPropagation(e)
|
|
437
445
|
onClickSave()
|
|
438
446
|
}}
|
|
447
|
+
disabled={loading}
|
|
439
448
|
>
|
|
440
|
-
Save
|
|
449
|
+
{loading ? <Progressing /> : 'Save'}
|
|
441
450
|
</button>
|
|
442
451
|
</div>
|
|
443
452
|
</div>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import RJSF from '@rjsf/core'
|
|
3
|
+
import RJSFValidator from '@rjsf/validator-ajv8'
|
|
4
|
+
|
|
5
|
+
import { templates, widgets } from './config'
|
|
6
|
+
import { FormProps } from './types'
|
|
7
|
+
import { translateString } from './utils'
|
|
8
|
+
import './rjsfForm.scss'
|
|
9
|
+
|
|
10
|
+
// Need to use this way because the default import was not working as expected
|
|
11
|
+
// The default import resolves to an object intead of a function
|
|
12
|
+
const Form = (RJSF as any).default as typeof RJSF
|
|
13
|
+
const validator = (RJSFValidator as any).default as typeof RJSFValidator
|
|
14
|
+
|
|
15
|
+
export const RJSFForm = (props: FormProps) => (
|
|
16
|
+
<Form
|
|
17
|
+
noHtml5Validate
|
|
18
|
+
showErrorList={false}
|
|
19
|
+
autoComplete="off"
|
|
20
|
+
{...props}
|
|
21
|
+
validator={validator}
|
|
22
|
+
templates={{
|
|
23
|
+
...templates,
|
|
24
|
+
...props.templates,
|
|
25
|
+
}}
|
|
26
|
+
widgets={{ ...widgets, ...props.widgets }}
|
|
27
|
+
translateString={translateString}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { FieldRowProps } from './types'
|
|
3
|
+
|
|
4
|
+
export const FieldRowWithLabel = ({
|
|
5
|
+
showLabel,
|
|
6
|
+
label,
|
|
7
|
+
required,
|
|
8
|
+
children,
|
|
9
|
+
id,
|
|
10
|
+
shouldAlignCenter = true,
|
|
11
|
+
}: FieldRowProps) => (
|
|
12
|
+
<div
|
|
13
|
+
className={
|
|
14
|
+
showLabel
|
|
15
|
+
? `display-grid dc__gap-12 rjsf-form-template__field ${shouldAlignCenter ? 'flex-align-center' : ''}`
|
|
16
|
+
: ''
|
|
17
|
+
}
|
|
18
|
+
>
|
|
19
|
+
{showLabel && (
|
|
20
|
+
<label className="cn-7 fs-13 lh-32 fw-4 flexbox mb-0" htmlFor={id}>
|
|
21
|
+
{!!label && (
|
|
22
|
+
<>
|
|
23
|
+
<span className="dc__ellipsis-right">{label}</span>
|
|
24
|
+
{required && <span className="cr-5"> *</span>}
|
|
25
|
+
</>
|
|
26
|
+
)}
|
|
27
|
+
</label>
|
|
28
|
+
)}
|
|
29
|
+
{children}
|
|
30
|
+
</div>
|
|
31
|
+
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { RegistryWidgetsType } from '@rjsf/utils'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
AddButton,
|
|
6
|
+
ArrayFieldItemTemplate,
|
|
7
|
+
ArrayFieldTemplate,
|
|
8
|
+
BaseInputTemplate,
|
|
9
|
+
DescriptionFieldTemplate,
|
|
10
|
+
FieldTemplate,
|
|
11
|
+
FieldErrorTemplate,
|
|
12
|
+
ObjectFieldTemplate,
|
|
13
|
+
RemoveButton,
|
|
14
|
+
SubmitButton,
|
|
15
|
+
TitleFieldTemplate,
|
|
16
|
+
WrapIfAdditionalTemplate,
|
|
17
|
+
} from './templates'
|
|
18
|
+
import { CheckboxWidget, SelectWidget } from './widgets'
|
|
19
|
+
import { FormProps } from './types'
|
|
20
|
+
|
|
21
|
+
export const widgets: RegistryWidgetsType = {
|
|
22
|
+
CheckboxWidget,
|
|
23
|
+
SelectWidget,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const templates: FormProps['templates'] = {
|
|
27
|
+
ArrayFieldItemTemplate,
|
|
28
|
+
ArrayFieldTemplate,
|
|
29
|
+
BaseInputTemplate,
|
|
30
|
+
ButtonTemplates: { AddButton, RemoveButton, SubmitButton },
|
|
31
|
+
DescriptionFieldTemplate,
|
|
32
|
+
FieldTemplate,
|
|
33
|
+
FieldErrorTemplate,
|
|
34
|
+
ObjectFieldTemplate,
|
|
35
|
+
TitleFieldTemplate,
|
|
36
|
+
WrapIfAdditionalTemplate,
|
|
37
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.rjsf-form-template {
|
|
2
|
+
&__field {
|
|
3
|
+
grid-template-columns: 250px 1fr;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
&__additional-fields {
|
|
7
|
+
grid-template-columns: 1fr 1fr minmax(20px, auto);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&__array-field-item {
|
|
11
|
+
grid-template-columns: 1fr auto;
|
|
12
|
+
|
|
13
|
+
& :first-child {
|
|
14
|
+
margin: 0;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { CSSProperties } from 'react'
|
|
2
|
+
import { ArrayFieldTemplateItemType } from '@rjsf/utils'
|
|
3
|
+
|
|
4
|
+
export const ArrayFieldItemTemplate = ({
|
|
5
|
+
children,
|
|
6
|
+
className,
|
|
7
|
+
disabled,
|
|
8
|
+
hasToolbar,
|
|
9
|
+
hasRemove,
|
|
10
|
+
index,
|
|
11
|
+
onDropIndexClick,
|
|
12
|
+
readonly,
|
|
13
|
+
registry,
|
|
14
|
+
uiSchema,
|
|
15
|
+
}: ArrayFieldTemplateItemType) => {
|
|
16
|
+
const { RemoveButton } = registry.templates.ButtonTemplates
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="display-grid rjsf-form-template__array-field-item flex-align-center dc__gap-8 mb-12">
|
|
20
|
+
{children}
|
|
21
|
+
{hasToolbar && hasRemove && (
|
|
22
|
+
<div>
|
|
23
|
+
<RemoveButton
|
|
24
|
+
disabled={disabled || readonly}
|
|
25
|
+
onClick={onDropIndexClick(index)}
|
|
26
|
+
uiSchema={uiSchema}
|
|
27
|
+
registry={registry}
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
)}
|
|
31
|
+
</div>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { getTemplate, getUiOptions, ArrayFieldTemplateProps, ArrayFieldTemplateItemType } from '@rjsf/utils'
|
|
3
|
+
import { FieldRowWithLabel } from '../common/FieldRow'
|
|
4
|
+
|
|
5
|
+
const ActionButton = ({ canAdd, onAddClick, disabled, readonly, uiSchema, registry }) => {
|
|
6
|
+
const {
|
|
7
|
+
ButtonTemplates: { AddButton },
|
|
8
|
+
} = registry.templates
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
canAdd && (
|
|
12
|
+
<AddButton onClick={onAddClick} disabled={disabled || readonly} uiSchema={uiSchema} registry={registry} />
|
|
13
|
+
)
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ArrayFieldTemplate = ({
|
|
18
|
+
canAdd,
|
|
19
|
+
className,
|
|
20
|
+
disabled,
|
|
21
|
+
idSchema,
|
|
22
|
+
uiSchema,
|
|
23
|
+
items,
|
|
24
|
+
onAddClick,
|
|
25
|
+
readonly,
|
|
26
|
+
registry,
|
|
27
|
+
required,
|
|
28
|
+
title,
|
|
29
|
+
}: ArrayFieldTemplateProps) => {
|
|
30
|
+
const uiOptions = getUiOptions(uiSchema)
|
|
31
|
+
const ArrayFieldItemTemplate = getTemplate<'ArrayFieldItemTemplate'>('ArrayFieldItemTemplate', registry, uiOptions)
|
|
32
|
+
const label = uiOptions.title || title
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<fieldset className={className} id={idSchema.$id}>
|
|
36
|
+
{/* Show the label here in case there are no items, otherwise handled by Field Template */}
|
|
37
|
+
{items.length ? (
|
|
38
|
+
<>
|
|
39
|
+
{items.map(({ key, ...itemProps }: ArrayFieldTemplateItemType, index) => {
|
|
40
|
+
// Show the title as the label for the first field
|
|
41
|
+
const children = {
|
|
42
|
+
...itemProps.children,
|
|
43
|
+
props: {
|
|
44
|
+
...itemProps.children.props,
|
|
45
|
+
name: index === 0 ? label : '',
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
return (
|
|
49
|
+
<ArrayFieldItemTemplate key={key} {...itemProps}>
|
|
50
|
+
{children}
|
|
51
|
+
</ArrayFieldItemTemplate>
|
|
52
|
+
)
|
|
53
|
+
})}
|
|
54
|
+
<ActionButton
|
|
55
|
+
canAdd={canAdd}
|
|
56
|
+
onAddClick={onAddClick}
|
|
57
|
+
disabled={disabled}
|
|
58
|
+
readonly={readonly}
|
|
59
|
+
uiSchema={uiSchema}
|
|
60
|
+
registry={registry}
|
|
61
|
+
/>
|
|
62
|
+
</>
|
|
63
|
+
) : (
|
|
64
|
+
<FieldRowWithLabel label={label} required={required} showLabel id={idSchema.$id}>
|
|
65
|
+
<ActionButton
|
|
66
|
+
canAdd={canAdd}
|
|
67
|
+
onAddClick={onAddClick}
|
|
68
|
+
disabled={disabled}
|
|
69
|
+
readonly={readonly}
|
|
70
|
+
uiSchema={uiSchema}
|
|
71
|
+
registry={registry}
|
|
72
|
+
/>
|
|
73
|
+
</FieldRowWithLabel>
|
|
74
|
+
)}
|
|
75
|
+
</fieldset>
|
|
76
|
+
)
|
|
77
|
+
}
|