mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-13 13:03:04 +00:00
117287: Removed method calls returning observables from the Group form
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<div class="group-form row">
|
<div class="group-form row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
|
||||||
<div *ngIf="groupDataService.getActiveGroup() | async; then editheader; else createHeader"></div>
|
<div *ngIf="activeGroup$ | async; then editheader; else createHeader"></div>
|
||||||
|
|
||||||
<ng-template #createHeader>
|
<ng-template #createHeader>
|
||||||
<h2 class="border-bottom pb-2">{{messagePrefix + '.head.create' | translate}}</h2>
|
<h2 class="border-bottom pb-2">{{messagePrefix + '.head.create' | translate}}</h2>
|
||||||
@@ -23,11 +23,15 @@
|
|||||||
</h2>
|
</h2>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ds-alert *ngIf="groupBeingEdited?.permanent" [type]="AlertTypeEnum.Warning"
|
<ng-container *ngIf="(activeGroup$ | async) as groupBeingEdited">
|
||||||
|
<ds-alert *ngIf="groupBeingEdited?.permanent" [type]="AlertType.Warning"
|
||||||
[content]="messagePrefix + '.alert.permanent'"></ds-alert>
|
[content]="messagePrefix + '.alert.permanent'"></ds-alert>
|
||||||
<ds-alert *ngIf="!(canEdit$ | async) && (groupDataService.getActiveGroup() | async)" [type]="AlertTypeEnum.Warning"
|
<ng-container *ngIf="(activeGroupLinkedDSO$ | async) as activeGroupLinkedDSO">
|
||||||
[content]="(messagePrefix + '.alert.workflowGroup' | translate:{ name: dsoNameService.getName((getLinkedDSO(groupBeingEdited) | async)?.payload), comcol: (getLinkedDSO(groupBeingEdited) | async)?.payload?.type, comcolEditRolesRoute: (getLinkedEditRolesRoute(groupBeingEdited) | async) })">
|
<ds-alert *ngIf="!(canEdit$ | async)" [type]="AlertType.Warning"
|
||||||
|
[content]="(messagePrefix + '.alert.workflowGroup' | translate:{ name: dsoNameService.getName(activeGroupLinkedDSO), comcol: activeGroupLinkedDSO.type, comcolEditRolesRoute: (linkedEditRolesRoute$ | async) })">
|
||||||
</ds-alert>
|
</ds-alert>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ds-form [formId]="formId"
|
<ds-form [formId]="formId"
|
||||||
[formModel]="formModel"
|
[formModel]="formModel"
|
||||||
@@ -39,7 +43,7 @@
|
|||||||
<button (click)="onCancel()"
|
<button (click)="onCancel()"
|
||||||
class="btn btn-outline-secondary"><i class="fas fa-arrow-left"></i> {{messagePrefix + '.return' | translate}}</button>
|
class="btn btn-outline-secondary"><i class="fas fa-arrow-left"></i> {{messagePrefix + '.return' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div after *ngIf="groupBeingEdited != null" class="btn-group">
|
<div after *ngIf="(activeGroup$ | async) as groupBeingEdited" class="btn-group">
|
||||||
<button class="btn btn-danger delete-button" [disabled]="!(canEdit$ | async) || groupBeingEdited.permanent"
|
<button class="btn btn-danger delete-button" [disabled]="!(canEdit$ | async) || groupBeingEdited.permanent"
|
||||||
(click)="delete()">
|
(click)="delete()">
|
||||||
<i class="fa fa-trash"></i> {{ messagePrefix + '.actions.delete' | translate}}
|
<i class="fa fa-trash"></i> {{ messagePrefix + '.actions.delete' | translate}}
|
||||||
@@ -47,15 +51,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</ds-form>
|
</ds-form>
|
||||||
|
|
||||||
|
<ng-container *ngIf="(activeGroup$ | async) as groupBeingEdited">
|
||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<ds-members-list *ngIf="groupBeingEdited != null"
|
<ds-members-list *ngIf="groupBeingEdited != null"
|
||||||
[messagePrefix]="messagePrefix + '.members-list'"></ds-members-list>
|
[messagePrefix]="messagePrefix + '.members-list'"></ds-members-list>
|
||||||
</div>
|
</div>
|
||||||
<ds-subgroups-list *ngIf="groupBeingEdited != null"
|
<ds-subgroups-list *ngIf="groupBeingEdited != null"
|
||||||
[messagePrefix]="messagePrefix + '.subgroups-list'"></ds-subgroups-list>
|
[messagePrefix]="messagePrefix + '.subgroups-list'"></ds-subgroups-list>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
import { UntypedFormControl, UntypedFormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { UntypedFormControl, UntypedFormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { BrowserModule, By } from '@angular/platform-browser';
|
import { BrowserModule, By } from '@angular/platform-browser';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { Observable, of as observableOf } from 'rxjs';
|
import { Observable, of as observableOf } from 'rxjs';
|
||||||
import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../../../core/cache/builders/remote-data-build.service';
|
||||||
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
|
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
|
||||||
@@ -29,8 +29,6 @@ import { GroupMock, GroupMock2 } from '../../../shared/testing/group-mock';
|
|||||||
import { GroupFormComponent } from './group-form.component';
|
import { GroupFormComponent } from './group-form.component';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
|
import { getMockFormBuilderService } from '../../../shared/mocks/form-builder-service.mock';
|
||||||
import { getMockTranslateService } from '../../../shared/mocks/translate.service.mock';
|
|
||||||
import { TranslateLoaderMock } from '../../../shared/testing/translate-loader.mock';
|
|
||||||
import { RouterMock } from '../../../shared/mocks/router.mock';
|
import { RouterMock } from '../../../shared/mocks/router.mock';
|
||||||
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
@@ -38,23 +36,24 @@ import { ValidateGroupExists } from './validators/group-exists.validator';
|
|||||||
import { NoContent } from '../../../core/shared/NoContent.model';
|
import { NoContent } from '../../../core/shared/NoContent.model';
|
||||||
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
|
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
|
||||||
import { DSONameServiceMock } from '../../../shared/mocks/dso-name.service.mock';
|
import { DSONameServiceMock } from '../../../shared/mocks/dso-name.service.mock';
|
||||||
|
import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub';
|
||||||
|
|
||||||
describe('GroupFormComponent', () => {
|
describe('GroupFormComponent', () => {
|
||||||
let component: GroupFormComponent;
|
let component: GroupFormComponent;
|
||||||
let fixture: ComponentFixture<GroupFormComponent>;
|
let fixture: ComponentFixture<GroupFormComponent>;
|
||||||
let translateService: TranslateService;
|
|
||||||
let builderService: FormBuilderService;
|
let builderService: FormBuilderService;
|
||||||
let ePersonDataServiceStub: any;
|
let ePersonDataServiceStub: any;
|
||||||
let groupsDataServiceStub: any;
|
let groupsDataServiceStub: any;
|
||||||
let dsoDataServiceStub: any;
|
let dsoDataServiceStub: any;
|
||||||
let authorizationService: AuthorizationDataService;
|
let authorizationService: AuthorizationDataService;
|
||||||
let notificationService: NotificationsServiceStub;
|
let notificationService: NotificationsServiceStub;
|
||||||
let router;
|
let router: RouterMock;
|
||||||
|
let route: ActivatedRouteStub;
|
||||||
|
|
||||||
let groups;
|
let groups: Group[];
|
||||||
let groupName;
|
let groupName: string;
|
||||||
let groupDescription;
|
let groupDescription: string;
|
||||||
let expected;
|
let expected: Group;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
groups = [GroupMock, GroupMock2];
|
groups = [GroupMock, GroupMock2];
|
||||||
@@ -69,6 +68,15 @@ describe('GroupFormComponent', () => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
object: createSuccessfulRemoteDataObject$(undefined),
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'group-selflink',
|
||||||
|
},
|
||||||
|
object: {
|
||||||
|
href: 'group-objectlink',
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
ePersonDataServiceStub = {};
|
ePersonDataServiceStub = {};
|
||||||
groupsDataServiceStub = {
|
groupsDataServiceStub = {
|
||||||
@@ -105,7 +113,14 @@ describe('GroupFormComponent', () => {
|
|||||||
create(group: Group): Observable<RemoteData<Group>> {
|
create(group: Group): Observable<RemoteData<Group>> {
|
||||||
this.allGroups = [...this.allGroups, group];
|
this.allGroups = [...this.allGroups, group];
|
||||||
this.createdGroup = Object.assign({}, group, {
|
this.createdGroup = Object.assign({}, group, {
|
||||||
_links: { self: { href: 'group-selflink' } }
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'group-selflink',
|
||||||
|
},
|
||||||
|
object: {
|
||||||
|
href: 'group-objectlink',
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
return createSuccessfulRemoteDataObject$(this.createdGroup);
|
return createSuccessfulRemoteDataObject$(this.createdGroup);
|
||||||
},
|
},
|
||||||
@@ -187,17 +202,13 @@ describe('GroupFormComponent', () => {
|
|||||||
return typeof value === 'object' && value !== null;
|
return typeof value === 'object' && value !== null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
translateService = getMockTranslateService();
|
|
||||||
router = new RouterMock();
|
router = new RouterMock();
|
||||||
|
route = new ActivatedRouteStub();
|
||||||
notificationService = new NotificationsServiceStub();
|
notificationService = new NotificationsServiceStub();
|
||||||
|
|
||||||
return TestBed.configureTestingModule({
|
return TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot(),
|
||||||
loader: {
|
|
||||||
provide: TranslateLoader,
|
|
||||||
useClass: TranslateLoaderMock
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
declarations: [GroupFormComponent],
|
declarations: [GroupFormComponent],
|
||||||
providers: [
|
providers: [
|
||||||
@@ -214,14 +225,11 @@ describe('GroupFormComponent', () => {
|
|||||||
{ provide: Store, useValue: {} },
|
{ provide: Store, useValue: {} },
|
||||||
{ provide: RemoteDataBuildService, useValue: {} },
|
{ provide: RemoteDataBuildService, useValue: {} },
|
||||||
{ provide: HALEndpointService, useValue: {} },
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
{
|
{ provide: ActivatedRoute, useValue: route },
|
||||||
provide: ActivatedRoute,
|
|
||||||
useValue: { data: observableOf({ dso: { payload: {} } }), params: observableOf({}) }
|
|
||||||
},
|
|
||||||
{ provide: Router, useValue: router },
|
{ provide: Router, useValue: router },
|
||||||
{ provide: AuthorizationDataService, useValue: authorizationService },
|
{ provide: AuthorizationDataService, useValue: authorizationService },
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -234,8 +242,8 @@ describe('GroupFormComponent', () => {
|
|||||||
describe('when submitting the form', () => {
|
describe('when submitting the form', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyOn(component.submitForm, 'emit');
|
spyOn(component.submitForm, 'emit');
|
||||||
component.groupName.value = groupName;
|
component.groupName.setValue(groupName);
|
||||||
component.groupDescription.value = groupDescription;
|
component.groupDescription.setValue(groupDescription);
|
||||||
});
|
});
|
||||||
describe('without active Group', () => {
|
describe('without active Group', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -243,14 +251,22 @@ describe('GroupFormComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit a new group using the correct values', (async () => {
|
it('should emit a new group using the correct values', (() => {
|
||||||
await fixture.whenStable().then(() => {
|
expect(component.submitForm.emit).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||||
expect(component.submitForm.emit).toHaveBeenCalledWith(expected);
|
name: groupName,
|
||||||
});
|
metadata: {
|
||||||
|
'dc.description': [
|
||||||
|
{
|
||||||
|
value: groupDescription,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}));
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('with active Group', () => {
|
describe('with active Group', () => {
|
||||||
let expected2;
|
let expected2: Group;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
expected2 = Object.assign(new Group(), {
|
expected2 = Object.assign(new Group(), {
|
||||||
name: 'newGroupName',
|
name: 'newGroupName',
|
||||||
@@ -261,15 +277,24 @@ describe('GroupFormComponent', () => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
object: createSuccessfulRemoteDataObject$(undefined),
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'group-selflink',
|
||||||
|
},
|
||||||
|
object: {
|
||||||
|
href: 'group-objectlink',
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
spyOn(groupsDataServiceStub, 'getActiveGroup').and.returnValue(observableOf(expected));
|
spyOn(groupsDataServiceStub, 'getActiveGroup').and.returnValue(observableOf(expected));
|
||||||
spyOn(groupsDataServiceStub, 'patch').and.returnValue(createSuccessfulRemoteDataObject$(expected2));
|
spyOn(groupsDataServiceStub, 'patch').and.returnValue(createSuccessfulRemoteDataObject$(expected2));
|
||||||
component.groupName.value = 'newGroupName';
|
component.ngOnInit();
|
||||||
component.onSubmit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should edit with name and description operations', () => {
|
it('should edit with name and description operations', () => {
|
||||||
|
component.groupName.setValue('newGroupName');
|
||||||
|
component.onSubmit();
|
||||||
const operations = [{
|
const operations = [{
|
||||||
op: 'add',
|
op: 'add',
|
||||||
path: '/metadata/dc.description',
|
path: '/metadata/dc.description',
|
||||||
@@ -283,9 +308,8 @@ describe('GroupFormComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should edit with description operations', () => {
|
it('should edit with description operations', () => {
|
||||||
component.groupName.value = null;
|
component.groupName.setValue(null);
|
||||||
component.onSubmit();
|
component.onSubmit();
|
||||||
fixture.detectChanges();
|
|
||||||
const operations = [{
|
const operations = [{
|
||||||
op: 'add',
|
op: 'add',
|
||||||
path: '/metadata/dc.description',
|
path: '/metadata/dc.description',
|
||||||
@@ -295,9 +319,9 @@ describe('GroupFormComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should edit with name operations', () => {
|
it('should edit with name operations', () => {
|
||||||
component.groupDescription.value = null;
|
component.groupName.setValue('newGroupName');
|
||||||
|
component.groupDescription.setValue(null);
|
||||||
component.onSubmit();
|
component.onSubmit();
|
||||||
fixture.detectChanges();
|
|
||||||
const operations = [{
|
const operations = [{
|
||||||
op: 'replace',
|
op: 'replace',
|
||||||
path: '/name',
|
path: '/name',
|
||||||
@@ -306,12 +330,13 @@ describe('GroupFormComponent', () => {
|
|||||||
expect(groupsDataServiceStub.patch).toHaveBeenCalledWith(expected, operations);
|
expect(groupsDataServiceStub.patch).toHaveBeenCalledWith(expected, operations);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit the existing group using the correct new values', (async () => {
|
it('should emit the existing group using the correct new values', () => {
|
||||||
await fixture.whenStable().then(() => {
|
component.onSubmit();
|
||||||
expect(component.submitForm.emit).toHaveBeenCalledWith(expected2);
|
expect(component.submitForm.emit).toHaveBeenCalledWith(expected2);
|
||||||
});
|
});
|
||||||
}));
|
|
||||||
it('should emit success notification', () => {
|
it('should emit success notification', () => {
|
||||||
|
component.onSubmit();
|
||||||
expect(notificationService.success).toHaveBeenCalled();
|
expect(notificationService.success).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -326,11 +351,8 @@ describe('GroupFormComponent', () => {
|
|||||||
|
|
||||||
|
|
||||||
describe('check form validation', () => {
|
describe('check form validation', () => {
|
||||||
let groupCommunity;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
groupName = 'testName';
|
groupName = 'testName';
|
||||||
groupCommunity = 'testgroupCommunity';
|
|
||||||
groupDescription = 'testgroupDescription';
|
groupDescription = 'testgroupDescription';
|
||||||
|
|
||||||
expected = Object.assign(new Group(), {
|
expected = Object.assign(new Group(), {
|
||||||
@@ -342,8 +364,17 @@ describe('GroupFormComponent', () => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href: 'group-selflink',
|
||||||
|
},
|
||||||
|
object: {
|
||||||
|
href: 'group-objectlink',
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
spyOn(component.submitForm, 'emit');
|
spyOn(component.submitForm, 'emit');
|
||||||
|
spyOn(dsoDataServiceStub, 'findByHref').and.returnValue(observableOf(expected));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
component.initialisePage();
|
component.initialisePage();
|
||||||
@@ -393,21 +424,20 @@ describe('GroupFormComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('delete', () => {
|
describe('delete', () => {
|
||||||
let deleteButton;
|
let deleteButton: HTMLButtonElement;
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
component.initialisePage();
|
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
spyOn(groupsDataServiceStub, 'delete').and.callThrough();
|
||||||
|
component.activeGroup$ = observableOf({
|
||||||
|
id: 'active-group',
|
||||||
|
permanent: false,
|
||||||
|
} as Group);
|
||||||
component.canEdit$ = observableOf(true);
|
component.canEdit$ = observableOf(true);
|
||||||
component.groupBeingEdited = {
|
|
||||||
permanent: false
|
component.initialisePage();
|
||||||
} as Group;
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
deleteButton = fixture.debugElement.query(By.css('.delete-button')).nativeElement;
|
deleteButton = fixture.debugElement.query(By.css('.delete-button')).nativeElement;
|
||||||
|
|
||||||
spyOn(groupsDataServiceStub, 'delete').and.callThrough();
|
|
||||||
spyOn(groupsDataServiceStub, 'getActiveGroup').and.returnValue(observableOf({ id: 'active-group' }));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('if confirmed via modal', () => {
|
describe('if confirmed via modal', () => {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { Component, EventEmitter, HostListener, OnDestroy, OnInit, Output, ChangeDetectorRef } from '@angular/core';
|
import { Component, EventEmitter, HostListener, OnDestroy, OnInit, Output, ChangeDetectorRef } from '@angular/core';
|
||||||
import { UntypedFormGroup } from '@angular/forms';
|
import { UntypedFormGroup, AbstractControl } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import {
|
import {
|
||||||
@@ -10,13 +10,10 @@ import {
|
|||||||
} from '@ng-dynamic-forms/core';
|
} from '@ng-dynamic-forms/core';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import {
|
import {
|
||||||
ObservedValueOf,
|
|
||||||
combineLatest as observableCombineLatest,
|
|
||||||
Observable,
|
Observable,
|
||||||
of as observableOf,
|
Subscription, combineLatest,
|
||||||
Subscription,
|
|
||||||
} from 'rxjs';
|
} from 'rxjs';
|
||||||
import { catchError, map, switchMap, take, filter, debounceTime } from 'rxjs/operators';
|
import { map, switchMap, take, debounceTime, startWith, filter } from 'rxjs/operators';
|
||||||
import { getCollectionEditRolesRoute } from '../../../collection-page/collection-page-routing-paths';
|
import { getCollectionEditRolesRoute } from '../../../collection-page/collection-page-routing-paths';
|
||||||
import { getCommunityEditRolesRoute } from '../../../community-page/community-page-routing-paths';
|
import { getCommunityEditRolesRoute } from '../../../community-page/community-page-routing-paths';
|
||||||
import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service';
|
import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service';
|
||||||
@@ -25,21 +22,20 @@ import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
|
|||||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
import { RequestService } from '../../../core/data/request.service';
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
|
|
||||||
import { GroupDataService } from '../../../core/eperson/group-data.service';
|
import { GroupDataService } from '../../../core/eperson/group-data.service';
|
||||||
import { Group } from '../../../core/eperson/models/group.model';
|
import { Group } from '../../../core/eperson/models/group.model';
|
||||||
import { Collection } from '../../../core/shared/collection.model';
|
import { Collection } from '../../../core/shared/collection.model';
|
||||||
import { Community } from '../../../core/shared/community.model';
|
import { Community } from '../../../core/shared/community.model';
|
||||||
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||||
import {
|
import {
|
||||||
|
getAllCompletedRemoteData,
|
||||||
getRemoteDataPayload,
|
getRemoteDataPayload,
|
||||||
getFirstSucceededRemoteData,
|
getFirstSucceededRemoteData,
|
||||||
getFirstCompletedRemoteData,
|
getFirstCompletedRemoteData,
|
||||||
getFirstSucceededRemoteDataPayload
|
|
||||||
} from '../../../core/shared/operators';
|
} from '../../../core/shared/operators';
|
||||||
import { AlertType } from '../../../shared/alert/aletr-type';
|
import { AlertType } from '../../../shared/alert/aletr-type';
|
||||||
import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component';
|
import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component';
|
||||||
import { hasValue, isNotEmpty, hasValueOperator } from '../../../shared/empty.util';
|
import { hasValue, isNotEmpty, hasValueOperator, hasNoValue } from '../../../shared/empty.util';
|
||||||
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
|
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
|
||||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||||
import { followLink } from '../../../shared/utils/follow-link-config.model';
|
import { followLink } from '../../../shared/utils/follow-link-config.model';
|
||||||
@@ -68,9 +64,9 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* Dynamic models for the inputs of form
|
* Dynamic models for the inputs of form
|
||||||
*/
|
*/
|
||||||
groupName: DynamicInputModel;
|
groupName: AbstractControl;
|
||||||
groupCommunity: DynamicInputModel;
|
groupCommunity: AbstractControl;
|
||||||
groupDescription: DynamicTextAreaModel;
|
groupDescription: AbstractControl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of all dynamic input models
|
* A list of all dynamic input models
|
||||||
@@ -113,21 +109,30 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
subs: Subscription[] = [];
|
subs: Subscription[] = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Group currently being edited
|
|
||||||
*/
|
|
||||||
groupBeingEdited: Group;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observable whether or not the logged in user is allowed to delete the Group & doesn't have a linked object (community / collection linked to workspace group
|
* Observable whether or not the logged in user is allowed to delete the Group & doesn't have a linked object (community / collection linked to workspace group
|
||||||
*/
|
*/
|
||||||
canEdit$: Observable<boolean>;
|
canEdit$: Observable<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The AlertType enumeration
|
* The current {@link Group}
|
||||||
* @type {AlertType}
|
|
||||||
*/
|
*/
|
||||||
public AlertTypeEnum = AlertType;
|
activeGroup$: Observable<Group>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current {@link Group}'s linked {@link Community}/{@link Collection}
|
||||||
|
*/
|
||||||
|
activeGroupLinkedDSO$: Observable<DSpaceObject>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to the current {@link Group}'s {@link Community}/{@link Collection} edit role tab
|
||||||
|
*/
|
||||||
|
linkedEditRolesRoute$: Observable<string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The AlertType enumeration
|
||||||
|
*/
|
||||||
|
public readonly AlertType = AlertType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscription to email field value change
|
* Subscription to email field value change
|
||||||
@@ -137,110 +142,97 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public groupDataService: GroupDataService,
|
public groupDataService: GroupDataService,
|
||||||
private ePersonDataService: EPersonDataService,
|
protected dSpaceObjectDataService: DSpaceObjectDataService,
|
||||||
private dSpaceObjectDataService: DSpaceObjectDataService,
|
protected formBuilderService: FormBuilderService,
|
||||||
private formBuilderService: FormBuilderService,
|
protected translateService: TranslateService,
|
||||||
private translateService: TranslateService,
|
protected notificationsService: NotificationsService,
|
||||||
private notificationsService: NotificationsService,
|
protected route: ActivatedRoute,
|
||||||
private route: ActivatedRoute,
|
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
private authorizationService: AuthorizationDataService,
|
protected authorizationService: AuthorizationDataService,
|
||||||
private modalService: NgbModal,
|
protected modalService: NgbModal,
|
||||||
public requestService: RequestService,
|
public requestService: RequestService,
|
||||||
protected changeDetectorRef: ChangeDetectorRef,
|
protected changeDetectorRef: ChangeDetectorRef,
|
||||||
public dsoNameService: DSONameService,
|
public dsoNameService: DSONameService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit(): void {
|
||||||
|
if (this.route.snapshot.params.groupId !== 'newGroup') {
|
||||||
|
this.setActiveGroup(this.route.snapshot.params.groupId);
|
||||||
|
}
|
||||||
|
this.activeGroup$ = this.groupDataService.getActiveGroup();
|
||||||
|
this.activeGroupLinkedDSO$ = this.getActiveGroupLinkedDSO();
|
||||||
|
this.linkedEditRolesRoute$ = this.getLinkedEditRolesRoute();
|
||||||
|
this.canEdit$ = this.activeGroupLinkedDSO$.pipe(
|
||||||
|
filter((dso: DSpaceObject) => hasNoValue(dso)),
|
||||||
|
switchMap(() => this.activeGroup$),
|
||||||
|
hasValueOperator(),
|
||||||
|
switchMap((group: Group) => this.authorizationService.isAuthorized(FeatureID.CanDelete, group.self)),
|
||||||
|
startWith(false),
|
||||||
|
);
|
||||||
this.initialisePage();
|
this.initialisePage();
|
||||||
}
|
}
|
||||||
|
|
||||||
initialisePage() {
|
initialisePage() {
|
||||||
this.subs.push(this.route.params.subscribe((params) => {
|
const groupNameModel = new DynamicInputModel({
|
||||||
if (params.groupId !== 'newGroup') {
|
|
||||||
this.setActiveGroup(params.groupId);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
this.canEdit$ = this.groupDataService.getActiveGroup().pipe(
|
|
||||||
hasValueOperator(),
|
|
||||||
switchMap((group: Group) => {
|
|
||||||
return observableCombineLatest(
|
|
||||||
this.authorizationService.isAuthorized(FeatureID.CanDelete, isNotEmpty(group) ? group.self : undefined),
|
|
||||||
this.hasLinkedDSO(group),
|
|
||||||
(isAuthorized: ObservedValueOf<Observable<boolean>>, hasLinkedDSO: ObservedValueOf<Observable<boolean>>) => {
|
|
||||||
return isAuthorized && !hasLinkedDSO;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
observableCombineLatest(
|
|
||||||
this.translateService.get(`${this.messagePrefix}.groupName`),
|
|
||||||
this.translateService.get(`${this.messagePrefix}.groupCommunity`),
|
|
||||||
this.translateService.get(`${this.messagePrefix}.groupDescription`)
|
|
||||||
).subscribe(([groupName, groupCommunity, groupDescription]) => {
|
|
||||||
this.groupName = new DynamicInputModel({
|
|
||||||
id: 'groupName',
|
id: 'groupName',
|
||||||
label: groupName,
|
label: this.translateService.instant(`${this.messagePrefix}.groupName`),
|
||||||
name: 'groupName',
|
name: 'groupName',
|
||||||
validators: {
|
validators: {
|
||||||
required: null,
|
required: null,
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
this.groupCommunity = new DynamicInputModel({
|
const groupCommunityModel = new DynamicInputModel({
|
||||||
id: 'groupCommunity',
|
id: 'groupCommunity',
|
||||||
label: groupCommunity,
|
label: this.translateService.instant(`${this.messagePrefix}.groupCommunity`),
|
||||||
name: 'groupCommunity',
|
name: 'groupCommunity',
|
||||||
required: false,
|
required: false,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
});
|
});
|
||||||
this.groupDescription = new DynamicTextAreaModel({
|
const groupDescriptionModel = new DynamicTextAreaModel({
|
||||||
id: 'groupDescription',
|
id: 'groupDescription',
|
||||||
label: groupDescription,
|
label: this.translateService.instant(`${this.messagePrefix}.groupDescription`),
|
||||||
name: 'groupDescription',
|
name: 'groupDescription',
|
||||||
required: false,
|
required: false,
|
||||||
spellCheck: environment.form.spellCheck,
|
spellCheck: environment.form.spellCheck,
|
||||||
});
|
});
|
||||||
this.formModel = [
|
this.formModel = [
|
||||||
this.groupName,
|
groupNameModel,
|
||||||
this.groupDescription,
|
groupDescriptionModel,
|
||||||
];
|
];
|
||||||
this.formGroup = this.formBuilderService.createFormGroup(this.formModel);
|
this.formGroup = this.formBuilderService.createFormGroup(this.formModel);
|
||||||
|
this.groupName = this.formGroup.get('groupName');
|
||||||
|
this.groupDescription = this.formGroup.get('groupDescription');
|
||||||
|
|
||||||
if (!!this.formGroup.controls.groupName) {
|
if (hasValue(this.groupName)) {
|
||||||
this.formGroup.controls.groupName.setAsyncValidators(ValidateGroupExists.createValidator(this.groupDataService));
|
this.groupName.setAsyncValidators(ValidateGroupExists.createValidator(this.groupDataService));
|
||||||
this.groupNameValueChangeSubscribe = this.groupName.valueChanges.pipe(debounceTime(300)).subscribe(() => {
|
this.groupNameValueChangeSubscribe = this.groupName.valueChanges.pipe(debounceTime(300)).subscribe(() => {
|
||||||
this.changeDetectorRef.detectChanges();
|
this.changeDetectorRef.detectChanges();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.subs.push(
|
this.subs.push(
|
||||||
observableCombineLatest(
|
combineLatest([
|
||||||
this.groupDataService.getActiveGroup(),
|
this.activeGroup$,
|
||||||
this.canEdit$,
|
this.canEdit$,
|
||||||
this.groupDataService.getActiveGroup()
|
this.activeGroupLinkedDSO$.pipe(take(1)),
|
||||||
.pipe(filter((activeGroup) => hasValue(activeGroup)),switchMap((activeGroup) => this.getLinkedDSO(activeGroup).pipe(getFirstSucceededRemoteDataPayload())))
|
]).subscribe(([activeGroup, canEdit, linkedObject]) => {
|
||||||
).subscribe(([activeGroup, canEdit, linkedObject]) => {
|
|
||||||
|
|
||||||
if (activeGroup != null) {
|
if (activeGroup != null) {
|
||||||
|
|
||||||
// Disable group name exists validator
|
// Disable group name exists validator
|
||||||
this.formGroup.controls.groupName.clearAsyncValidators();
|
this.formGroup.controls.groupName.clearAsyncValidators();
|
||||||
|
|
||||||
this.groupBeingEdited = activeGroup;
|
|
||||||
|
|
||||||
if (linkedObject?.name) {
|
if (linkedObject?.name) {
|
||||||
this.formBuilderService.insertFormGroupControl(1, this.formGroup, this.formModel, this.groupCommunity);
|
this.formBuilderService.insertFormGroupControl(1, this.formGroup, this.formModel, groupCommunityModel);
|
||||||
|
this.groupDescription = this.formGroup.get('groupCommunity');
|
||||||
this.formGroup.patchValue({
|
this.formGroup.patchValue({
|
||||||
groupName: activeGroup.name,
|
groupName: activeGroup.name,
|
||||||
groupCommunity: linkedObject?.name ?? '',
|
groupCommunity: linkedObject?.name ?? '',
|
||||||
groupDescription: activeGroup.firstMetadataValue('dc.description'),
|
groupDescription: activeGroup.firstMetadataValue('dc.description'),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.formModel = [
|
|
||||||
this.groupName,
|
|
||||||
this.groupDescription,
|
|
||||||
];
|
|
||||||
this.formGroup.patchValue({
|
this.formGroup.patchValue({
|
||||||
groupName: activeGroup.name,
|
groupName: activeGroup.name,
|
||||||
groupDescription: activeGroup.firstMetadataValue('dc.description'),
|
groupDescription: activeGroup.firstMetadataValue('dc.description'),
|
||||||
@@ -254,7 +246,6 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -273,25 +264,22 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
* Emit the updated/created eperson using the EventEmitter submitForm
|
* Emit the updated/created eperson using the EventEmitter submitForm
|
||||||
*/
|
*/
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.groupDataService.getActiveGroup().pipe(take(1)).subscribe(
|
this.activeGroup$.pipe(take(1)).subscribe((group: Group) => {
|
||||||
(group: Group) => {
|
if (group === null) {
|
||||||
const values = {
|
this.createNewGroup({
|
||||||
name: this.groupName.value,
|
name: this.groupName.value,
|
||||||
metadata: {
|
metadata: {
|
||||||
'dc.description': [
|
'dc.description': [
|
||||||
{
|
{
|
||||||
value: this.groupDescription.value
|
value: this.groupDescription.value,
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
};
|
],
|
||||||
if (group === null) {
|
},
|
||||||
this.createNewGroup(values);
|
});
|
||||||
} else {
|
} else {
|
||||||
this.editGroup(group);
|
this.editGroup(group);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -397,7 +385,7 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
* @param groupSelfLink SelfLink of group to set as active
|
* @param groupSelfLink SelfLink of group to set as active
|
||||||
*/
|
*/
|
||||||
setActiveGroupWithLink(groupSelfLink: string) {
|
setActiveGroupWithLink(groupSelfLink: string) {
|
||||||
this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => {
|
this.activeGroup$.pipe(take(1)).subscribe((activeGroup: Group) => {
|
||||||
if (activeGroup === null) {
|
if (activeGroup === null) {
|
||||||
this.groupDataService.cancelEditGroup();
|
this.groupDataService.cancelEditGroup();
|
||||||
this.groupDataService.findByHref(groupSelfLink, false, false, followLink('subgroups'), followLink('epersons'), followLink('object'))
|
this.groupDataService.findByHref(groupSelfLink, false, false, followLink('subgroups'), followLink('epersons'), followLink('object'))
|
||||||
@@ -416,7 +404,7 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
* It'll either show a success or error message depending on whether the delete was successful or not.
|
* It'll either show a success or error message depending on whether the delete was successful or not.
|
||||||
*/
|
*/
|
||||||
delete() {
|
delete() {
|
||||||
this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((group: Group) => {
|
this.activeGroup$.pipe(take(1)).subscribe((group: Group) => {
|
||||||
const modalRef = this.modalService.open(ConfirmationModalComponent);
|
const modalRef = this.modalService.open(ConfirmationModalComponent);
|
||||||
modalRef.componentInstance.dso = group;
|
modalRef.componentInstance.dso = group;
|
||||||
modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-group.modal.header';
|
modalRef.componentInstance.headerLabel = this.messagePrefix + '.delete-group.modal.header';
|
||||||
@@ -460,52 +448,37 @@ export class GroupFormComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if group has a linked object (community or collection linked to a workflow group)
|
* Get the active {@link Group}'s linked object if it has one ({@link Community} or {@link Collection} linked to a
|
||||||
* @param group
|
* workflow group)
|
||||||
*/
|
*/
|
||||||
hasLinkedDSO(group: Group): Observable<boolean> {
|
getActiveGroupLinkedDSO(): Observable<DSpaceObject> {
|
||||||
if (hasValue(group) && hasValue(group._links.object.href)) {
|
return this.activeGroup$.pipe(
|
||||||
return this.getLinkedDSO(group).pipe(
|
hasValueOperator(),
|
||||||
map((rd: RemoteData<DSpaceObject>) => {
|
switchMap((group: Group) => {
|
||||||
return hasValue(rd) && hasValue(rd.payload);
|
|
||||||
}),
|
|
||||||
catchError(() => observableOf(false)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get group's linked object if it has one (community or collection linked to a workflow group)
|
|
||||||
* @param group
|
|
||||||
*/
|
|
||||||
getLinkedDSO(group: Group): Observable<RemoteData<DSpaceObject>> {
|
|
||||||
if (hasValue(group) && hasValue(group._links.object.href)) {
|
|
||||||
if (group.object === undefined) {
|
if (group.object === undefined) {
|
||||||
return this.dSpaceObjectDataService.findByHref(group._links.object.href);
|
return this.dSpaceObjectDataService.findByHref(group._links.object.href);
|
||||||
}
|
}
|
||||||
return group.object;
|
return group.object;
|
||||||
}
|
}),
|
||||||
|
getAllCompletedRemoteData(),
|
||||||
|
getRemoteDataPayload(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the route to the edit roles tab of the group's linked object (community or collection linked to a workflow group) if it has one
|
* Get the route to the edit roles tab of the active {@link Group}'s linked object (community or collection linked
|
||||||
* @param group
|
* to a workflow group) if it has one
|
||||||
*/
|
*/
|
||||||
getLinkedEditRolesRoute(group: Group): Observable<string> {
|
getLinkedEditRolesRoute(): Observable<string> {
|
||||||
if (hasValue(group) && hasValue(group._links.object.href)) {
|
return this.activeGroupLinkedDSO$.pipe(
|
||||||
return this.getLinkedDSO(group).pipe(
|
map((dso: DSpaceObject) => {
|
||||||
map((rd: RemoteData<DSpaceObject>) => {
|
|
||||||
if (hasValue(rd) && hasValue(rd.payload)) {
|
|
||||||
const dso = rd.payload;
|
|
||||||
switch ((dso as any).type) {
|
switch ((dso as any).type) {
|
||||||
case Community.type.value:
|
case Community.type.value:
|
||||||
return getCommunityEditRolesRoute(rd.payload.id);
|
return getCommunityEditRolesRoute(dso.id);
|
||||||
case Collection.type.value:
|
case Collection.type.value:
|
||||||
return getCollectionEditRolesRoute(rd.payload.id);
|
return getCollectionEditRolesRoute(dso.id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user