1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
1
3
import { react as bindCallbacks } from 'auto-bind' ;
2
4
import Dialog , { ButtonSet , Tab } from 'components/dialog/Dialog' ;
3
5
import styles from 'components/flow/actions/action/Action.module.scss' ;
@@ -16,16 +18,16 @@ import { MaxOfTenItems, validate } from 'store/validators';
16
18
import { initializeLocalizedForm } from './helpers' ;
17
19
import i18n from 'config/i18n' ;
18
20
import { Trans } from 'react-i18next' ;
19
- import { range } from 'utils' ;
20
21
import { renderIssues } from '../helpers' ;
21
22
import { Attachment , renderAttachments } from '../sendmsg/attachments' ;
22
23
import { AxiosError , AxiosResponse } from 'axios' ;
24
+ import { TembaComponent } from 'temba/TembaComponent' ;
23
25
24
26
export interface MsgLocalizationFormState extends FormState {
25
27
message : StringEntry ;
26
28
quickReplies : StringArrayEntry ;
27
29
audio : StringEntry ;
28
- templateVariables : StringEntry [ ] ;
30
+ params : any ;
29
31
templating : MsgTemplating ;
30
32
attachments : Attachment [ ] ;
31
33
uploadInProgress : boolean ;
@@ -91,7 +93,7 @@ export default class MsgLocalizationForm extends React.Component<
91
93
}
92
94
93
95
private handleSave ( ) : void {
94
- const { message : text , quickReplies, audio, templateVariables , attachments } = this . state ;
96
+ const { message : text , quickReplies, audio, attachments } = this . state ;
95
97
96
98
// make sure we are valid for saving, only quick replies can be invalid
97
99
const typeConfig = determineTypeConfig ( this . props . nodeSettings ) ;
@@ -125,17 +127,22 @@ export default class MsgLocalizationForm extends React.Component<
125
127
}
126
128
] ;
127
129
128
- // if we have template variables, they show up on their own key
129
- const hasTemplateVariables = templateVariables . find (
130
- ( entry : StringEntry ) => entry . value . length > 0
131
- ) ;
132
- if ( hasTemplateVariables ) {
133
- localizations . push ( {
134
- uuid : this . state . templating . uuid ,
135
- translations : { variables : templateVariables . map ( ( entry : StringEntry ) => entry . value ) }
130
+ // save our template components
131
+ const templating = ( this . props . nodeSettings . originalAction as SendMsg ) . templating ;
132
+ if ( this . state . params && templating ) {
133
+ const components = templating . components ;
134
+
135
+ // find the matching component for our params
136
+ Object . keys ( this . state . params ) . forEach ( ( key : any ) => {
137
+ const component = components . find ( ( c : any ) => c . name === key ) ;
138
+ if ( component ) {
139
+ localizations . push ( {
140
+ uuid : component . uuid ,
141
+ translations : { params : this . state . params [ key ] }
142
+ } ) ;
143
+ }
136
144
} ) ;
137
145
}
138
-
139
146
this . props . updateLocalizations ( this . props . language . id , localizations ) ;
140
147
141
148
// notify our modal we are done
@@ -157,26 +164,20 @@ export default class MsgLocalizationForm extends React.Component<
157
164
this . handleUpdate ( { quickReplies } ) ;
158
165
}
159
166
160
- private handleTemplateVariableChanged ( updatedText : string , num : number ) : void {
161
- const entry = validate ( `Variable ${ num + 1 } ` , updatedText , [ ] ) ;
162
-
163
- const templateVariables = mutate ( this . state . templateVariables , {
164
- $merge : { [ num ] : entry }
165
- } ) as StringEntry [ ] ;
166
-
167
- this . setState ( { templateVariables } ) ;
167
+ private handleTemplateVariableChanged ( event : any ) : void {
168
+ this . setState ( { params : event . detail . params } ) ;
168
169
}
169
170
170
171
private handleAttachmentUploading ( isUploading : boolean ) {
171
- const uploadError : string = '' ;
172
+ const uploadError = '' ;
172
173
console . log ( uploadError ) ;
173
174
this . setState ( { uploadError } ) ;
174
175
175
176
if ( isUploading ) {
176
- const uploadInProgress : boolean = true ;
177
+ const uploadInProgress = true ;
177
178
this . setState ( { uploadInProgress } ) ;
178
179
} else {
179
- const uploadInProgress : boolean = false ;
180
+ const uploadInProgress = false ;
180
181
this . setState ( { uploadInProgress } ) ;
181
182
}
182
183
}
@@ -193,18 +194,18 @@ export default class MsgLocalizationForm extends React.Component<
193
194
} ) ;
194
195
this . setState ( { attachments } ) ;
195
196
196
- const uploadError : string = '' ;
197
+ const uploadError = '' ;
197
198
console . log ( uploadError ) ;
198
199
this . setState ( { uploadError } ) ;
199
200
}
200
201
201
- const uploadInProgress : boolean = false ;
202
+ const uploadInProgress = false ;
202
203
this . setState ( { uploadInProgress } ) ;
203
204
}
204
205
205
206
private handleAttachmentUploadFailed ( error : AxiosError ) {
206
207
//nginx returns a 300+ if there's an error
207
- let uploadError : string = '' ;
208
+ let uploadError = '' ;
208
209
const status = error . response . status ;
209
210
if ( status >= 500 ) {
210
211
uploadError = i18n . t ( 'file_upload_failed_generic' , 'File upload failed, please try again' ) ;
@@ -215,7 +216,7 @@ export default class MsgLocalizationForm extends React.Component<
215
216
}
216
217
this . setState ( { uploadError } ) ;
217
218
218
- const uploadInProgress : boolean = false ;
219
+ const uploadInProgress = false ;
219
220
this . setState ( { uploadInProgress } ) ;
220
221
}
221
222
@@ -249,16 +250,7 @@ export default class MsgLocalizationForm extends React.Component<
249
250
const typeConfig = determineTypeConfig ( this . props . nodeSettings ) ;
250
251
const tabs : Tab [ ] = [ ] ;
251
252
252
- if (
253
- this . state . templating &&
254
- typeConfig . localizeableKeys ! . indexOf ( 'templating.variables' ) > - 1
255
- ) {
256
- const hasLocalizedValue = ! ! this . state . templateVariables . find (
257
- ( entry : StringEntry ) => entry . value . length > 0
258
- ) ;
259
-
260
- const variable = i18n . t ( 'forms.variable' , 'Variable' ) ;
261
-
253
+ if ( this . state . templating ) {
262
254
tabs . push ( {
263
255
name : 'WhatsApp' ,
264
256
body : (
@@ -269,30 +261,22 @@ export default class MsgLocalizationForm extends React.Component<
269
261
'Sending messages over a WhatsApp channel requires that a template be used if you have not received a message from a contact in the last 24 hours. Setting a template to use over WhatsApp is especially important for the first message in your flow.'
270
262
) }
271
263
</ p >
272
- { this . state . templating && this . state . templating . variables . length > 0 ? (
273
- < >
274
- { range ( 0 , this . state . templating . variables . length ) . map ( ( num : number ) => {
275
- const entry = this . state . templateVariables [ num ] || { value : '' } ;
276
- return (
277
- < div className = { styles . variable } key = { 'tr_arg_' + num } >
278
- < TextInputElement
279
- name = { `${ i18n . t ( 'forms.variable' , 'Variable' ) } ${ num + 1 } ` }
280
- showLabel = { false }
281
- placeholder = { `${ this . props . language . name } ${ variable } ${ num + 1 } ` }
282
- onChange = { ( updatedText : string ) => {
283
- this . handleTemplateVariableChanged ( updatedText , num ) ;
284
- } }
285
- entry = { entry }
286
- autocomplete = { true }
287
- />
288
- </ div >
289
- ) ;
290
- } ) }
291
- </ >
264
+ { this . state . templating ? (
265
+ < TembaComponent
266
+ tag = "temba-template-editor"
267
+ eventHandlers = { {
268
+ 'temba-content-changed' : this . handleTemplateVariableChanged
269
+ } }
270
+ template = { this . state . templating . template . uuid }
271
+ url = { this . props . assetStore . templates . endpoint }
272
+ lang = { this . props . language . id }
273
+ params = { JSON . stringify ( this . state . params ) }
274
+ translating = { true }
275
+ > </ TembaComponent >
292
276
) : null }
293
277
</ >
294
278
) ,
295
- checked : hasLocalizedValue
279
+ checked : true // hasLocalizedValue
296
280
} ) ;
297
281
}
298
282
0 commit comments