Spaces:
Running
Running
Update flare-ui/src/app/components/apis/apis.component.ts
Browse files
flare-ui/src/app/components/apis/apis.component.ts
CHANGED
@@ -556,11 +556,11 @@ export class ApisComponent implements OnInit, OnDestroy {
|
|
556 |
const input = document.createElement('input');
|
557 |
input.type = 'file';
|
558 |
input.accept = '.json';
|
559 |
-
|
560 |
input.onchange = async (event: any) => {
|
561 |
const file = event.target.files[0];
|
562 |
if (!file) return;
|
563 |
-
|
564 |
try {
|
565 |
const text = await file.text();
|
566 |
let apis: any[];
|
@@ -574,7 +574,7 @@ export class ApisComponent implements OnInit, OnDestroy {
|
|
574 |
});
|
575 |
return;
|
576 |
}
|
577 |
-
|
578 |
if (!Array.isArray(apis)) {
|
579 |
this.snackBar.open('Invalid file format. Expected an array of APIs.', 'Close', {
|
580 |
duration: 5000,
|
@@ -582,12 +582,12 @@ export class ApisComponent implements OnInit, OnDestroy {
|
|
582 |
});
|
583 |
return;
|
584 |
}
|
585 |
-
|
586 |
this.loading = true;
|
587 |
let imported = 0;
|
588 |
let failed = 0;
|
589 |
const errors: string[] = [];
|
590 |
-
|
591 |
for (const api of apis) {
|
592 |
try {
|
593 |
await this.apiService.createAPI(api).toPromise();
|
@@ -595,30 +595,57 @@ export class ApisComponent implements OnInit, OnDestroy {
|
|
595 |
} catch (err: any) {
|
596 |
failed++;
|
597 |
const apiName = api.name || 'unnamed';
|
598 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
599 |
errors.push(`${apiName}: ${errorMsg}`);
|
600 |
console.error(`Failed to import API ${apiName}:`, err);
|
601 |
}
|
602 |
}
|
603 |
-
|
604 |
this.loading = false;
|
605 |
|
606 |
if (imported > 0) {
|
607 |
this.loadAPIs();
|
608 |
}
|
609 |
-
|
610 |
-
|
|
|
|
|
|
|
|
|
|
|
611 |
if (failed > 0) {
|
612 |
-
message +=
|
613 |
-
|
614 |
-
|
615 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
616 |
}
|
617 |
-
|
618 |
-
this.snackBar.open(message, 'Close', {
|
619 |
-
duration: failed > 0 ? 8000 : 5000,
|
620 |
-
panelClass: failed > 0 ? 'error-snackbar' : undefined
|
621 |
-
});
|
622 |
} catch (error) {
|
623 |
this.loading = false;
|
624 |
this.snackBar.open('Failed to read file', 'Close', {
|
@@ -627,9 +654,29 @@ export class ApisComponent implements OnInit, OnDestroy {
|
|
627 |
});
|
628 |
}
|
629 |
};
|
630 |
-
|
631 |
input.click();
|
632 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
633 |
|
634 |
exportAPIs() {
|
635 |
const selectedAPIs = this.filteredAPIs.filter(api => !api.deleted);
|
|
|
556 |
const input = document.createElement('input');
|
557 |
input.type = 'file';
|
558 |
input.accept = '.json';
|
559 |
+
|
560 |
input.onchange = async (event: any) => {
|
561 |
const file = event.target.files[0];
|
562 |
if (!file) return;
|
563 |
+
|
564 |
try {
|
565 |
const text = await file.text();
|
566 |
let apis: any[];
|
|
|
574 |
});
|
575 |
return;
|
576 |
}
|
577 |
+
|
578 |
if (!Array.isArray(apis)) {
|
579 |
this.snackBar.open('Invalid file format. Expected an array of APIs.', 'Close', {
|
580 |
duration: 5000,
|
|
|
582 |
});
|
583 |
return;
|
584 |
}
|
585 |
+
|
586 |
this.loading = true;
|
587 |
let imported = 0;
|
588 |
let failed = 0;
|
589 |
const errors: string[] = [];
|
590 |
+
|
591 |
for (const api of apis) {
|
592 |
try {
|
593 |
await this.apiService.createAPI(api).toPromise();
|
|
|
595 |
} catch (err: any) {
|
596 |
failed++;
|
597 |
const apiName = api.name || 'unnamed';
|
598 |
+
|
599 |
+
// Parse error message
|
600 |
+
let errorMsg = 'Unknown error';
|
601 |
+
if (err.status === 409) {
|
602 |
+
errorMsg = `API with name '${apiName}' already exists`;
|
603 |
+
} else if (err.error?.detail) {
|
604 |
+
errorMsg = err.error.detail;
|
605 |
+
} else if (err.message) {
|
606 |
+
errorMsg = err.message;
|
607 |
+
}
|
608 |
+
|
609 |
errors.push(`${apiName}: ${errorMsg}`);
|
610 |
console.error(`Failed to import API ${apiName}:`, err);
|
611 |
}
|
612 |
}
|
613 |
+
|
614 |
this.loading = false;
|
615 |
|
616 |
if (imported > 0) {
|
617 |
this.loadAPIs();
|
618 |
}
|
619 |
+
|
620 |
+
// Build detailed message
|
621 |
+
let message = '';
|
622 |
+
if (imported > 0) {
|
623 |
+
message = `Successfully imported ${imported} API${imported > 1 ? 's' : ''}.`;
|
624 |
+
}
|
625 |
+
|
626 |
if (failed > 0) {
|
627 |
+
if (message) message += '\n\n';
|
628 |
+
message += `Failed to import ${failed} API${failed > 1 ? 's' : ''}:`;
|
629 |
+
|
630 |
+
// Show all errors
|
631 |
+
errors.forEach(error => {
|
632 |
+
message += '\n• ' + error;
|
633 |
+
});
|
634 |
+
}
|
635 |
+
|
636 |
+
// Use dialog for detailed errors
|
637 |
+
if (failed > 0 && errors.length > 3) {
|
638 |
+
// For many errors, show in a dialog instead of snackbar
|
639 |
+
this.showImportErrorsDialog(imported, failed, errors);
|
640 |
+
} else {
|
641 |
+
// For few errors, show in snackbar
|
642 |
+
this.snackBar.open(message, 'Close', {
|
643 |
+
duration: failed > 0 ? 10000 : 5000,
|
644 |
+
panelClass: failed > 0 ? 'error-snackbar' : 'success-snackbar',
|
645 |
+
verticalPosition: 'top',
|
646 |
+
horizontalPosition: 'right'
|
647 |
+
});
|
648 |
}
|
|
|
|
|
|
|
|
|
|
|
649 |
} catch (error) {
|
650 |
this.loading = false;
|
651 |
this.snackBar.open('Failed to read file', 'Close', {
|
|
|
654 |
});
|
655 |
}
|
656 |
};
|
657 |
+
|
658 |
input.click();
|
659 |
}
|
660 |
+
|
661 |
+
// Yeni method ekle
|
662 |
+
private async showImportErrorsDialog(imported: number, failed: number, errors: string[]) {
|
663 |
+
try {
|
664 |
+
const { default: ImportResultsDialogComponent } = await import('../../dialogs/import-results-dialog/import-results-dialog.component');
|
665 |
+
|
666 |
+
this.dialog.open(ImportResultsDialogComponent, {
|
667 |
+
width: '600px',
|
668 |
+
data: {
|
669 |
+
title: 'API Import Results',
|
670 |
+
imported,
|
671 |
+
failed,
|
672 |
+
errors
|
673 |
+
}
|
674 |
+
});
|
675 |
+
} catch (error) {
|
676 |
+
// Fallback to alert if dialog fails to load
|
677 |
+
alert(`Imported: ${imported}\nFailed: ${failed}\n\nErrors:\n${errors.join('\n')}`);
|
678 |
+
}
|
679 |
+
}
|
680 |
|
681 |
exportAPIs() {
|
682 |
const selectedAPIs = this.filteredAPIs.filter(api => !api.deleted);
|