ciyidogan commited on
Commit
b590102
·
verified ·
1 Parent(s): fed974c

Update flare-ui/src/app/services/environment.service.ts

Browse files
flare-ui/src/app/services/environment.service.ts CHANGED
@@ -1,25 +1,102 @@
 
 
 
1
  import { Injectable } from '@angular/core';
2
- import { BehaviorSubject, Observable } from 'rxjs';
3
  import { Environment } from './api.service';
4
 
 
 
 
 
 
 
5
  @Injectable({
6
  providedIn: 'root'
7
  })
8
  export class EnvironmentService {
9
  private environmentSubject = new BehaviorSubject<Environment | null>(null);
10
  public environment$ = this.environmentSubject.asObservable();
 
11
  private ttsEnabledSource = new BehaviorSubject<boolean>(false);
12
  private sttEnabledSource = new BehaviorSubject<boolean>(false);
13
 
 
 
 
 
 
 
 
14
  ttsEnabled$ = this.ttsEnabledSource.asObservable();
15
  sttEnabled$ = this.sttEnabledSource.asObservable();
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  setTTSEnabled(enabled: boolean): void {
18
- this.ttsEnabledSource.next(enabled);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
 
21
  setSTTEnabled(enabled: boolean): void {
22
- this.sttEnabledSource.next(enabled);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
 
25
  isTTSEnabled(): boolean {
@@ -30,8 +107,35 @@ export class EnvironmentService {
30
  return this.sttEnabledSource.value;
31
  }
32
 
33
- updateEnvironment(env: Environment) {
34
- this.environmentSubject.next(env);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
 
37
  getEnvironment(): Environment | null {
@@ -39,7 +143,147 @@ export class EnvironmentService {
39
  }
40
 
41
  isGPTMode(): boolean {
 
 
 
 
 
 
 
 
 
 
42
  const env = this.environmentSubject.value;
43
- return env?.work_mode?.startsWith('gpt4o') || false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
  }
 
1
+ // environment.service.ts
2
+ // Path: /flare-ui/src/app/services/environment.service.ts
3
+
4
  import { Injectable } from '@angular/core';
5
+ import { BehaviorSubject, Observable, throwError } from 'rxjs';
6
  import { Environment } from './api.service';
7
 
8
+ export interface EnvironmentError {
9
+ type: 'validation' | 'update' | 'unknown';
10
+ message: string;
11
+ details?: any;
12
+ }
13
+
14
  @Injectable({
15
  providedIn: 'root'
16
  })
17
  export class EnvironmentService {
18
  private environmentSubject = new BehaviorSubject<Environment | null>(null);
19
  public environment$ = this.environmentSubject.asObservable();
20
+
21
  private ttsEnabledSource = new BehaviorSubject<boolean>(false);
22
  private sttEnabledSource = new BehaviorSubject<boolean>(false);
23
 
24
+ private errorSubject = new BehaviorSubject<EnvironmentError | null>(null);
25
+ public error$ = this.errorSubject.asObservable();
26
+
27
+ // Local storage keys
28
+ private readonly TTS_KEY = 'flare_tts_enabled';
29
+ private readonly STT_KEY = 'flare_stt_enabled';
30
+
31
  ttsEnabled$ = this.ttsEnabledSource.asObservable();
32
  sttEnabled$ = this.sttEnabledSource.asObservable();
33
 
34
+ constructor() {
35
+ // Load saved preferences
36
+ this.loadPreferences();
37
+ }
38
+
39
+ private loadPreferences(): void {
40
+ try {
41
+ // Load TTS preference
42
+ const savedTTS = localStorage.getItem(this.TTS_KEY);
43
+ if (savedTTS !== null) {
44
+ this.ttsEnabledSource.next(savedTTS === 'true');
45
+ }
46
+
47
+ // Load STT preference
48
+ const savedSTT = localStorage.getItem(this.STT_KEY);
49
+ if (savedSTT !== null) {
50
+ this.sttEnabledSource.next(savedSTT === 'true');
51
+ }
52
+ } catch (error) {
53
+ console.error('Error loading preferences:', error);
54
+ // Use defaults on error
55
+ this.ttsEnabledSource.next(false);
56
+ this.sttEnabledSource.next(false);
57
+ }
58
+ }
59
+
60
  setTTSEnabled(enabled: boolean): void {
61
+ try {
62
+ if (typeof enabled !== 'boolean') {
63
+ throw new Error('TTS enabled must be a boolean value');
64
+ }
65
+
66
+ this.ttsEnabledSource.next(enabled);
67
+
68
+ // Save preference
69
+ try {
70
+ localStorage.setItem(this.TTS_KEY, enabled.toString());
71
+ } catch (error) {
72
+ console.warn('Failed to save TTS preference:', error);
73
+ }
74
+
75
+ console.log(`TTS ${enabled ? 'enabled' : 'disabled'}`);
76
+ } catch (error) {
77
+ this.handleError('validation', 'Invalid TTS setting', error);
78
+ }
79
  }
80
 
81
  setSTTEnabled(enabled: boolean): void {
82
+ try {
83
+ if (typeof enabled !== 'boolean') {
84
+ throw new Error('STT enabled must be a boolean value');
85
+ }
86
+
87
+ this.sttEnabledSource.next(enabled);
88
+
89
+ // Save preference
90
+ try {
91
+ localStorage.setItem(this.STT_KEY, enabled.toString());
92
+ } catch (error) {
93
+ console.warn('Failed to save STT preference:', error);
94
+ }
95
+
96
+ console.log(`STT ${enabled ? 'enabled' : 'disabled'}`);
97
+ } catch (error) {
98
+ this.handleError('validation', 'Invalid STT setting', error);
99
+ }
100
  }
101
 
102
  isTTSEnabled(): boolean {
 
107
  return this.sttEnabledSource.value;
108
  }
109
 
110
+ updateEnvironment(env: Environment | null): void {
111
+ try {
112
+ if (env) {
113
+ // Validate environment object
114
+ this.validateEnvironment(env);
115
+
116
+ // Check for changes
117
+ const currentEnv = this.environmentSubject.value;
118
+ const hasChanged = !currentEnv ||
119
+ currentEnv.id !== env.id ||
120
+ currentEnv.work_mode !== env.work_mode ||
121
+ currentEnv.last_update_date !== env.last_update_date;
122
+
123
+ if (hasChanged) {
124
+ console.log('Environment updated:', {
125
+ id: env.id,
126
+ name: env.name,
127
+ work_mode: env.work_mode,
128
+ version: env.active_version_id
129
+ });
130
+ }
131
+ }
132
+
133
+ this.environmentSubject.next(env);
134
+ this.errorSubject.next(null); // Clear any previous errors
135
+
136
+ } catch (error: any) {
137
+ this.handleError('update', error.message || 'Failed to update environment', error);
138
+ }
139
  }
140
 
141
  getEnvironment(): Environment | null {
 
143
  }
144
 
145
  isGPTMode(): boolean {
146
+ try {
147
+ const env = this.environmentSubject.value;
148
+ return env?.work_mode?.toLowerCase()?.startsWith('gpt4o') || false;
149
+ } catch (error) {
150
+ console.error('Error checking GPT mode:', error);
151
+ return false;
152
+ }
153
+ }
154
+
155
+ getWorkMode(): string | null {
156
  const env = this.environmentSubject.value;
157
+ return env?.work_mode || null;
158
+ }
159
+
160
+ isEnvironmentActive(): boolean {
161
+ const env = this.environmentSubject.value;
162
+ return env?.enabled === true;
163
+ }
164
+
165
+ hasActiveVersion(): boolean {
166
+ const env = this.environmentSubject.value;
167
+ return !!env?.active_version_id;
168
+ }
169
+
170
+ // Check if environment supports a specific feature
171
+ supportsFeature(feature: 'tts' | 'stt' | 'realtime' | 'streaming'): boolean {
172
+ const env = this.environmentSubject.value;
173
+ if (!env) return false;
174
+
175
+ switch (feature) {
176
+ case 'tts':
177
+ return this.isTTSEnabled() && env.enabled;
178
+ case 'stt':
179
+ return this.isSTTEnabled() && env.enabled;
180
+ case 'realtime':
181
+ return this.isGPTMode() && env.enabled;
182
+ case 'streaming':
183
+ return env.enabled;
184
+ default:
185
+ return false;
186
+ }
187
+ }
188
+
189
+ // Reset all settings
190
+ reset(): void {
191
+ try {
192
+ this.environmentSubject.next(null);
193
+ this.setTTSEnabled(false);
194
+ this.setSTTEnabled(false);
195
+ this.errorSubject.next(null);
196
+
197
+ // Clear saved preferences
198
+ try {
199
+ localStorage.removeItem(this.TTS_KEY);
200
+ localStorage.removeItem(this.STT_KEY);
201
+ } catch (error) {
202
+ console.warn('Failed to clear preferences:', error);
203
+ }
204
+
205
+ console.log('Environment service reset');
206
+ } catch (error) {
207
+ this.handleError('unknown', 'Failed to reset environment', error);
208
+ }
209
+ }
210
+
211
+ // Get configuration summary
212
+ getConfigSummary(): {
213
+ environment: string | null;
214
+ workMode: string | null;
215
+ ttsEnabled: boolean;
216
+ sttEnabled: boolean;
217
+ features: string[];
218
+ } {
219
+ const env = this.environmentSubject.value;
220
+ const features: string[] = [];
221
+
222
+ if (this.supportsFeature('tts')) features.push('TTS');
223
+ if (this.supportsFeature('stt')) features.push('STT');
224
+ if (this.supportsFeature('realtime')) features.push('Realtime');
225
+ if (this.supportsFeature('streaming')) features.push('Streaming');
226
+
227
+ return {
228
+ environment: env?.name || null,
229
+ workMode: env?.work_mode || null,
230
+ ttsEnabled: this.isTTSEnabled(),
231
+ sttEnabled: this.isSTTEnabled(),
232
+ features
233
+ };
234
+ }
235
+
236
+ private validateEnvironment(env: Environment): void {
237
+ if (!env.id) {
238
+ throw new Error('Environment must have an ID');
239
+ }
240
+
241
+ if (!env.name || env.name.trim().length === 0) {
242
+ throw new Error('Environment must have a name');
243
+ }
244
+
245
+ if (!env.project_id) {
246
+ throw new Error('Environment must be associated with a project');
247
+ }
248
+
249
+ if (env.work_mode && !this.isValidWorkMode(env.work_mode)) {
250
+ throw new Error(`Invalid work mode: ${env.work_mode}`);
251
+ }
252
+ }
253
+
254
+ private isValidWorkMode(workMode: string): boolean {
255
+ const validModes = ['stream', 'batch', 'gpt4o', 'gpt4o-mini', 'gpt4o-realtime'];
256
+ return validModes.includes(workMode.toLowerCase());
257
+ }
258
+
259
+ private handleError(type: EnvironmentError['type'], message: string, details?: any): void {
260
+ const error: EnvironmentError = {
261
+ type,
262
+ message,
263
+ details
264
+ };
265
+
266
+ console.error(`Environment error [${type}]:`, message, details);
267
+ this.errorSubject.next(error);
268
+ }
269
+
270
+ // Observable to check if environment is ready
271
+ isReady(): Observable<boolean> {
272
+ return new Observable(subscriber => {
273
+ const sub = this.environment$.subscribe(env => {
274
+ subscriber.next(!!env && env.enabled && !!env.active_version_id);
275
+ });
276
+
277
+ return () => sub.unsubscribe();
278
+ });
279
+ }
280
+
281
+ // Get error state
282
+ hasError(): boolean {
283
+ return this.errorSubject.value !== null;
284
+ }
285
+
286
+ clearError(): void {
287
+ this.errorSubject.next(null);
288
  }
289
  }