mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
[ACA-4454] The create library button should get disabled after being clicked once (#7046)
This commit is contained in:
@@ -87,7 +87,7 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
mat-button
|
mat-button
|
||||||
(click)="submit()"
|
(click)="submit()"
|
||||||
[disabled]="!form.valid"
|
[disabled]="!form.valid || disableCreateButton"
|
||||||
data-automation-id="create-library-id"
|
data-automation-id="create-library-id"
|
||||||
>
|
>
|
||||||
{{ 'LIBRARY.DIALOG.CREATE' | translate }}
|
{{ 'LIBRARY.DIALOG.CREATE' | translate }}
|
||||||
|
@@ -16,16 +16,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { LibraryDialogComponent } from './library.dialog';
|
import { LibraryDialogComponent } from './library.dialog';
|
||||||
import { TestBed, fakeAsync, tick, flush } from '@angular/core/testing';
|
import { TestBed, fakeAsync, tick, flush, ComponentFixture, flushMicrotasks } from '@angular/core/testing';
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
import { AlfrescoApiService, setupTestBed } from '@alfresco/adf-core';
|
import { AlfrescoApiService, setupTestBed, SitesService } from '@alfresco/adf-core';
|
||||||
import { ContentTestingModule } from '../../testing/content.testing.module';
|
import { ContentTestingModule } from '../../testing/content.testing.module';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { of, throwError } from 'rxjs';
|
||||||
|
import { delay } from 'rxjs/operators';
|
||||||
|
|
||||||
describe('LibraryDialogComponent', () => {
|
describe('LibraryDialogComponent', () => {
|
||||||
let fixture;
|
let fixture: ComponentFixture<LibraryDialogComponent>;
|
||||||
let component;
|
let component: LibraryDialogComponent;
|
||||||
|
let sitesService: SitesService;
|
||||||
let alfrescoApi;
|
let alfrescoApi;
|
||||||
let findSitesSpy;
|
let findSitesSpy;
|
||||||
const findSitesResponse = { list: { entries: [] } };
|
const findSitesResponse = { list: { entries: [] } };
|
||||||
@@ -48,6 +51,7 @@ describe('LibraryDialogComponent', () => {
|
|||||||
fixture = TestBed.createComponent(LibraryDialogComponent);
|
fixture = TestBed.createComponent(LibraryDialogComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
alfrescoApi = TestBed.inject(AlfrescoApiService);
|
alfrescoApi = TestBed.inject(AlfrescoApiService);
|
||||||
|
sitesService = TestBed.inject(SitesService);
|
||||||
findSitesSpy = spyOn(alfrescoApi.getInstance().core.queriesApi, 'findSites');
|
findSitesSpy = spyOn(alfrescoApi.getInstance().core.queriesApi, 'findSites');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -57,8 +61,8 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should set library id automatically on title input', fakeAsync(() => {
|
it('should set library id automatically on title input', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -72,8 +76,8 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should translate library title space character to dash for library id', fakeAsync(() => {
|
it('should translate library title space character to dash for library id', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -87,8 +91,8 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should not change custom library id on title input', fakeAsync(() => {
|
it('should not change custom library id on title input', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -107,7 +111,7 @@ describe('LibraryDialogComponent', () => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should invalidate form when library id already exists', fakeAsync(() => {
|
it('should invalidate form when library id already exists', fakeAsync(() => {
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.returnValue(Promise.resolve());
|
spyOn(sitesService, 'getSite').and.returnValue(of(null));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
component.form.controls.id.setValue('existingLibrary');
|
component.form.controls.id.setValue('existingLibrary');
|
||||||
@@ -123,11 +127,11 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should create site when form is valid', fakeAsync(() => {
|
it('should create site when form is valid', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'createSite').and.returnValue(
|
spyOn(sitesService, 'createSite').and.returnValue(
|
||||||
Promise.resolve()
|
of({entry: {id: 'fake-id'}}).pipe(delay(100))
|
||||||
);
|
);
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -138,9 +142,18 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
component.submit();
|
component.submit();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
flush();
|
const confirmButton = fixture.nativeElement.querySelector(`[data-automation-id="create-library-id"]`);
|
||||||
|
expect(component.disableCreateButton).toBe(true);
|
||||||
|
expect(confirmButton.disabled).toBe(true);
|
||||||
|
|
||||||
expect(alfrescoApi.sitesApi.createSite).toHaveBeenCalledWith({
|
tick(500);
|
||||||
|
flushMicrotasks();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(confirmButton.disabled).toBe(false);
|
||||||
|
expect(component.disableCreateButton).toBe(false);
|
||||||
|
|
||||||
|
expect(sitesService.createSite).toHaveBeenCalledWith({
|
||||||
id: 'library-title',
|
id: 'library-title',
|
||||||
title: 'library title',
|
title: 'library title',
|
||||||
description: '',
|
description: '',
|
||||||
@@ -150,10 +163,10 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should not create site when form is invalid', fakeAsync(() => {
|
it('should not create site when form is invalid', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'createSite').and.returnValue(
|
spyOn(sitesService, 'createSite').and.returnValue(
|
||||||
Promise.resolve({})
|
Promise.resolve({})
|
||||||
);
|
);
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.returnValue(Promise.resolve());
|
spyOn(sitesService, 'getSite').and.returnValue(of(null));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
component.form.controls.title.setValue('existingLibrary');
|
component.form.controls.title.setValue('existingLibrary');
|
||||||
@@ -165,11 +178,11 @@ describe('LibraryDialogComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
expect(alfrescoApi.sitesApi.createSite).not.toHaveBeenCalled();
|
expect(sitesService.createSite).not.toHaveBeenCalled();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should notify when library title is already used', fakeAsync(() => {
|
it('should notify when library title is already used', fakeAsync(() => {
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.returnValue(Promise.resolve());
|
spyOn(sitesService, 'getSite').and.returnValue(of(null));
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(
|
findSitesSpy.and.returnValue(Promise.resolve(
|
||||||
{ list: { entries: [{ entry: { title: 'TEST', id: 'library-id' } }] } }
|
{ list: { entries: [{ entry: { title: 'TEST', id: 'library-id' } }] } }
|
||||||
));
|
));
|
||||||
@@ -186,11 +199,11 @@ describe('LibraryDialogComponent', () => {
|
|||||||
it('should notify on 409 conflict error (might be in trash)', fakeAsync(() => {
|
it('should notify on 409 conflict error (might be in trash)', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
const error = { message: '{ "error": { "statusCode": 409 } }' };
|
const error = { message: '{ "error": { "statusCode": 409 } }' };
|
||||||
spyOn(alfrescoApi.sitesApi, 'createSite').and.callFake(() => {
|
spyOn(sitesService, 'createSite').and.callFake(() => {
|
||||||
return Promise.reject(error);
|
return throwError(error);
|
||||||
});
|
});
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -210,8 +223,8 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should not translate library title if value is not a valid id', fakeAsync(() => {
|
it('should not translate library title if value is not a valid id', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -225,8 +238,8 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should translate library title partially for library id', fakeAsync(() => {
|
it('should translate library title partially for library id', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -240,8 +253,8 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should translate library title multiple space character to one dash for library id', fakeAsync(() => {
|
it('should translate library title multiple space character to one dash for library id', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -255,8 +268,8 @@ describe('LibraryDialogComponent', () => {
|
|||||||
|
|
||||||
it('should invalidate library title if is too short', fakeAsync(() => {
|
it('should invalidate library title if is too short', fakeAsync(() => {
|
||||||
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
findSitesSpy.and.returnValue(Promise.resolve(findSitesResponse));
|
||||||
spyOn(alfrescoApi.sitesApi, 'getSite').and.callFake(() => {
|
spyOn(sitesService, 'getSite').and.callFake(() => {
|
||||||
return Promise.reject();
|
return throwError('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Observable, Subject, from } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
OnInit,
|
OnInit,
|
||||||
@@ -33,8 +33,8 @@ import {
|
|||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
import { SiteBodyCreate, SiteEntry, SitePaging } from '@alfresco/js-api';
|
import { SiteBodyCreate, SiteEntry, SitePaging } from '@alfresco/js-api';
|
||||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
import { AlfrescoApiService, SitesService } from '@alfresco/adf-core';
|
||||||
import { debounceTime, mergeMap, takeUntil } from 'rxjs/operators';
|
import { debounceTime, finalize, mergeMap, takeUntil } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-library-dialog',
|
selector: 'adf-library-dialog',
|
||||||
@@ -70,9 +70,11 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
|
|||||||
disabled: false
|
disabled: false
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
disableCreateButton = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private alfrescoApiService: AlfrescoApiService,
|
private alfrescoApiService: AlfrescoApiService,
|
||||||
|
private sitesService: SitesService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private dialog: MatDialogRef<LibraryDialogComponent>
|
private dialog: MatDialogRef<LibraryDialogComponent>
|
||||||
) {}
|
) {}
|
||||||
@@ -152,7 +154,8 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.create().subscribe(
|
this.disableCreateButton = true;
|
||||||
|
this.create().pipe(finalize(() => this.disableCreateButton = false)).subscribe(
|
||||||
(node: SiteEntry) => {
|
(node: SiteEntry) => {
|
||||||
this.success.emit(node);
|
this.success.emit(node);
|
||||||
dialog.close(node);
|
dialog.close(node);
|
||||||
@@ -174,7 +177,7 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
|
|||||||
visibility
|
visibility
|
||||||
};
|
};
|
||||||
|
|
||||||
return from(this.alfrescoApiService.sitesApi.createSite(siteBody));
|
return this.sitesService.createSite(siteBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sanitize(input: string) {
|
private sanitize(input: string) {
|
||||||
@@ -219,7 +222,7 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async findLibraryByTitle(libraryTitle: string): Promise<SitePaging> {
|
private findLibraryByTitle(libraryTitle: string): Promise<SitePaging> {
|
||||||
return this.alfrescoApiService
|
return this.alfrescoApiService
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.core.queriesApi.findSites(libraryTitle, {
|
.core.queriesApi.findSites(libraryTitle, {
|
||||||
@@ -267,9 +270,7 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
return from(
|
return this.sitesService.getSite(control.value).subscribe(
|
||||||
this.alfrescoApiService.sitesApi.getSite(control.value)
|
|
||||||
).subscribe(
|
|
||||||
() => resolve({ message: 'LIBRARY.ERRORS.EXISTENT_SITE' }),
|
() => resolve({ message: 'LIBRARY.ERRORS.EXISTENT_SITE' }),
|
||||||
() => resolve(null)
|
() => resolve(null)
|
||||||
);
|
);
|
||||||
|
@@ -20,7 +20,10 @@ import { from, Observable, throwError } from 'rxjs';
|
|||||||
import { AlfrescoApiService } from './alfresco-api.service';
|
import { AlfrescoApiService } from './alfresco-api.service';
|
||||||
import {
|
import {
|
||||||
MinimalNode,
|
MinimalNode,
|
||||||
SiteEntry, SiteGroupEntry, SiteGroupPaging,
|
SiteBodyCreate,
|
||||||
|
SiteEntry,
|
||||||
|
SiteGroupEntry,
|
||||||
|
SiteGroupPaging,
|
||||||
SiteMemberEntry,
|
SiteMemberEntry,
|
||||||
SiteMemberPaging,
|
SiteMemberPaging,
|
||||||
SiteMembershipBodyCreate,
|
SiteMembershipBodyCreate,
|
||||||
@@ -42,6 +45,18 @@ export class SitesService {
|
|||||||
this.sitesApi = new SitesApi(apiService.getInstance());
|
this.sitesApi = new SitesApi(apiService.getInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a site
|
||||||
|
* @param siteBody SiteBodyCreate to create site
|
||||||
|
* @returns site SiteEntry
|
||||||
|
*/
|
||||||
|
createSite(siteBody: SiteBodyCreate): Observable<SiteEntry> {
|
||||||
|
return from(this.sitesApi.createSite(siteBody))
|
||||||
|
.pipe(
|
||||||
|
catchError((err: any) => this.handleError(err))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a list of all sites in the repository.
|
* Gets a list of all sites in the repository.
|
||||||
* @param opts Options supported by JS-API
|
* @param opts Options supported by JS-API
|
||||||
|
Reference in New Issue
Block a user