@@ -6,11 +6,13 @@ import {
6
6
ButtonProps ,
7
7
CircularProgress ,
8
8
Stack ,
9
+ Tab ,
9
10
Table ,
10
11
TableBody ,
11
12
TableCell ,
12
13
TableHead ,
13
14
TableRow ,
15
+ Tabs ,
14
16
Typography ,
15
17
} from "@mui/material" ;
16
18
import Form , { IChangeEvent } from "@rjsf/core" ;
@@ -88,6 +90,11 @@ const ReadOnlyValueField: React.FC<{
88
90
return value as string ;
89
91
} ;
90
92
93
+ type InnerAdminEditorStateType = {
94
+ tab : number ;
95
+ formData : Record < string , string > | undefined ;
96
+ } ;
97
+
91
98
const InnerAdminEditor : React . FC < AppResourceIdType & AdminEditorPropsType > =
92
99
ErrorBoundary . with (
93
100
{ fallback : Common . Components . ErrorFallback } ,
@@ -110,9 +117,11 @@ const InnerAdminEditor: React.FC<AppResourceIdType & AdminEditorPropsType> =
110
117
RJSFSchema ,
111
118
{ [ k in string ] : unknown }
112
119
> | null > ( null ) ;
113
- const [ formDataState , setFormDataState ] = React . useState <
114
- Record < string , string > | undefined
115
- > ( undefined ) ;
120
+ const [ editorState , setEditorState ] =
121
+ React . useState < InnerAdminEditorStateType > ( {
122
+ tab : 0 ,
123
+ formData : undefined ,
124
+ } ) ;
116
125
const backendAdminClient =
117
126
Common . Hooks . BackendAdminAPI . useBackendAdminClient ( ) ;
118
127
const { data : schemaInfo } =
@@ -122,6 +131,13 @@ const InnerAdminEditor: React.FC<AppResourceIdType & AdminEditorPropsType> =
122
131
resource
123
132
) ;
124
133
134
+ const setTab = ( _ : React . SyntheticEvent , selectedTab : number ) =>
135
+ setEditorState ( ( ps ) => ( { ...ps , tab : selectedTab } ) ) ;
136
+ const setFormDataState = ( formData ?: Record < string , string > ) =>
137
+ setEditorState ( ( ps ) => ( { ...ps , formData } ) ) ;
138
+ const selectedLanguage = editorState . tab === 0 ? "ko" : "en" ;
139
+ const notSelectedLanguage = editorState . tab === 0 ? "en" : "ko" ;
140
+
125
141
const createMutation = Common . Hooks . BackendAdminAPI . useCreateMutation <
126
142
Record < string , string >
127
143
> ( backendAdminClient , app , resource ) ;
@@ -195,16 +211,40 @@ const InnerAdminEditor: React.FC<AppResourceIdType & AdminEditorPropsType> =
195
211
const goToCreateNew = ( ) => navigate ( `/${ app } /${ resource } /create` ) ;
196
212
197
213
const writableSchema =
198
- Common . Utils . filterWritablePropertiesInJsonSchema ( schemaInfo . schema ) ;
214
+ Common . Utils . filterPropertiesByLanguageInJsonSchema (
215
+ Common . Utils . filterWritablePropertiesInJsonSchema (
216
+ schemaInfo . schema
217
+ ) ,
218
+ schemaInfo . translation_fields ,
219
+ selectedLanguage
220
+ ) ;
199
221
const readOnlySchema =
200
- Common . Utils . filterReadOnlyPropertiesInJsonSchema ( schemaInfo . schema ) ;
222
+ Common . Utils . filterPropertiesByLanguageInJsonSchema (
223
+ Common . Utils . filterReadOnlyPropertiesInJsonSchema (
224
+ schemaInfo . schema
225
+ ) ,
226
+ schemaInfo . translation_fields ,
227
+ selectedLanguage
228
+ ) ;
201
229
const uiSchema : UiSchema = schemaInfo . ui_schema ;
202
230
const disabled =
203
231
createMutation . isPending ||
204
232
modifyMutation . isPending ||
205
233
deleteMutation . isPending ;
206
234
const title = `${ app . toUpperCase ( ) } > ${ resource . toUpperCase ( ) } > ${ id ? "편집: " + id : "새 객체 추가" } ` ;
207
235
236
+ const notSelectedLangFields = schemaInfo . translation_fields . map (
237
+ ( f ) => `${ f } _${ notSelectedLanguage } `
238
+ ) ;
239
+ const languageFilteredFormData = editorState . formData
240
+ ? Object . entries ( editorState . formData )
241
+ . filter ( ( [ k ] ) => ! notSelectedLangFields . includes ( k ) )
242
+ . reduce (
243
+ ( acc , [ k , v ] ) => ( { ...acc , [ k ] : v } ) ,
244
+ { } as Record < string , string >
245
+ )
246
+ : undefined ;
247
+
208
248
const handleCtrlSAction : (
209
249
this : GlobalEventHandlers ,
210
250
ev : KeyboardEvent
@@ -225,56 +265,75 @@ const InnerAdminEditor: React.FC<AppResourceIdType & AdminEditorPropsType> =
225
265
} ;
226
266
} , [ ] ) ;
227
267
228
- if ( formDataState === undefined ) return < CircularProgress /> ;
268
+ if ( editorState . formData === undefined ) return < CircularProgress /> ;
229
269
230
270
return (
231
271
< Box sx = { { flexGrow : 1 , width : "100%" , minHeight : "100%" } } >
232
272
< Typography variant = "h5" > { title } </ Typography >
233
- { id && (
234
- < >
235
- < Table >
236
- < TableHead >
237
- < TableRow >
238
- < TableCell > 필드</ TableCell >
239
- < TableCell > 값</ TableCell >
240
- </ TableRow >
241
- </ TableHead >
242
- < TableBody >
243
- { Object . keys ( readOnlySchema . properties || { } ) . map ( ( key ) => (
244
- < TableRow key = { key } >
245
- < TableCell > { key } </ TableCell >
246
- < TableCell >
247
- < ReadOnlyValueField
248
- name = { key }
249
- value = { formDataState ?. [ key ] }
250
- uiSchema = { uiSchema }
251
- />
252
- </ TableCell >
253
- </ TableRow >
254
- ) ) }
255
- </ TableBody >
256
- </ Table >
257
- < br />
258
- </ >
259
- ) }
260
- < MuiForm
261
- ref = { formRef }
262
- schema = { writableSchema }
263
- uiSchema = { {
264
- ...uiSchema ,
265
- "ui:submitButtonOptions" : { norender : true } ,
266
- } }
267
- validator = { customizeValidator ( { AjvClass : AjvDraft04 } ) }
268
- formData = { formDataState }
269
- liveValidate
270
- focusOnFirstError
271
- formContext = { { readonlyAsDisabled : true } }
272
- onChange = { ( { formData } ) => setFormDataState ( formData ) }
273
- onSubmit = { onSubmitFunc }
274
- disabled = { disabled }
275
- showErrorList = { false }
276
- fields = { { file : FileField } }
277
- />
273
+ < Stack
274
+ direction = "row"
275
+ spacing = { 2 }
276
+ sx = { { width : "100%" , height : "100%" , maxWidth : "100%" } }
277
+ >
278
+ < Tabs
279
+ orientation = "vertical"
280
+ value = { editorState . tab }
281
+ onChange = { setTab }
282
+ scrollButtons = { false }
283
+ >
284
+ < Tab wrapped label = "한국어" />
285
+ < Tab wrapped label = "영어" />
286
+ </ Tabs >
287
+ < Box sx = { { flexGrow : 1 } } >
288
+ { id && (
289
+ < >
290
+ < Table >
291
+ < TableHead >
292
+ < TableRow >
293
+ < TableCell > 필드</ TableCell >
294
+ < TableCell > 값</ TableCell >
295
+ </ TableRow >
296
+ </ TableHead >
297
+ < TableBody >
298
+ { Object . keys ( readOnlySchema . properties || { } ) . map (
299
+ ( key ) => (
300
+ < TableRow key = { key } >
301
+ < TableCell > { key } </ TableCell >
302
+ < TableCell >
303
+ < ReadOnlyValueField
304
+ name = { key }
305
+ value = { languageFilteredFormData ?. [ key ] }
306
+ uiSchema = { uiSchema }
307
+ />
308
+ </ TableCell >
309
+ </ TableRow >
310
+ )
311
+ ) }
312
+ </ TableBody >
313
+ </ Table >
314
+ < br />
315
+ </ >
316
+ ) }
317
+ < MuiForm
318
+ ref = { formRef }
319
+ schema = { writableSchema }
320
+ uiSchema = { {
321
+ ...uiSchema ,
322
+ "ui:submitButtonOptions" : { norender : true } ,
323
+ } }
324
+ validator = { customizeValidator ( { AjvClass : AjvDraft04 } ) }
325
+ formData = { languageFilteredFormData }
326
+ liveValidate
327
+ focusOnFirstError
328
+ formContext = { { readonlyAsDisabled : true } }
329
+ onChange = { ( { formData } ) => setFormDataState ( formData ) }
330
+ onSubmit = { onSubmitFunc }
331
+ disabled = { disabled }
332
+ showErrorList = { false }
333
+ fields = { { file : FileField } }
334
+ />
335
+ </ Box >
336
+ </ Stack >
278
337
{ children }
279
338
< Stack
280
339
direction = "row"
0 commit comments