Spaces:
Building
Building
Update flare-ui/src/app/components/apis/apis.component.ts
Browse files
flare-ui/src/app/components/apis/apis.component.ts
CHANGED
@@ -1,12 +1,13 @@
|
|
1 |
import { Component, inject, OnInit } from '@angular/core';
|
2 |
import { CommonModule } from '@angular/common';
|
3 |
import { FormsModule } from '@angular/forms';
|
|
|
4 |
import { ApiService, API } from '../../services/api.service';
|
5 |
|
6 |
@Component({
|
7 |
selector: 'app-apis',
|
8 |
standalone: true,
|
9 |
-
imports: [CommonModule, FormsModule],
|
10 |
template: `
|
11 |
<div class="apis-container">
|
12 |
<div class="toolbar">
|
@@ -15,10 +16,10 @@ import { ApiService, API } from '../../services/api.service';
|
|
15 |
<button class="btn btn-primary" (click)="createAPI()">
|
16 |
New API
|
17 |
</button>
|
18 |
-
<button class="btn btn-secondary"
|
19 |
Import
|
20 |
</button>
|
21 |
-
<button class="btn btn-secondary"
|
22 |
Export
|
23 |
</button>
|
24 |
<input
|
@@ -218,6 +219,7 @@ import { ApiService, API } from '../../services/api.service';
|
|
218 |
})
|
219 |
export class ApisComponent implements OnInit {
|
220 |
private apiService = inject(ApiService);
|
|
|
221 |
|
222 |
apis: API[] = [];
|
223 |
filteredAPIs: API[] = [];
|
@@ -254,26 +256,30 @@ export class ApisComponent implements OnInit {
|
|
254 |
);
|
255 |
}
|
256 |
|
257 |
-
createAPI() {
|
|
|
|
|
258 |
const dialogRef = this.dialog.open(ApiEditDialogComponent, {
|
259 |
width: '800px',
|
260 |
data: { mode: 'create' }
|
261 |
});
|
262 |
|
263 |
-
dialogRef.afterClosed().subscribe(result => {
|
264 |
if (result) {
|
265 |
this.loadAPIs();
|
266 |
}
|
267 |
});
|
268 |
}
|
269 |
|
270 |
-
editAPI(api: API) {
|
|
|
|
|
271 |
const dialogRef = this.dialog.open(ApiEditDialogComponent, {
|
272 |
width: '800px',
|
273 |
data: { mode: 'edit', api: { ...api } }
|
274 |
});
|
275 |
|
276 |
-
dialogRef.afterClosed().subscribe(result => {
|
277 |
if (result) {
|
278 |
this.loadAPIs();
|
279 |
}
|
@@ -295,13 +301,15 @@ export class ApisComponent implements OnInit {
|
|
295 |
});
|
296 |
}
|
297 |
|
298 |
-
duplicateAPI(api: API) {
|
|
|
|
|
299 |
const dialogRef = this.dialog.open(ApiEditDialogComponent, {
|
300 |
width: '800px',
|
301 |
data: { mode: 'duplicate', api: { ...api } }
|
302 |
});
|
303 |
|
304 |
-
dialogRef.afterClosed().subscribe(result => {
|
305 |
if (result) {
|
306 |
this.loadAPIs();
|
307 |
}
|
@@ -322,6 +330,67 @@ export class ApisComponent implements OnInit {
|
|
322 |
}
|
323 |
}
|
324 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
private showMessage(message: string, isError: boolean) {
|
326 |
this.message = message;
|
327 |
this.isError = isError;
|
|
|
1 |
import { Component, inject, OnInit } from '@angular/core';
|
2 |
import { CommonModule } from '@angular/common';
|
3 |
import { FormsModule } from '@angular/forms';
|
4 |
+
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
|
5 |
import { ApiService, API } from '../../services/api.service';
|
6 |
|
7 |
@Component({
|
8 |
selector: 'app-apis',
|
9 |
standalone: true,
|
10 |
+
imports: [CommonModule, FormsModule, MatDialogModule],
|
11 |
template: `
|
12 |
<div class="apis-container">
|
13 |
<div class="toolbar">
|
|
|
16 |
<button class="btn btn-primary" (click)="createAPI()">
|
17 |
New API
|
18 |
</button>
|
19 |
+
<button class="btn btn-secondary" (click)="importAPIs()">
|
20 |
Import
|
21 |
</button>
|
22 |
+
<button class="btn btn-secondary" (click)="exportAPIs()">
|
23 |
Export
|
24 |
</button>
|
25 |
<input
|
|
|
219 |
})
|
220 |
export class ApisComponent implements OnInit {
|
221 |
private apiService = inject(ApiService);
|
222 |
+
private dialog = inject(MatDialog);
|
223 |
|
224 |
apis: API[] = [];
|
225 |
filteredAPIs: API[] = [];
|
|
|
256 |
);
|
257 |
}
|
258 |
|
259 |
+
async createAPI() {
|
260 |
+
const { default: ApiEditDialogComponent } = await import('../../dialogs/api-edit-dialog/api-edit-dialog.component');
|
261 |
+
|
262 |
const dialogRef = this.dialog.open(ApiEditDialogComponent, {
|
263 |
width: '800px',
|
264 |
data: { mode: 'create' }
|
265 |
});
|
266 |
|
267 |
+
dialogRef.afterClosed().subscribe((result: any) => {
|
268 |
if (result) {
|
269 |
this.loadAPIs();
|
270 |
}
|
271 |
});
|
272 |
}
|
273 |
|
274 |
+
async editAPI(api: API) {
|
275 |
+
const { default: ApiEditDialogComponent } = await import('../../dialogs/api-edit-dialog/api-edit-dialog.component');
|
276 |
+
|
277 |
const dialogRef = this.dialog.open(ApiEditDialogComponent, {
|
278 |
width: '800px',
|
279 |
data: { mode: 'edit', api: { ...api } }
|
280 |
});
|
281 |
|
282 |
+
dialogRef.afterClosed().subscribe((result: any) => {
|
283 |
if (result) {
|
284 |
this.loadAPIs();
|
285 |
}
|
|
|
301 |
});
|
302 |
}
|
303 |
|
304 |
+
async duplicateAPI(api: API) {
|
305 |
+
const { default: ApiEditDialogComponent } = await import('../../dialogs/api-edit-dialog/api-edit-dialog.component');
|
306 |
+
|
307 |
const dialogRef = this.dialog.open(ApiEditDialogComponent, {
|
308 |
width: '800px',
|
309 |
data: { mode: 'duplicate', api: { ...api } }
|
310 |
});
|
311 |
|
312 |
+
dialogRef.afterClosed().subscribe((result: any) => {
|
313 |
if (result) {
|
314 |
this.loadAPIs();
|
315 |
}
|
|
|
330 |
}
|
331 |
}
|
332 |
|
333 |
+
importAPIs() {
|
334 |
+
const input = document.createElement('input');
|
335 |
+
input.type = 'file';
|
336 |
+
input.accept = '.json';
|
337 |
+
|
338 |
+
input.onchange = async (event: any) => {
|
339 |
+
const file = event.target.files[0];
|
340 |
+
if (!file) return;
|
341 |
+
|
342 |
+
try {
|
343 |
+
const text = await file.text();
|
344 |
+
const apis = JSON.parse(text);
|
345 |
+
|
346 |
+
if (!Array.isArray(apis)) {
|
347 |
+
this.showMessage('Invalid file format. Expected an array of APIs.', true);
|
348 |
+
return;
|
349 |
+
}
|
350 |
+
|
351 |
+
let imported = 0;
|
352 |
+
let failed = 0;
|
353 |
+
|
354 |
+
for (const api of apis) {
|
355 |
+
try {
|
356 |
+
await this.apiService.createAPI(api).toPromise();
|
357 |
+
imported++;
|
358 |
+
} catch (err: any) {
|
359 |
+
failed++;
|
360 |
+
console.error(`Failed to import API ${api.name}:`, err);
|
361 |
+
}
|
362 |
+
}
|
363 |
+
|
364 |
+
this.showMessage(`Imported ${imported} APIs. ${failed} failed.`, failed > 0);
|
365 |
+
this.loadAPIs();
|
366 |
+
} catch (error) {
|
367 |
+
this.showMessage('Failed to read file', true);
|
368 |
+
}
|
369 |
+
};
|
370 |
+
|
371 |
+
input.click();
|
372 |
+
}
|
373 |
+
|
374 |
+
exportAPIs() {
|
375 |
+
const selectedAPIs = this.filteredAPIs.filter(api => !api.deleted);
|
376 |
+
|
377 |
+
if (selectedAPIs.length === 0) {
|
378 |
+
this.showMessage('No APIs to export', true);
|
379 |
+
return;
|
380 |
+
}
|
381 |
+
|
382 |
+
const data = JSON.stringify(selectedAPIs, null, 2);
|
383 |
+
const blob = new Blob([data], { type: 'application/json' });
|
384 |
+
const url = window.URL.createObjectURL(blob);
|
385 |
+
const link = document.createElement('a');
|
386 |
+
link.href = url;
|
387 |
+
link.download = `apis_export_${new Date().getTime()}.json`;
|
388 |
+
link.click();
|
389 |
+
window.URL.revokeObjectURL(url);
|
390 |
+
|
391 |
+
this.showMessage(`Exported ${selectedAPIs.length} APIs`, false);
|
392 |
+
}
|
393 |
+
|
394 |
private showMessage(message: string, isError: boolean) {
|
395 |
this.message = message;
|
396 |
this.isError = isError;
|