ciyidogan commited on
Commit
128160d
·
verified ·
1 Parent(s): 9fe0a44

Update flare-ui/src/app/components/environment/environment.component.ts

Browse files
flare-ui/src/app/components/environment/environment.component.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Component, OnInit } from '@angular/core';
2
  import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
3
  import { FormsModule } from '@angular/forms';
4
  import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
@@ -18,6 +18,7 @@ import { MatDividerModule } from '@angular/material/divider';
18
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
19
  import { MatTooltipModule } from '@angular/material/tooltip';
20
  import { MatDialogModule } from '@angular/material/dialog';
 
21
 
22
  // Provider interfaces
23
  interface ProviderConfig {
@@ -69,7 +70,7 @@ interface EnvironmentConfig {
69
  templateUrl: './environment.component.html',
70
  styleUrls: ['./environment.component.scss']
71
  })
72
- export class EnvironmentComponent implements OnInit {
73
  form: FormGroup;
74
  loading = false;
75
  saving = false;
@@ -120,6 +121,12 @@ export class EnvironmentComponent implements OnInit {
120
  { value: 'phone_call', name: 'Phone Call (Optimized for telephony)' }
121
  ];
122
 
 
 
 
 
 
 
123
  constructor(
124
  private fb: FormBuilder,
125
  private apiService: ApiService,
@@ -160,6 +167,11 @@ export class EnvironmentComponent implements OnInit {
160
  this.loadEnvironment();
161
  }
162
 
 
 
 
 
 
163
  // Safe getters for template
164
  get currentLLMProviderSafe(): ProviderConfig | null {
165
  return this.currentLLMProvider || null;
@@ -173,28 +185,55 @@ export class EnvironmentComponent implements OnInit {
173
  return this.currentSTTProvider || null;
174
  }
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  loadEnvironment(): void {
177
  this.loading = true;
178
  this.isLoading = true;
179
 
180
- this.apiService.getEnvironment().subscribe({
181
- next: (data: any) => {
182
- // Check if it's new format or legacy
183
- if (data.llm_provider) {
184
- this.handleNewFormat(data);
185
- } else {
186
- this.handleLegacyFormat(data);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  }
188
- this.loading = false;
189
- this.isLoading = false;
190
- },
191
- error: (err) => {
192
- console.error('Failed to load environment:', err);
193
- this.snackBar.open('Failed to load environment configuration', 'Close', { duration: 3000 });
194
- this.loading = false;
195
- this.isLoading = false;
196
- }
197
- });
198
  }
199
 
200
  handleNewFormat(data: EnvironmentConfig): void {
@@ -481,8 +520,11 @@ export class EnvironmentComponent implements OnInit {
481
  }
482
 
483
  saveEnvironment(): void {
484
- if (this.form.invalid) {
485
- this.snackBar.open('Please fix validation errors', 'Close', { duration: 3000 });
 
 
 
486
  return;
487
  }
488
 
@@ -513,17 +555,47 @@ export class EnvironmentComponent implements OnInit {
513
  }
514
  };
515
 
516
- this.apiService.updateEnvironment(saveData as any).subscribe({
517
- next: () => {
518
- this.snackBar.open('Environment configuration saved successfully', 'Close', { duration: 3000 });
519
- this.saving = false;
520
- },
521
- error: (err) => {
522
- console.error('Failed to save environment:', err);
523
- this.snackBar.open('Failed to save environment configuration', 'Close', { duration: 3000 });
524
- this.saving = false;
525
- }
526
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
  }
528
 
529
  // Icon helpers
 
1
+ import { Component, OnInit, OnDestroy } from '@angular/core';
2
  import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
3
  import { FormsModule } from '@angular/forms';
4
  import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
 
18
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
19
  import { MatTooltipModule } from '@angular/material/tooltip';
20
  import { MatDialogModule } from '@angular/material/dialog';
21
+ import { Subject, takeUntil } from 'rxjs';
22
 
23
  // Provider interfaces
24
  interface ProviderConfig {
 
70
  templateUrl: './environment.component.html',
71
  styleUrls: ['./environment.component.scss']
72
  })
73
+ export class EnvironmentComponent implements OnInit, OnDestroy {
74
  form: FormGroup;
75
  loading = false;
76
  saving = false;
 
121
  { value: 'phone_call', name: 'Phone Call (Optimized for telephony)' }
122
  ];
123
 
124
+ // API key visibility tracking
125
+ showApiKeys: { [key: string]: boolean } = {};
126
+
127
+ // Memory leak prevention
128
+ private destroyed$ = new Subject<void>();
129
+
130
  constructor(
131
  private fb: FormBuilder,
132
  private apiService: ApiService,
 
167
  this.loadEnvironment();
168
  }
169
 
170
+ ngOnDestroy() {
171
+ this.destroyed$.next();
172
+ this.destroyed$.complete();
173
+ }
174
+
175
  // Safe getters for template
176
  get currentLLMProviderSafe(): ProviderConfig | null {
177
  return this.currentLLMProvider || null;
 
185
  return this.currentSTTProvider || null;
186
  }
187
 
188
+ // API key masking methods
189
+ maskApiKey(key?: string): string {
190
+ if (!key) return '';
191
+ if (key.length <= 8) return '••••••••';
192
+ return key.substring(0, 4) + '••••' + key.substring(key.length - 4);
193
+ }
194
+
195
+ toggleApiKeyVisibility(fieldName: string): void {
196
+ this.showApiKeys[fieldName] = !this.showApiKeys[fieldName];
197
+ }
198
+
199
+ getApiKeyInputType(fieldName: string): string {
200
+ return this.showApiKeys[fieldName] ? 'text' : 'password';
201
+ }
202
+
203
+ formatApiKeyForDisplay(fieldName: string, value?: string): string {
204
+ if (this.showApiKeys[fieldName]) {
205
+ return value || '';
206
+ }
207
+ return this.maskApiKey(value);
208
+ }
209
+
210
  loadEnvironment(): void {
211
  this.loading = true;
212
  this.isLoading = true;
213
 
214
+ this.apiService.getEnvironment()
215
+ .pipe(takeUntil(this.destroyed$))
216
+ .subscribe({
217
+ next: (data: any) => {
218
+ // Check if it's new format or legacy
219
+ if (data.llm_provider) {
220
+ this.handleNewFormat(data);
221
+ } else {
222
+ this.handleLegacyFormat(data);
223
+ }
224
+ this.loading = false;
225
+ this.isLoading = false;
226
+ },
227
+ error: (err) => {
228
+ console.error('Failed to load environment:', err);
229
+ this.snackBar.open('Failed to load environment configuration', 'Close', {
230
+ duration: 3000,
231
+ panelClass: ['error-snackbar']
232
+ });
233
+ this.loading = false;
234
+ this.isLoading = false;
235
  }
236
+ });
 
 
 
 
 
 
 
 
 
237
  }
238
 
239
  handleNewFormat(data: EnvironmentConfig): void {
 
520
  }
521
 
522
  saveEnvironment(): void {
523
+ if (this.form.invalid || this.saving) {
524
+ this.snackBar.open('Please fix validation errors', 'Close', {
525
+ duration: 3000,
526
+ panelClass: ['error-snackbar']
527
+ });
528
  return;
529
  }
530
 
 
555
  }
556
  };
557
 
558
+ this.apiService.updateEnvironment(saveData as any)
559
+ .pipe(takeUntil(this.destroyed$))
560
+ .subscribe({
561
+ next: () => {
562
+ this.saving = false;
563
+ this.snackBar.open('Environment configuration saved successfully', 'Close', {
564
+ duration: 3000,
565
+ panelClass: ['success-snackbar']
566
+ });
567
+
568
+ // Update environment service
569
+ this.environmentService.updateEnvironment(saveData as any);
570
+
571
+ // Clear form dirty state
572
+ this.form.markAsPristine();
573
+ },
574
+ error: (error) => {
575
+ this.saving = false;
576
+
577
+ // Race condition handling
578
+ if (error.status === 409) {
579
+ const details = error.error?.details || {};
580
+ this.snackBar.open(
581
+ `Settings were modified by ${details.last_update_user || 'another user'}. Please reload.`,
582
+ 'Reload',
583
+ { duration: 0 }
584
+ ).onAction().subscribe(() => {
585
+ this.loadEnvironment();
586
+ });
587
+ } else {
588
+ this.snackBar.open(
589
+ error.error?.detail || 'Failed to save environment configuration',
590
+ 'Close',
591
+ {
592
+ duration: 5000,
593
+ panelClass: ['error-snackbar']
594
+ }
595
+ );
596
+ }
597
+ }
598
+ });
599
  }
600
 
601
  // Icon helpers