Spaces:
Building
Building
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>, | |
public data: any (MAT_DIALOG_DATA) | |
) { | |
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(); | |
} | |
} |