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,32 @@ 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
+ const params = this . state . params [ key ] ;
140
+
141
+ // if each string in params is empty string, set params to null
142
+ if ( params . every ( ( p : string ) => p . trim ( ) === '' ) ) {
143
+ localizations . push ( {
144
+ uuid : component . uuid ,
145
+ translations : null
146
+ } ) ;
147
+ } else {
148
+ localizations . push ( {
149
+ uuid : component . uuid ,
150
+ translations : { params }
151
+ } ) ;
152
+ }
153
+ }
136
154
} ) ;
137
155
}
138
-
139
156
this . props . updateLocalizations ( this . props . language . id , localizations ) ;
140
157
141
158
// notify our modal we are done
@@ -157,26 +174,20 @@ export default class MsgLocalizationForm extends React.Component<
157
174
this . handleUpdate ( { quickReplies } ) ;
158
175
}
159
176
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 } ) ;
177
+ private handleTemplateVariableChanged ( event : any ) : void {
178
+ this . setState ( { params : event . detail . params } ) ;
168
179
}
169
180
170
181
private handleAttachmentUploading ( isUploading : boolean ) {
171
- const uploadError : string = '' ;
182
+ const uploadError = '' ;
172
183
console . log ( uploadError ) ;
173
184
this . setState ( { uploadError } ) ;
174
185
175
186
if ( isUploading ) {
176
- const uploadInProgress : boolean = true ;
187
+ const uploadInProgress = true ;
177
188
this . setState ( { uploadInProgress } ) ;
178
189
} else {
179
- const uploadInProgress : boolean = false ;
190
+ const uploadInProgress = false ;
180
191
this . setState ( { uploadInProgress } ) ;
181
192
}
182
193
}
@@ -193,18 +204,18 @@ export default class MsgLocalizationForm extends React.Component<
193
204
} ) ;
194
205
this . setState ( { attachments } ) ;
195
206
196
- const uploadError : string = '' ;
207
+ const uploadError = '' ;
197
208
console . log ( uploadError ) ;
198
209
this . setState ( { uploadError } ) ;
199
210
}
200
211
201
- const uploadInProgress : boolean = false ;
212
+ const uploadInProgress = false ;
202
213
this . setState ( { uploadInProgress } ) ;
203
214
}
204
215
205
216
private handleAttachmentUploadFailed ( error : AxiosError ) {
206
217
//nginx returns a 300+ if there's an error
207
- let uploadError : string = '' ;
218
+ let uploadError = '' ;
208
219
const status = error . response . status ;
209
220
if ( status >= 500 ) {
210
221
uploadError = i18n . t ( 'file_upload_failed_generic' , 'File upload failed, please try again' ) ;
@@ -215,7 +226,7 @@ export default class MsgLocalizationForm extends React.Component<
215
226
}
216
227
this . setState ( { uploadError } ) ;
217
228
218
- const uploadInProgress : boolean = false ;
229
+ const uploadInProgress = false ;
219
230
this . setState ( { uploadInProgress } ) ;
220
231
}
221
232
@@ -249,16 +260,7 @@ export default class MsgLocalizationForm extends React.Component<
249
260
const typeConfig = determineTypeConfig ( this . props . nodeSettings ) ;
250
261
const tabs : Tab [ ] = [ ] ;
251
262
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
-
263
+ if ( this . state . templating ) {
262
264
tabs . push ( {
263
265
name : 'WhatsApp' ,
264
266
body : (
@@ -269,30 +271,22 @@ export default class MsgLocalizationForm extends React.Component<
269
271
'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
272
) }
271
273
</ 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
- </ >
274
+ { this . state . templating ? (
275
+ < TembaComponent
276
+ tag = "temba-template-editor"
277
+ eventHandlers = { {
278
+ 'temba-content-changed' : this . handleTemplateVariableChanged
279
+ } }
280
+ template = { this . state . templating . template . uuid }
281
+ url = { this . props . assetStore . templates . endpoint }
282
+ lang = { this . props . language . id }
283
+ params = { JSON . stringify ( this . state . params ) }
284
+ translating = { true }
285
+ > </ TembaComponent >
292
286
) : null }
293
287
</ >
294
288
) ,
295
- checked : hasLocalizedValue
289
+ checked : true // hasLocalizedValue
296
290
} ) ;
297
291
}
298
292
0 commit comments