ciyidogan commited on
Commit
0fc1d64
·
verified ·
1 Parent(s): d0bbbb3

Update flare-ui/src/app/dialogs/api-edit-dialog/api-edit-dialog.component.ts

Browse files
flare-ui/src/app/dialogs/api-edit-dialog/api-edit-dialog.component.ts CHANGED
@@ -42,18 +42,13 @@ export default class ApiEditDialogComponent implements OnInit {
42
  saving = false;
43
  testing = false;
44
  testResult: any = null;
 
 
 
45
 
46
  httpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
47
  retryStrategies = ['static', 'exponential'];
48
-
49
- // Template variable helpers
50
- templateVariables = [
51
- { key: 'variables.origin', desc: 'Origin city from session' },
52
- { key: 'variables.destination', desc: 'Destination city from session' },
53
- { key: 'variables.flight_date', desc: 'Flight date from session' },
54
- { key: 'auth_tokens.api_name.token', desc: 'Auth token for this API' },
55
- { key: 'config.work_mode', desc: 'Current work mode' }
56
- ];
57
 
58
  constructor(
59
  private fb: FormBuilder,
@@ -65,6 +60,7 @@ export default class ApiEditDialogComponent implements OnInit {
65
 
66
  ngOnInit() {
67
  this.initializeForm();
 
68
 
69
  if (this.data.mode === 'edit' && this.data.api) {
70
  this.populateForm(this.data.api);
@@ -74,6 +70,11 @@ export default class ApiEditDialogComponent implements OnInit {
74
  delete duplicateData.last_update_date;
75
  this.populateForm(duplicateData);
76
  }
 
 
 
 
 
77
  }
78
 
79
  initializeForm() {
@@ -85,6 +86,7 @@ export default class ApiEditDialogComponent implements OnInit {
85
  body_template: ['{}'],
86
  timeout_seconds: [10, [Validators.required, Validators.min(1), Validators.max(300)]],
87
  response_prompt: [''],
 
88
 
89
  // Headers Tab
90
  headers: this.fb.array([]),
@@ -139,6 +141,16 @@ export default class ApiEditDialogComponent implements OnInit {
139
  });
140
  }
141
 
 
 
 
 
 
 
 
 
 
 
142
  // Convert body_template to JSON string if it's an object
143
  if (api.body_template && typeof api.body_template === 'object') {
144
  api.body_template = JSON.stringify(api.body_template, null, 2);
@@ -167,6 +179,10 @@ export default class ApiEditDialogComponent implements OnInit {
167
  return this.form.get('headers') as FormArray;
168
  }
169
 
 
 
 
 
170
  createHeaderFormGroup(key = '', value = ''): FormGroup {
171
  return this.fb.group({
172
  key: [key, Validators.required],
@@ -174,6 +190,14 @@ export default class ApiEditDialogComponent implements OnInit {
174
  });
175
  }
176
 
 
 
 
 
 
 
 
 
177
  addHeader() {
178
  this.headers.push(this.createHeaderFormGroup());
179
  }
@@ -182,6 +206,14 @@ export default class ApiEditDialogComponent implements OnInit {
182
  this.headers.removeAt(index);
183
  }
184
 
 
 
 
 
 
 
 
 
185
  insertTemplateVariable(field: string, variable: string) {
186
  const control = field.includes('.')
187
  ? this.form.get(field)
@@ -194,18 +226,118 @@ export default class ApiEditDialogComponent implements OnInit {
194
  }
195
  }
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  validateJSON(field: string): boolean {
198
  const control = this.form.get(field);
199
  if (!control || !control.value) return true;
200
 
201
  try {
202
- JSON.parse(control.value);
 
 
 
 
 
203
  return true;
204
  } catch {
205
  return false;
206
  }
207
  }
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  async testAPI() {
210
  // Validate form first
211
  const generalValid = this.form.get('url')?.valid && this.form.get('method')?.valid;
@@ -220,7 +352,10 @@ export default class ApiEditDialogComponent implements OnInit {
220
  try {
221
  const testData = this.prepareAPIData();
222
 
223
- // For test, we'll use a sample request
 
 
 
224
  const result = await this.apiService.testAPI(testData).toPromise();
225
  this.testResult = result;
226
 
@@ -246,6 +381,64 @@ export default class ApiEditDialogComponent implements OnInit {
246
  }
247
  }
248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  prepareAPIData(): any {
250
  const formValue = this.form.getRawValue();
251
 
@@ -285,11 +478,12 @@ export default class ApiEditDialogComponent implements OnInit {
285
  name: formValue.name,
286
  url: formValue.url,
287
  method: formValue.method,
288
- headers, // Now it's a dictionary object
289
  body_template,
290
  timeout_seconds: formValue.timeout_seconds,
291
  retry: formValue.retry,
292
- response_prompt: formValue.response_prompt
 
293
  };
294
 
295
  // Add proxy if specified
 
42
  saving = false;
43
  testing = false;
44
  testResult: any = null;
45
+ testRequestJson = '{}';
46
+ allIntentParameters: string[] = [];
47
+ responseMappingVariables: string[] = [];
48
 
49
  httpMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
50
  retryStrategies = ['static', 'exponential'];
51
+ variableTypes = ['str', 'int', 'float', 'bool', 'date'];
 
 
 
 
 
 
 
 
52
 
53
  constructor(
54
  private fb: FormBuilder,
 
60
 
61
  ngOnInit() {
62
  this.initializeForm();
63
+ this.loadIntentParameters();
64
 
65
  if (this.data.mode === 'edit' && this.data.api) {
66
  this.populateForm(this.data.api);
 
70
  delete duplicateData.last_update_date;
71
  this.populateForm(duplicateData);
72
  }
73
+
74
+ // Watch response mappings changes
75
+ this.form.get('response_mappings')?.valueChanges.subscribe(() => {
76
+ this.updateResponseMappingVariables();
77
+ });
78
  }
79
 
80
  initializeForm() {
 
86
  body_template: ['{}'],
87
  timeout_seconds: [10, [Validators.required, Validators.min(1), Validators.max(300)]],
88
  response_prompt: [''],
89
+ response_mappings: this.fb.array([]),
90
 
91
  // Headers Tab
92
  headers: this.fb.array([]),
 
141
  });
142
  }
143
 
144
+ // Convert response_mappings to FormArray
145
+ const responseMappingsArray = this.form.get('response_mappings') as FormArray;
146
+ responseMappingsArray.clear();
147
+
148
+ if (api.response_mappings && Array.isArray(api.response_mappings)) {
149
+ api.response_mappings.forEach((mapping: any) => {
150
+ responseMappingsArray.push(this.createResponseMappingFormGroup(mapping));
151
+ });
152
+ }
153
+
154
  // Convert body_template to JSON string if it's an object
155
  if (api.body_template && typeof api.body_template === 'object') {
156
  api.body_template = JSON.stringify(api.body_template, null, 2);
 
179
  return this.form.get('headers') as FormArray;
180
  }
181
 
182
+ get responseMappings() {
183
+ return this.form.get('response_mappings') as FormArray;
184
+ }
185
+
186
  createHeaderFormGroup(key = '', value = ''): FormGroup {
187
  return this.fb.group({
188
  key: [key, Validators.required],
 
190
  });
191
  }
192
 
193
+ createResponseMappingFormGroup(data: any = {}): FormGroup {
194
+ return this.fb.group({
195
+ variable_name: [data.variable_name || '', [Validators.required, Validators.pattern(/^[a-z_][a-z0-9_]*$/)]],
196
+ type: [data.type || 'str', Validators.required],
197
+ json_path: [data.json_path || '', Validators.required]
198
+ });
199
+ }
200
+
201
  addHeader() {
202
  this.headers.push(this.createHeaderFormGroup());
203
  }
 
206
  this.headers.removeAt(index);
207
  }
208
 
209
+ addResponseMapping() {
210
+ this.responseMappings.push(this.createResponseMappingFormGroup());
211
+ }
212
+
213
+ removeResponseMapping(index: number) {
214
+ this.responseMappings.removeAt(index);
215
+ }
216
+
217
  insertTemplateVariable(field: string, variable: string) {
218
  const control = field.includes('.')
219
  ? this.form.get(field)
 
226
  }
227
  }
228
 
229
+ insertHeaderValue(index: number, variable: string) {
230
+ const headerGroup = this.headers.at(index);
231
+ if (headerGroup) {
232
+ const valueControl = headerGroup.get('value');
233
+ if (valueControl) {
234
+ const currentValue = valueControl.value || '';
235
+ const newValue = currentValue + `{{${variable}}}`;
236
+ valueControl.setValue(newValue);
237
+ }
238
+ }
239
+ }
240
+
241
+ getTemplateVariables(includeResponseMappings = true): string[] {
242
+ const variables = new Set<string>();
243
+
244
+ // Intent parameters
245
+ this.allIntentParameters.forEach(param => {
246
+ variables.add(`variables.${param}`);
247
+ });
248
+
249
+ // Auth tokens
250
+ const apiName = this.form.get('name')?.value || 'api_name';
251
+ variables.add(`auth_tokens.${apiName}.token`);
252
+
253
+ // Response mappings
254
+ if (includeResponseMappings) {
255
+ this.responseMappingVariables.forEach(varName => {
256
+ variables.add(`variables.${varName}`);
257
+ });
258
+ }
259
+
260
+ // Config variables
261
+ variables.add('config.work_mode');
262
+ variables.add('config.cloud_token');
263
+
264
+ return Array.from(variables).sort();
265
+ }
266
+
267
+ updateResponseMappingVariables() {
268
+ this.responseMappingVariables = [];
269
+ const mappings = this.responseMappings.value;
270
+ mappings.forEach((mapping: any) => {
271
+ if (mapping.variable_name) {
272
+ this.responseMappingVariables.push(mapping.variable_name);
273
+ }
274
+ });
275
+ }
276
+
277
+ async loadIntentParameters() {
278
+ try {
279
+ // Tüm projeleri al
280
+ const projects = await this.apiService.getProjects(false).toPromise();
281
+ const params = new Set<string>();
282
+
283
+ projects?.forEach(project => {
284
+ project.versions?.forEach(version => {
285
+ version.intents?.forEach(intent => {
286
+ intent.parameters?.forEach((param: any) => {
287
+ if (param.variable_name) {
288
+ params.add(param.variable_name);
289
+ }
290
+ });
291
+ });
292
+ });
293
+ });
294
+
295
+ this.allIntentParameters = Array.from(params).sort();
296
+ } catch (error) {
297
+ console.error('Failed to load intent parameters:', error);
298
+ }
299
+ }
300
+
301
  validateJSON(field: string): boolean {
302
  const control = this.form.get(field);
303
  if (!control || !control.value) return true;
304
 
305
  try {
306
+ const jsonStr = control.value;
307
+
308
+ // Template değişkenlerini placeholder değerlerle değiştir
309
+ const processedJson = this.replaceVariablesForValidation(jsonStr);
310
+
311
+ JSON.parse(processedJson);
312
  return true;
313
  } catch {
314
  return false;
315
  }
316
  }
317
 
318
+ replaceVariablesForValidation(jsonStr: string): string {
319
+ let processed = jsonStr;
320
+
321
+ // Numeric değişkenler için
322
+ const numericVars = ['passenger_count', 'count', 'timeout_seconds', 'retry_count'];
323
+ numericVars.forEach(varName => {
324
+ const regex = new RegExp(`{{\\s*variables\\.${varName}\\s*}}`, 'g');
325
+ processed = processed.replace(regex, '1');
326
+ });
327
+
328
+ // Boolean değişkenler için
329
+ const booleanVars = ['enabled', 'published'];
330
+ booleanVars.forEach(varName => {
331
+ const regex = new RegExp(`{{\\s*variables\\.${varName}\\s*}}`, 'g');
332
+ processed = processed.replace(regex, 'true');
333
+ });
334
+
335
+ // Diğer tüm değişkenler için string değer
336
+ processed = processed.replace(/\{\{[^}]+\}\}/g, '"placeholder"');
337
+
338
+ return processed;
339
+ }
340
+
341
  async testAPI() {
342
  // Validate form first
343
  const generalValid = this.form.get('url')?.valid && this.form.get('method')?.valid;
 
352
  try {
353
  const testData = this.prepareAPIData();
354
 
355
+ // Test için request JSON'ını hazırla
356
+ const testRequestData = this.prepareTestRequest();
357
+ testData.test_request = testRequestData;
358
+
359
  const result = await this.apiService.testAPI(testData).toPromise();
360
  this.testResult = result;
361
 
 
381
  }
382
  }
383
 
384
+ prepareTestRequest(): any {
385
+ try {
386
+ const requestData = JSON.parse(this.testRequestJson);
387
+ return requestData;
388
+ } catch {
389
+ return {};
390
+ }
391
+ }
392
+
393
+ updateTestRequestJson() {
394
+ const formValue = this.form.getRawValue();
395
+ let bodyTemplate = {};
396
+
397
+ try {
398
+ bodyTemplate = JSON.parse(formValue.body_template);
399
+ } catch {
400
+ bodyTemplate = {};
401
+ }
402
+
403
+ // Placeholder değerlerle doldur
404
+ const testData = this.replacePlaceholdersForTest(bodyTemplate);
405
+ this.testRequestJson = JSON.stringify(testData, null, 2);
406
+ }
407
+
408
+ replacePlaceholdersForTest(obj: any): any {
409
+ if (typeof obj === 'string') {
410
+ // Template değişkenlerini test değerleriyle değiştir
411
+ let result = obj;
412
+
413
+ // Intent parameters
414
+ result = result.replace(/\{\{variables\.origin\}\}/g, 'Istanbul');
415
+ result = result.replace(/\{\{variables\.destination\}\}/g, 'Ankara');
416
+ result = result.replace(/\{\{variables\.flight_date\}\}/g, '2025-06-15');
417
+ result = result.replace(/\{\{variables\.passenger_count\}\}/g, '2');
418
+ result = result.replace(/\{\{variables\.flight_number\}\}/g, 'TK123');
419
+ result = result.replace(/\{\{variables\.pnr\}\}/g, 'ABC12');
420
+ result = result.replace(/\{\{variables\.surname\}\}/g, 'Test');
421
+
422
+ // Auth tokens
423
+ result = result.replace(/\{\{auth_tokens\.[^}]+\.token\}\}/g, 'test_token_123');
424
+
425
+ // Config
426
+ result = result.replace(/\{\{config\.work_mode\}\}/g, 'hfcloud');
427
+
428
+ // Diğer değişkenler
429
+ result = result.replace(/\{\{[^}]+\}\}/g, 'test_value');
430
+
431
+ return result;
432
+ } else if (typeof obj === 'object' && obj !== null) {
433
+ const result: any = Array.isArray(obj) ? [] : {};
434
+ for (const key in obj) {
435
+ result[key] = this.replacePlaceholdersForTest(obj[key]);
436
+ }
437
+ return result;
438
+ }
439
+ return obj;
440
+ }
441
+
442
  prepareAPIData(): any {
443
  const formValue = this.form.getRawValue();
444
 
 
478
  name: formValue.name,
479
  url: formValue.url,
480
  method: formValue.method,
481
+ headers,
482
  body_template,
483
  timeout_seconds: formValue.timeout_seconds,
484
  retry: formValue.retry,
485
+ response_prompt: formValue.response_prompt,
486
+ response_mappings: formValue.response_mappings || []
487
  };
488
 
489
  // Add proxy if specified