Improve import error messages (#841)

* Display server import errors in modal

* Fix UI text and modal appearance

* Fix loading spinner behaviour

* Fix linting

* Update jslib version
This commit is contained in:
Thomas Rittson 2021-02-24 05:48:30 +10:00 committed by GitHub
parent a975f6df2b
commit 85856d8390
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 9 deletions

2
jslib

@ -1 +1 @@
Subproject commit 0951424de77fbb61a38616d13d6c67f74ee19775
Subproject commit 42348e2fdc6206157d68d8a9f496eaa70520ab01

View File

@ -24,9 +24,9 @@ export class ImportComponent extends BaseImportComponent {
constructor(i18nService: I18nService, analytics: Angulartics2,
toasterService: ToasterService, importService: ImportService,
router: Router, private route: ActivatedRoute,
private platformUtilsService: PlatformUtilsService,
platformUtilsService: PlatformUtilsService,
private userService: UserService) {
super(i18nService, analytics, toasterService, importService, router);
super(i18nService, analytics, toasterService, importService, router, platformUtilsService);
}
async ngOnInit() {

View File

@ -128,7 +128,8 @@ const authService = new AuthService(cryptoService, apiService,
userService, tokenService, appIdService, i18nService, platformUtilsService, messagingService, vaultTimeoutService,
consoleLogService);
const exportService = new ExportService(folderService, cipherService, apiService);
const importService = new ImportService(cipherService, folderService, apiService, i18nService, collectionService);
const importService = new ImportService(cipherService, folderService, apiService, i18nService, collectionService,
platformUtilsService);
const notificationsService = new NotificationsService(userService, syncService, appIdService,
apiService, vaultTimeoutService, async () => messagingService.send('logout', { expired: true }), consoleLogService);
const environmentService = new EnvironmentService(apiService, storageService, notificationsService);

View File

@ -1,7 +1,7 @@
<div class="page-header">
<h1>{{'importData' | i18n}}</h1>
</div>
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
<form #form (ngSubmit)="submit()" ngNativeValidate>
<div class="row">
<div class="col-6">
<div class="form-group">
@ -248,7 +248,7 @@
<label for="fileContents">{{'orCopyPasteFileContents' | i18n}}</label>
<textarea id="fileContents" class="form-control" name="FileContents" [(ngModel)]="fileContents"></textarea>
</div>
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
<button type="submit" class="btn btn-primary btn-submit" [disabled]="loading">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
<span>{{'importData' | i18n}}</span>
</button>

View File

@ -9,6 +9,9 @@ import { Angulartics2 } from 'angulartics2';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { ImportOption, ImportService } from 'jslib/abstractions/import.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import Swal, { SweetAlertIcon } from 'sweetalert2/dist/sweetalert2.js';
@Component({
selector: 'app-import',
@ -20,13 +23,14 @@ export class ImportComponent implements OnInit {
format: string = null;
fileContents: string;
formPromise: Promise<Error>;
loading: boolean = false;
protected organizationId: string = null;
protected successNavigate: any[] = ['vault'];
constructor(protected i18nService: I18nService, protected analytics: Angulartics2,
protected toasterService: ToasterService, protected importService: ImportService,
protected router: Router) { }
protected router: Router, protected platformUtilsService: PlatformUtilsService) { }
ngOnInit() {
this.setImportOptions();
@ -47,10 +51,13 @@ export class ImportComponent implements OnInit {
}
async submit() {
this.loading = true;
const importer = this.importService.getImporter(this.format, this.organizationId);
if (importer === null) {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('selectFormat'));
this.loading = false;
return;
}
@ -59,6 +66,7 @@ export class ImportComponent implements OnInit {
if ((files == null || files.length === 0) && (this.fileContents == null || this.fileContents === '')) {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('selectFile'));
this.loading = false;
return;
}
@ -75,6 +83,7 @@ export class ImportComponent implements OnInit {
if (fileContents == null || fileContents === '') {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('selectFile'));
this.loading = false;
return;
}
@ -83,6 +92,7 @@ export class ImportComponent implements OnInit {
const error = await this.formPromise;
if (error != null) {
this.error(error);
this.loading = false;
return;
}
this.analytics.eventTrack.next({
@ -92,6 +102,8 @@ export class ImportComponent implements OnInit {
this.toasterService.popAsync('success', null, this.i18nService.t('importSuccess'));
this.router.navigate(this.successNavigate);
} catch { }
this.loading = false;
}
getFormatInstructionTitle() {
@ -114,12 +126,30 @@ export class ImportComponent implements OnInit {
this.importOptions = this.importService.regularImportOptions;
}
private error(error: Error) {
private async error(error: Error) {
this.analytics.eventTrack.next({
action: 'Import Data Failed',
properties: { label: this.format },
});
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'), error.message);
await Swal.fire({
heightAuto: false,
buttonsStyling: false,
icon: 'error' as SweetAlertIcon,
iconHtml: `<i class="swal-custom-icon fa fa-bolt text-danger"></i>`,
input: 'textarea',
inputValue: error.message,
inputAttributes: {
'readonly': 'true',
},
title: this.i18nService.t('importError'),
text: this.i18nService.t('importErrorDesc'),
showConfirmButton: true,
confirmButtonText: this.i18nService.t('ok'),
onOpen: popupEl => {
popupEl.querySelector('.swal2-textarea').scrollTo(0, 0);
},
});
}
private getFileContents(file: File): Promise<string> {

View File

@ -1000,6 +1000,12 @@
"importData": {
"message": "Import Data"
},
"importError": {
"message": "Import Error"
},
"importErrorDesc": {
"message": "There was a problem with the data you tried to import. Please resolve the errors listed below in your source file and try again."
},
"importSuccess": {
"message": "Data has been successfully imported into your vault."
},