ciyidogan commited on
Commit
8c6054f
·
verified ·
1 Parent(s): 7c5b9e0

Upload 3 files

Browse files
flare-ui/src/app/dialogs/intent-edit-dialog/intent-edit-dialog.component.html ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h2 mat-dialog-title>
2
+ {{ data.intent ? 'Edit Intent' : 'Create Intent' }}
3
+ </h2>
4
+
5
+ <mat-dialog-content>
6
+ <form [formGroup]="form">
7
+ <mat-tab-group>
8
+ <!-- General Tab -->
9
+ <mat-tab label="General">
10
+ <div class="tab-content">
11
+ <mat-form-field appearance="outline" class="full-width">
12
+ <mat-label>Intent Name*</mat-label>
13
+ <input matInput formControlName="name"
14
+ placeholder="e.g., flight-booking">
15
+ <mat-hint>Use lowercase with hyphens, no spaces</mat-hint>
16
+ <mat-error *ngIf="form.get('name')?.hasError('required')">Name is required</mat-error>
17
+ <mat-error *ngIf="form.get('name')?.hasError('pattern')">Invalid format</mat-error>
18
+ </mat-form-field>
19
+
20
+ <mat-form-field appearance="outline" class="full-width">
21
+ <mat-label>Caption</mat-label>
22
+ <input matInput formControlName="caption"
23
+ placeholder="e.g., Flight Booking Intent">
24
+ </mat-form-field>
25
+
26
+ <mat-form-field appearance="outline">
27
+ <mat-label>Locale</mat-label>
28
+ <mat-select formControlName="locale">
29
+ <mat-option value="tr-TR">Turkish (tr-TR)</mat-option>
30
+ <mat-option value="en-US">English (en-US)</mat-option>
31
+ </mat-select>
32
+ </mat-form-field>
33
+
34
+ <mat-form-field appearance="outline" class="full-width">
35
+ <mat-label>Detection Prompt*</mat-label>
36
+ <textarea matInput formControlName="detection_prompt"
37
+ rows="4"
38
+ placeholder="Describe when this intent should be detected..."></textarea>
39
+ <mat-hint>Explain to the LLM when to detect this intent</mat-hint>
40
+ </mat-form-field>
41
+
42
+ <mat-form-field appearance="outline" class="full-width">
43
+ <mat-label>API Action*</mat-label>
44
+ <mat-select formControlName="action">
45
+ <mat-option *ngFor="let api of availableAPIs" [value]="api.name">
46
+ {{ api.name }} - {{ api.method }} {{ api.url }}
47
+ </mat-option>
48
+ </mat-select>
49
+ <mat-hint>Select the API to call when this intent is triggered</mat-hint>
50
+ </mat-form-field>
51
+
52
+ <mat-divider></mat-divider>
53
+
54
+ <h4>Fallback Messages</h4>
55
+
56
+ <mat-form-field appearance="outline" class="full-width">
57
+ <mat-label>Timeout Message</mat-label>
58
+ <textarea matInput formControlName="fallback_timeout_prompt"
59
+ rows="2"
60
+ placeholder="Message when API times out..."></textarea>
61
+ </mat-form-field>
62
+
63
+ <mat-form-field appearance="outline" class="full-width">
64
+ <mat-label>Error Message</mat-label>
65
+ <textarea matInput formControlName="fallback_error_prompt"
66
+ rows="2"
67
+ placeholder="Message when API returns error..."></textarea>
68
+ </mat-form-field>
69
+ </div>
70
+ </mat-tab>
71
+
72
+ <!-- Examples Tab -->
73
+ <mat-tab label="Examples">
74
+ <div class="tab-content">
75
+ <div class="examples-section">
76
+ <h4>Example Sentences</h4>
77
+ <p>Add example sentences that should trigger this intent</p>
78
+
79
+ <div class="add-example">
80
+ <mat-form-field appearance="outline" class="example-input">
81
+ <mat-label>New Example</mat-label>
82
+ <input matInput [(ngModel)]="newExample"
83
+ [ngModelOptions]="{standalone: true}"
84
+ (keyup.enter)="addExample()"
85
+ placeholder="e.g., I want to book a flight">
86
+ </mat-form-field>
87
+ <button mat-raised-button color="primary" (click)="addExample()">
88
+ <mat-icon>add</mat-icon>
89
+ Add
90
+ </button>
91
+ </div>
92
+
93
+ <mat-list class="examples-list" *ngIf="examples.length > 0">
94
+ <mat-list-item *ngFor="let example of examples.controls; let i = index">
95
+ <mat-icon matListItemIcon>format_quote</mat-icon>
96
+ <div matListItemTitle>{{ example.value }}</div>
97
+ <button mat-icon-button matListItemMeta (click)="removeExample(i)">
98
+ <mat-icon>delete</mat-icon>
99
+ </button>
100
+ </mat-list-item>
101
+ </mat-list>
102
+
103
+ <div class="empty-state" *ngIf="examples.length === 0">
104
+ <p>No examples added yet. Examples help improve intent detection accuracy.</p>
105
+ </div>
106
+ </div>
107
+ </div>
108
+ </mat-tab>
109
+
110
+ <!-- Parameters Tab -->
111
+ <mat-tab label="Parameters">
112
+ <div class="tab-content">
113
+ <div class="parameters-header">
114
+ <h4>Intent Parameters</h4>
115
+ <button mat-raised-button color="primary" (click)="addParameter()">
116
+ <mat-icon>add</mat-icon>
117
+ Add Parameter
118
+ </button>
119
+ </div>
120
+
121
+ <div formArrayName="parameters" class="parameters-list">
122
+ <mat-expansion-panel *ngFor="let param of parameters.controls; let i = index"
123
+ [formGroupName]="i">
124
+ <mat-expansion-panel-header>
125
+ <mat-panel-title>
126
+ {{ param.get('name')?.value || 'New Parameter' }}
127
+ </mat-panel-title>
128
+ <mat-panel-description>
129
+ <mat-chip-listbox>
130
+ <mat-chip-option>{{ param.get('type')?.value }}</mat-chip-option>
131
+ <mat-chip-option *ngIf="param.get('required')?.value" selected>Required</mat-chip-option>
132
+ <mat-chip-option *ngIf="!param.get('required')?.value">Optional</mat-chip-option>
133
+ </mat-chip-listbox>
134
+ </mat-panel-description>
135
+ </mat-expansion-panel-header>
136
+
137
+ <div class="parameter-content">
138
+ <div class="parameter-grid">
139
+ <mat-form-field appearance="outline">
140
+ <mat-label>Parameter Name*</mat-label>
141
+ <input matInput formControlName="name"
142
+ placeholder="e.g., origin_city">
143
+ <mat-hint>Use snake_case</mat-hint>
144
+ </mat-form-field>
145
+
146
+ <mat-form-field appearance="outline">
147
+ <mat-label>Display Name</mat-label>
148
+ <input matInput formControlName="caption"
149
+ placeholder="e.g., Origin City">
150
+ </mat-form-field>
151
+
152
+ <mat-form-field appearance="outline">
153
+ <mat-label>Type*</mat-label>
154
+ <mat-select formControlName="type">
155
+ <mat-option *ngFor="let type of parameterTypes" [value]="type">
156
+ {{ type }}
157
+ </mat-option>
158
+ </mat-select>
159
+ </mat-form-field>
160
+
161
+ <mat-form-field appearance="outline">
162
+ <mat-label>Variable Name*</mat-label>
163
+ <input matInput formControlName="variable_name"
164
+ placeholder="e.g., origin">
165
+ <mat-hint>Session variable name</mat-hint>
166
+ </mat-form-field>
167
+ </div>
168
+
169
+ <mat-checkbox formControlName="required">Required Parameter</mat-checkbox>
170
+
171
+ <mat-form-field appearance="outline" class="full-width">
172
+ <mat-label>Extraction Prompt</mat-label>
173
+ <textarea matInput formControlName="extraction_prompt"
174
+ rows="3"
175
+ placeholder="Instructions for extracting this parameter..."></textarea>
176
+ </mat-form-field>
177
+
178
+ <mat-form-field appearance="outline" class="full-width">
179
+ <mat-label>Validation Regex</mat-label>
180
+ <input matInput formControlName="validation_regex"
181
+ placeholder="e.g., ^[A-Z]{3}$">
182
+ <button mat-icon-button matSuffix (click)="testRegex(i)" type="button">
183
+ <mat-icon>bug_report</mat-icon>
184
+ </button>
185
+ <mat-hint>Optional regex pattern for validation</mat-hint>
186
+ </mat-form-field>
187
+
188
+ <mat-form-field appearance="outline" class="full-width">
189
+ <mat-label>Invalid Value Message</mat-label>
190
+ <input matInput formControlName="invalid_prompt"
191
+ placeholder="Message when value doesn't match regex...">
192
+ </mat-form-field>
193
+
194
+ <mat-form-field appearance="outline" class="full-width">
195
+ <mat-label>Type Error Message</mat-label>
196
+ <input matInput formControlName="type_error_prompt"
197
+ placeholder="Message when value has wrong type...">
198
+ </mat-form-field>
199
+
200
+ <div class="parameter-actions">
201
+ <button mat-button color="warn" (click)="removeParameter(i)">
202
+ <mat-icon>delete</mat-icon>
203
+ Remove
204
+ </button>
205
+ <div class="spacer"></div>
206
+ <button mat-icon-button (click)="moveParameter(i, 'up')"
207
+ [disabled]="i === 0">
208
+ <mat-icon>arrow_upward</mat-icon>
209
+ </button>
210
+ <button mat-icon-button (click)="moveParameter(i, 'down')"
211
+ [disabled]="i === parameters.length - 1">
212
+ <mat-icon>arrow_downward</mat-icon>
213
+ </button>
214
+ </div>
215
+ </div>
216
+ </mat-expansion-panel>
217
+ </div>
218
+
219
+ <div class="empty-state" *ngIf="parameters.length === 0">
220
+ <mat-icon>input</mat-icon>
221
+ <p>No parameters defined. Add parameters that need to be extracted from user input.</p>
222
+ </div>
223
+ </div>
224
+ </mat-tab>
225
+ </mat-tab-group>
226
+ </form>
227
+ </mat-dialog-content>
228
+
229
+ <mat-dialog-actions align="end">
230
+ <button mat-button (click)="cancel()">Cancel</button>
231
+ <button mat-raised-button color="primary"
232
+ (click)="save()"
233
+ [disabled]="form.invalid">
234
+ Save
235
+ </button>
236
+ </mat-dialog-actions>
flare-ui/src/app/dialogs/intent-edit-dialog/intent-edit-dialog.component.scss ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ mat-dialog-content {
2
+ min-width: 700px;
3
+ max-width: 900px;
4
+ max-height: 70vh;
5
+ padding: 0;
6
+ }
7
+
8
+ .tab-content {
9
+ padding: 24px;
10
+ }
11
+
12
+ .full-width {
13
+ width: 100%;
14
+ margin-bottom: 16px;
15
+ }
16
+
17
+ h4 {
18
+ margin: 24px 0 16px 0;
19
+ color: rgba(0, 0, 0, 0.87);
20
+ }
21
+
22
+ mat-divider {
23
+ margin: 24px 0;
24
+ }
25
+
26
+ // Examples Tab
27
+ .examples-section {
28
+ .add-example {
29
+ display: flex;
30
+ gap: 16px;
31
+ align-items: flex-start;
32
+ margin-bottom: 24px;
33
+
34
+ .example-input {
35
+ flex: 1;
36
+ }
37
+ }
38
+
39
+ .examples-list {
40
+ border: 1px solid #e0e0e0;
41
+ border-radius: 4px;
42
+ padding: 0;
43
+
44
+ mat-list-item {
45
+ border-bottom: 1px solid #f5f5f5;
46
+
47
+ &:last-child {
48
+ border-bottom: none;
49
+ }
50
+
51
+ &:hover {
52
+ background-color: #f5f5f5;
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ // Parameters Tab
59
+ .parameters-header {
60
+ display: flex;
61
+ justify-content: space-between;
62
+ align-items: center;
63
+ margin-bottom: 16px;
64
+
65
+ h4 {
66
+ margin: 0;
67
+ }
68
+ }
69
+
70
+ .parameters-list {
71
+ mat-expansion-panel {
72
+ margin-bottom: 8px;
73
+
74
+ mat-chip-listbox {
75
+ margin-left: 16px;
76
+
77
+ mat-chip {
78
+ font-size: 11px;
79
+ min-height: 20px;
80
+ padding: 2px 8px;
81
+ }
82
+ }
83
+ }
84
+
85
+ .parameter-content {
86
+ padding: 16px;
87
+
88
+ .parameter-grid {
89
+ display: grid;
90
+ grid-template-columns: 1fr 1fr;
91
+ gap: 16px;
92
+ margin-bottom: 16px;
93
+ }
94
+
95
+ mat-checkbox {
96
+ margin-bottom: 16px;
97
+ }
98
+
99
+ .parameter-actions {
100
+ display: flex;
101
+ align-items: center;
102
+ margin-top: 16px;
103
+ padding-top: 16px;
104
+ border-top: 1px solid #e0e0e0;
105
+
106
+ .spacer {
107
+ flex: 1;
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ .empty-state {
114
+ text-align: center;
115
+ padding: 40px 20px;
116
+
117
+ mat-icon {
118
+ font-size: 48px;
119
+ width: 48px;
120
+ height: 48px;
121
+ color: #e0e0e0;
122
+ margin-bottom: 16px;
123
+ }
124
+
125
+ p {
126
+ color: #666;
127
+ margin: 0;
128
+ }
129
+ }
130
+
131
+ mat-dialog-actions {
132
+ padding: 16px 24px;
133
+ margin: 0;
134
+ }
flare-ui/src/app/dialogs/intent-edit-dialog/intent-edit-dialog.component.ts ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, Inject, OnInit } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormBuilder, FormGroup, FormArray, Validators, ReactiveFormsModule } from '@angular/forms';
4
+ import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
5
+ import { MatFormFieldModule } from '@angular/material/form-field';
6
+ import { MatInputModule } from '@angular/material/input';
7
+ import { MatSelectModule } from '@angular/material/select';
8
+ import { MatCheckboxModule } from '@angular/material/checkbox';
9
+ import { MatButtonModule } from '@angular/material/button';
10
+ import { MatIconModule } from '@angular/material/icon';
11
+ import { MatChipsModule } from '@angular/material/chips';
12
+ import { MatTableModule } from '@angular/material/table';
13
+ import { MatTabsModule } from '@angular/material/tabs';
14
+ import { MatExpansionModule } from '@angular/material/expansion';
15
+ import { MatListModule } from '@angular/material/list';
16
+ import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
17
+
18
+ @Component({
19
+ selector: 'app-intent-edit-dialog',
20
+ standalone: true,
21
+ imports: [
22
+ CommonModule,
23
+ ReactiveFormsModule,
24
+ MatDialogModule,
25
+ MatFormFieldModule,
26
+ MatInputModule,
27
+ MatSelectModule,
28
+ MatCheckboxModule,
29
+ MatButtonModule,
30
+ MatIconModule,
31
+ MatChipsModule,
32
+ MatTableModule,
33
+ MatTabsModule,
34
+ MatExpansionModule,
35
+ MatListModule,
36
+ MatSnackBarModule
37
+ ],
38
+ templateUrl: './intent-edit-dialog.component.html',
39
+ styleUrls: ['./intent-edit-dialog.component.scss']
40
+ })
41
+ export default class IntentEditDialogComponent implements OnInit {
42
+ form!: FormGroup;
43
+ availableAPIs: any[] = [];
44
+ parameterTypes = ['str', 'int', 'float', 'bool', 'date'];
45
+
46
+ newExample = '';
47
+
48
+ constructor(
49
+ private fb: FormBuilder,
50
+ private snackBar: MatSnackBar,
51
+ public dialogRef: MatDialogRef<IntentEditDialogComponent>,
52
+ @Inject(MAT_DIALOG_DATA) public data: any
53
+ ) {
54
+ this.availableAPIs = data.apis || [];
55
+ }
56
+
57
+ ngOnInit() {
58
+ this.initializeForm();
59
+ if (this.data.intent) {
60
+ this.populateForm(this.data.intent);
61
+ }
62
+ }
63
+
64
+ initializeForm() {
65
+ this.form = this.fb.group({
66
+ name: ['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9-]+$/)]],
67
+ caption: [''],
68
+ locale: ['tr-TR'],
69
+ detection_prompt: ['', Validators.required],
70
+ examples: this.fb.array([]),
71
+ parameters: this.fb.array([]),
72
+ action: ['', Validators.required],
73
+ fallback_timeout_prompt: [''],
74
+ fallback_error_prompt: ['']
75
+ });
76
+ }
77
+
78
+ populateForm(intent: any) {
79
+ this.form.patchValue({
80
+ name: intent.name,
81
+ caption: intent.caption,
82
+ locale: intent.locale,
83
+ detection_prompt: intent.detection_prompt,
84
+ action: intent.action,
85
+ fallback_timeout_prompt: intent.fallback_timeout_prompt,
86
+ fallback_error_prompt: intent.fallback_error_prompt
87
+ });
88
+
89
+ // Populate examples
90
+ if (intent.examples) {
91
+ const examplesArray = this.form.get('examples') as FormArray;
92
+ intent.examples.forEach((example: string) => {
93
+ examplesArray.push(this.fb.control(example));
94
+ });
95
+ }
96
+
97
+ // Populate parameters
98
+ if (intent.parameters) {
99
+ const parametersArray = this.form.get('parameters') as FormArray;
100
+ intent.parameters.forEach((param: any) => {
101
+ parametersArray.push(this.createParameterFormGroup(param));
102
+ });
103
+ }
104
+ }
105
+
106
+ createParameterFormGroup(param: any = {}): FormGroup {
107
+ return this.fb.group({
108
+ name: [param.name || '', [Validators.required, Validators.pattern(/^[a-zA-Z0-9_]+$/)]],
109
+ caption: [param.caption || ''],
110
+ type: [param.type || 'str', Validators.required],
111
+ required: [param.required !== false],
112
+ variable_name: [param.variable_name || '', Validators.required],
113
+ extraction_prompt: [param.extraction_prompt || ''],
114
+ validation_regex: [param.validation_regex || ''],
115
+ invalid_prompt: [param.invalid_prompt || ''],
116
+ type_error_prompt: [param.type_error_prompt || '']
117
+ });
118
+ }
119
+
120
+ get examples() {
121
+ return this.form.get('examples') as FormArray;
122
+ }
123
+
124
+ get parameters() {
125
+ return this.form.get('parameters') as FormArray;
126
+ }
127
+
128
+ addExample() {
129
+ if (this.newExample.trim()) {
130
+ this.examples.push(this.fb.control(this.newExample.trim()));
131
+ this.newExample = '';
132
+ }
133
+ }
134
+
135
+ removeExample(index: number) {
136
+ this.examples.removeAt(index);
137
+ }
138
+
139
+ addParameter() {
140
+ this.parameters.push(this.createParameterFormGroup());
141
+ }
142
+
143
+ removeParameter(index: number) {
144
+ this.parameters.removeAt(index);
145
+ }
146
+
147
+ moveParameter(index: number, direction: 'up' | 'down') {
148
+ const newIndex = direction === 'up' ? index - 1 : index + 1;
149
+ if (newIndex >= 0 && newIndex < this.parameters.length) {
150
+ const param = this.parameters.at(index);
151
+ this.parameters.removeAt(index);
152
+ this.parameters.insert(newIndex, param);
153
+ }
154
+ }
155
+
156
+ async testRegex(index: number) {
157
+ const param = this.parameters.at(index);
158
+ const regex = param.get('validation_regex')?.value;
159
+
160
+ if (!regex) {
161
+ this.snackBar.open('No regex pattern to test', 'Close', { duration: 2000 });
162
+ return;
163
+ }
164
+
165
+ const testValue = prompt('Enter a test value:');
166
+ if (testValue !== null) {
167
+ try {
168
+ const pattern = new RegExp(regex);
169
+ const matches = pattern.test(testValue);
170
+
171
+ this.snackBar.open(
172
+ matches ? '✓ Pattern matches!' : '✗ Pattern does not match',
173
+ 'Close',
174
+ { duration: 3000 }
175
+ );
176
+ } catch (error) {
177
+ this.snackBar.open('Invalid regex pattern', 'Close', {
178
+ duration: 3000,
179
+ panelClass: 'error-snackbar'
180
+ });
181
+ }
182
+ }
183
+ }
184
+
185
+ save() {
186
+ if (this.form.invalid) {
187
+ this.snackBar.open('Please fix all validation errors', 'Close', { duration: 3000 });
188
+ return;
189
+ }
190
+
191
+ const formValue = this.form.value;
192
+ this.dialogRef.close(formValue);
193
+ }
194
+
195
+ cancel() {
196
+ this.dialogRef.close(null);
197
+ }
198
+ }