Spaces:
Paused
Paused
| import { Component, Inject, OnInit } from '@angular/core'; | |
| import { CommonModule } from '@angular/common'; | |
| import { FormBuilder, FormGroup, FormArray, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms'; | |
| import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; | |
| import { MatFormFieldModule } from '@angular/material/form-field'; | |
| import { MatInputModule } from '@angular/material/input'; | |
| import { MatSelectModule } from '@angular/material/select'; | |
| import { MatCheckboxModule } from '@angular/material/checkbox'; | |
| import { MatButtonModule } from '@angular/material/button'; | |
| import { MatIconModule } from '@angular/material/icon'; | |
| import { MatChipsModule } from '@angular/material/chips'; | |
| import { MatTableModule } from '@angular/material/table'; | |
| import { MatTabsModule } from '@angular/material/tabs'; | |
| import { MatExpansionModule } from '@angular/material/expansion'; | |
| import { MatListModule } from '@angular/material/list'; | |
| import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar'; | |
| import { MatDialog } from '@angular/material/dialog'; | |
| // Interfaces for multi-language support | |
| interface LocalizedExample { | |
| locale_code: string; | |
| example: string; | |
| } | |
| interface LocalizedCaption { | |
| locale_code: string; | |
| caption: string; | |
| } | |
| interface ParameterWithLocalizedCaption { | |
| name: string; | |
| caption: LocalizedCaption[]; | |
| type: string; | |
| required: boolean; | |
| variable_name: string; | |
| extraction_prompt?: string; | |
| validation_regex?: string; | |
| invalid_prompt?: string; | |
| type_error_prompt?: string; | |
| } | |
| ({ | |
| selector: 'app-intent-edit-dialog', | |
| standalone: true, | |
| imports: [ | |
| CommonModule, | |
| ReactiveFormsModule, | |
| FormsModule, | |
| MatDialogModule, | |
| MatFormFieldModule, | |
| MatInputModule, | |
| MatSelectModule, | |
| MatCheckboxModule, | |
| MatButtonModule, | |
| MatIconModule, | |
| MatChipsModule, | |
| MatTableModule, | |
| MatTabsModule, | |
| MatExpansionModule, | |
| MatListModule, | |
| MatSnackBarModule | |
| ], | |
| templateUrl: './intent-edit-dialog.component.html', | |
| styleUrls: ['./intent-edit-dialog.component.scss'] | |
| }) | |
| export default class IntentEditDialogComponent implements OnInit { | |
| form!: FormGroup; | |
| availableAPIs: any[] = []; | |
| parameterTypes = ['str', 'int', 'float', 'bool', 'date']; | |
| // Multi-language support | |
| supportedLocales: string[] = []; | |
| selectedExampleLocale: string = ''; | |
| examples: LocalizedExample[] = []; | |
| newExample = ''; | |
| constructor( | |
| private fb: FormBuilder, | |
| private snackBar: MatSnackBar, | |
| private dialog: MatDialog, | |
| public dialogRef: MatDialogRef<IntentEditDialogComponent>, | |
| (MAT_DIALOG_DATA) public data: any | |
| ) { | |
| this.availableAPIs = data.apis || []; | |
| this.supportedLocales = data.project?.supported_locales || data.supportedLocales || ['tr']; | |
| this.selectedExampleLocale = data.project?.default_locale || data.defaultLocale || this.supportedLocales[0] || 'tr'; | |
| } | |
| ngOnInit() { | |
| this.initializeForm(); | |
| if (this.data.intent) { | |
| this.populateForm(this.data.intent); | |
| } | |
| } | |
| initializeForm() { | |
| this.form = this.fb.group({ | |
| name: ['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9-]+$/)]], | |
| caption: ['', Validators.required], | |
| detection_prompt: ['', Validators.required], | |
| parameters: this.fb.array([]), | |
| action: ['', Validators.required], | |
| fallback_timeout_prompt: [''], | |
| fallback_error_prompt: [''] | |
| }); | |
| } | |
| populateForm(intent: any) { | |
| // Populate basic fields | |
| this.form.patchValue({ | |
| name: intent.name || '', | |
| caption: intent.caption || '', | |
| detection_prompt: intent.detection_prompt || '', | |
| action: intent.action || '', | |
| fallback_timeout_prompt: intent.fallback_timeout_prompt || '', | |
| fallback_error_prompt: intent.fallback_error_prompt || '' | |
| }); | |
| // Populate localized examples | |
| if (intent.examples && Array.isArray(intent.examples)) { | |
| if (intent.examples.length > 0 && typeof intent.examples[0] === 'object' && 'locale_code' in intent.examples[0]) { | |
| // New format with LocalizedExample | |
| this.examples = [...intent.examples]; | |
| } else if (typeof intent.examples[0] === 'string') { | |
| // Old format - convert to new format using default locale | |
| this.examples = intent.examples.map((ex: string) => ({ | |
| locale_code: this.selectedExampleLocale, | |
| example: ex | |
| })); | |
| } | |
| } | |
| // Populate parameters with localized captions | |
| if (intent.parameters && Array.isArray(intent.parameters)) { | |
| const paramsArray = this.form.get('parameters') as FormArray; | |
| paramsArray.clear(); | |
| intent.parameters.forEach((param: any) => { | |
| paramsArray.push(this.createParameterFormGroup(param)); | |
| }); | |
| } | |
| } | |
| createParameterFormGroup(param?: any): FormGroup { | |
| // Convert old caption format to new if needed | |
| let captionArray: LocalizedCaption[] = []; | |
| if (param?.caption) { | |
| if (Array.isArray(param.caption)) { | |
| captionArray = param.caption; | |
| } else if (typeof param.caption === 'string') { | |
| // Old format - convert to new | |
| captionArray = [{ | |
| locale_code: this.selectedExampleLocale, | |
| caption: param.caption | |
| }]; | |
| } | |
| } | |
| return this.fb.group({ | |
| name: [param?.name || '', Validators.required], | |
| caption: [captionArray], | |
| type: [param?.type || 'str', Validators.required], | |
| required: [param?.required !== false], | |
| variable_name: [param?.variable_name || '', Validators.required], | |
| extraction_prompt: [param?.extraction_prompt || ''], | |
| validation_regex: [param?.validation_regex || ''], | |
| invalid_prompt: [param?.invalid_prompt || ''], | |
| type_error_prompt: [param?.type_error_prompt || ''] | |
| }); | |
| } | |
| get parameters() { | |
| return this.form.get('parameters') as FormArray; | |
| } | |
| addParameter() { | |
| this.parameters.push(this.createParameterFormGroup()); | |
| } | |
| removeParameter(index: number) { | |
| this.parameters.removeAt(index); | |
| } | |
| // Multi-language example management | |
| getExamplesForCurrentLocale(): LocalizedExample[] { | |
| return this.examples.filter(ex => ex.locale_code === this.selectedExampleLocale); | |
| } | |
| addExample() { | |
| if (this.newExample.trim()) { | |
| const existingIndex = this.examples.findIndex( | |
| ex => ex.locale_code === this.selectedExampleLocale && ex.example === this.newExample.trim() | |
| ); | |
| if (existingIndex === -1) { | |
| this.examples.push({ | |
| locale_code: this.selectedExampleLocale, | |
| example: this.newExample.trim() | |
| }); | |
| this.newExample = ''; | |
| } else { | |
| this.snackBar.open('This example already exists for this locale', 'Close', { duration: 3000 }); | |
| } | |
| } | |
| } | |
| removeExample(example: LocalizedExample) { | |
| const index = this.examples.findIndex( | |
| ex => ex.locale_code === example.locale_code && ex.example === example.example | |
| ); | |
| if (index !== -1) { | |
| this.examples.splice(index, 1); | |
| } | |
| } | |
| // Test regex functionality | |
| testRegex(paramIndex: number) { | |
| const param = this.parameters.at(paramIndex); | |
| const regex = param.get('validation_regex')?.value; | |
| if (!regex) { | |
| this.snackBar.open('No regex pattern to test', 'Close', { duration: 2000 }); | |
| return; | |
| } | |
| // Simple test implementation | |
| const testValue = prompt('Enter a test value:'); | |
| if (testValue !== null) { | |
| try { | |
| const pattern = new RegExp(regex); | |
| const matches = pattern.test(testValue); | |
| this.snackBar.open( | |
| matches ? '✓ Pattern matches!' : '✗ Pattern does not match', | |
| 'Close', | |
| { duration: 3000 } | |
| ); | |
| } catch (e) { | |
| this.snackBar.open('Invalid regex pattern', 'Close', { duration: 3000 }); | |
| } | |
| } | |
| } | |
| // Move parameter up or down | |
| moveParameter(index: number, direction: 'up' | 'down') { | |
| const newIndex = direction === 'up' ? index - 1 : index + 1; | |
| if (newIndex < 0 || newIndex >= this.parameters.length) { | |
| return; | |
| } | |
| const currentItem = this.parameters.at(index); | |
| this.parameters.removeAt(index); | |
| this.parameters.insert(newIndex, currentItem); | |
| } | |
| // Parameter caption management | |
| getCaptionDisplay(captions: LocalizedCaption[]): string { | |
| if (!captions || captions.length === 0) return '(No caption)'; | |
| // Try to find caption for default locale | |
| const defaultCaption = captions.find(c => c.locale_code === (this.data.project?.default_locale || this.data.defaultLocale || 'tr')); | |
| if (defaultCaption) return defaultCaption.caption; | |
| // Return first available caption | |
| return captions[0].caption; | |
| } | |
| async openCaptionDialog(paramIndex: number) { | |
| const param = this.parameters.at(paramIndex); | |
| const currentCaptions = param.get('caption')?.value || []; | |
| // Import and open caption dialog | |
| const { default: CaptionDialogComponent } = await import('../caption-dialog/caption-dialog.component'); | |
| const dialogRef = this.dialog.open(CaptionDialogComponent, { | |
| width: '600px', | |
| data: { | |
| captions: [...currentCaptions], | |
| supportedLocales: this.supportedLocales, | |
| defaultLocale: this.data.project?.default_locale || this.data.defaultLocale | |
| } | |
| }); | |
| dialogRef.afterClosed().subscribe(result => { | |
| if (result) { | |
| param.patchValue({ caption: result }); | |
| } | |
| }); | |
| } | |
| // Locale helpers | |
| getLocaleName(localeCode: string): string { | |
| const localeNames: { [key: string]: string } = { | |
| 'tr': 'Türkçe', | |
| 'en': 'English', | |
| 'de': 'Deutsch', | |
| 'fr': 'Français', | |
| 'es': 'Español', | |
| 'ar': 'العربية', | |
| 'ru': 'Русский', | |
| 'zh': '中文', | |
| 'ja': '日本語', | |
| 'ko': '한국어' | |
| }; | |
| return localeNames[localeCode] || localeCode; | |
| } | |
| onSubmit() { | |
| if (this.form.valid) { | |
| const formValue = this.form.value; | |
| // Add examples to the result | |
| formValue.examples = this.examples; | |
| // Ensure all parameters have captions | |
| formValue.parameters = formValue.parameters.map((param: any) => { | |
| if (!param.caption || param.caption.length === 0) { | |
| // Create default caption if missing | |
| param.caption = [{ | |
| locale_code: this.data.project?.default_locale || this.data.defaultLocale || 'tr', | |
| caption: param.name | |
| }]; | |
| } | |
| return param; | |
| }); | |
| this.dialogRef.close(formValue); | |
| } else { | |
| this.snackBar.open('Please fill all required fields', 'Close', { duration: 3000 }); | |
| } | |
| } | |
| save() { | |
| this.onSubmit(); | |
| } | |
| cancel() { | |
| this.dialogRef.close(); | |
| } | |
| } |