diff --git a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.html b/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.html index 9956163944..1932c37000 100644 --- a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.html +++ b/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.html @@ -1,4 +1,4 @@ - - - - diff --git a/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.scss b/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.scss deleted file mode 100644 index fb9db5b0ff..0000000000 --- a/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.alert{ - font-weight: bold; - color:red; -} diff --git a/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.spec.ts b/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.spec.ts deleted file mode 100644 index d406fa2c1a..0000000000 --- a/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.spec.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { ComponentFixture, ComponentFixtureAutoDetect, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing'; -import { cold } from 'jasmine-marbles'; - -// Import modules -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule } from '@angular/forms'; -import { By } from '@angular/platform-browser'; -import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { DebugElement } from '@angular/core'; - -import { SubscriptionEditModalComponent } from './subscription-edit-modal.component'; - -// Import mocks -import { TranslateLoaderMock } from '../../../mocks/translate-loader.mock'; -import { subscription } from '../../../testing/subscriptions-data.mock'; -import { ItemInfo } from '../../../testing/relationships-mocks'; - -// Import utils -import { NotificationsService } from '../../../notifications/notifications.service'; -import { NotificationsServiceStub } from '../../../testing/notifications-service.stub'; -import { SubscriptionService } from '../../subscription.service'; -import { Subscription } from '../../models/subscription.model'; - - -describe('SubscriptionEditModalComponent', () => { - let component: SubscriptionEditModalComponent; - let fixture: ComponentFixture; - let de: DebugElement; - - const subscriptionServiceStub = jasmine.createSpyObj('SubscriptionService', { - updateSubscription: jasmine.createSpy('updateSubscription'), - }); - - - beforeEach(waitForAsync (() => { - TestBed.configureTestingModule({ - imports: [ - CommonModule, - ReactiveFormsModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useClass: TranslateLoaderMock - } - }), - ], - declarations: [ SubscriptionEditModalComponent ], - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true }, - { provide: NotificationsService, useValue: NotificationsServiceStub }, - { provide: SubscriptionService, useValue: subscriptionServiceStub }, - ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(SubscriptionEditModalComponent); - component = fixture.componentInstance; - component.eperson = 'testid123'; - component.dso = ItemInfo.payload; - - de = fixture.debugElement; - - subscriptionServiceStub.updateSubscription.and.returnValue(cold('a|', { - a: {} - })); - - - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('No Subscription inserted', () => { - it('should not show form', () => { - expect(de.query(By.css('form'))).toBeNull(); - }); - }); - - - describe('Subscription inserted', () => { - - beforeEach(fakeAsync(() => { - component.subscription = Object.assign(new Subscription(), subscription); - component.ngOnInit(); - fixture.detectChanges(); - })); - - it('when insert subscription show form', () => { - expect(de.query(By.css('form'))).toBeTruthy(); - }); - - it('should have right checkboxes checked', () => { - expect(de.query(By.css('#checkbox-0'))?.nativeElement?.checked).toEqual(true); - expect(de.query(By.css('#checkbox-1'))?.nativeElement?.checked).toEqual(true); - expect(de.query(By.css('#checkbox-2'))?.nativeElement?.checked).toEqual(false); - }); - - it('on checkbox clicked should change form values', () => { - const checkbox = de.query(By.css('#checkbox-2')).nativeElement; - checkbox.click(); - - expect(de.query(By.css('#checkbox-2'))?.nativeElement?.checked).toEqual(true); - expect(component.subscriptionParameterList?.value?.length).toEqual(3); - }); - - it('on submit clicked update should have been called', () => { - const button = de.query(By.css('.btn-success')).nativeElement; - button.click(); - expect(subscriptionServiceStub.updateSubscription).toHaveBeenCalled(); - }); - }); -}); diff --git a/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.ts b/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.ts deleted file mode 100644 index 46c895dc18..0000000000 --- a/src/app/shared/subscriptions/components/subscription-edit-modal/subscription-edit-modal.component.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; - -import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; - -import { Subscription } from '../../models/subscription.model'; - -import { BehaviorSubject } from 'rxjs'; - -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; - -import { SubscriptionService } from '../../subscription.service'; -import { NotificationsService } from '../../../notifications/notifications.service'; - -import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; - -@Component({ - selector: 'ds-subscription-edit-modal', - templateUrl: './subscription-edit-modal.component.html', - styleUrls: ['./subscription-edit-modal.component.scss'] -}) -export class SubscriptionEditModalComponent implements OnInit { - - - /** - * DSpaceObject of the subscription - */ - @Input() dso: DSpaceObject; - - /** - * EPerson of the subscription - */ - @Input() eperson: string; - - /** - * List of subscription for the dso object and eperson relation - */ - @Input() subscription!: Subscription; - - /** - * Close event emit to close modal - */ - @Output() close: EventEmitter = new EventEmitter(); - - /** - * Reload event emit to refresh informations - */ - @Output() reload: EventEmitter = new EventEmitter(); - - /** - * A boolean representing if a request operation is pending - * @type {BehaviorSubject} - */ - public processing$ = new BehaviorSubject(false); - - /** - * Reactive form group that will be used to add subscriptions - */ - subscriptionForm: FormGroup; - - /** - * Used to show validation errors when user submits - */ - submitted = false; - - /** - * Reference to NgbModal - */ - public modalRef: NgbModalRef; - - - /** - * Frequencies to be shown as checkboxes - */ - frequencies = [ - {name: 'daily' ,value: 'D'}, - {name: 'monthly' ,value: 'M'}, - {name: 'weekly' ,value: 'W'}, - ]; - - constructor(private formGroup: FormBuilder, - private notificationsService: NotificationsService, - private subscriptionService: SubscriptionService - ) {} - - /** - * When component starts initialize starting functionality - */ - ngOnInit(): void { - this.initSubscription(); - } - - /** - * If the subscription is passed start the form with the information of subscription - */ - initSubscription(): void { - if (!!this.subscription) { - this.buildFormBuilder(this.subscription); - } - } - - /** - * Function to get subscriptionParameterList form array cleaner - */ - get subscriptionParameterList(): FormArray { - return this.subscriptionForm.get('subscriptionParameterList') as FormArray; - } - - /** - * When frequency checkboxes are being changed we add/remove frequencies from subscriptionParameterList - */ - selectCheckbox(event,frequency): void { - if (event.target.checked) { - this.addFrequency(frequency); - } else { - this.removeFrequency(frequency); - } - } - - /** - * Start the form with preinserted informations - */ - buildFormBuilder(subscription): void { - - this.subscriptionForm = this.formGroup.group({ - id: subscription.id, - type: subscription.subscriptionType, - subscriptionParameterList: this.formGroup.array([], Validators.required) - }); - - subscription.subscriptionParameterList.forEach( (parameter) => { - this.addFrequency(parameter.value); - }); - } - - /** - * Add a new frequency to the subscriptionParameterList form array - */ - addFrequency(frequency): void { - this.subscriptionParameterList.push( - this.formGroup.group({ - name: 'frequency', - value: frequency - }) - ); - } - - /** - * Remove frequency from subscriptionParameterList form array - */ - removeFrequency(frequency): void { - const index = this.subscriptionParameterList.controls.findIndex(el => el.value.value === frequency); - this.subscriptionParameterList.removeAt(index); - } - - /** - * When user saves it will check if form is valid and send request to update subscription - */ - submit(): void { - this.submitted = true; - if (this.subscriptionForm.valid) { - if (this.subscriptionForm.value.id) { - this.updateForm(this.subscriptionForm.value); - } - } - } - - /** - * Sends request to update a new subscription, refreshes the table of subscriptions and notifies about summary page - */ - updateForm(body): void { - this.subscriptionService.updateSubscription(body,this.eperson,this.dso.uuid).subscribe( (res) => { - this.reload.emit(); - this.close.emit(); - }); - } - - /** - * When close button is pressed emit function to close modal - */ - c(text): void { - this.close.emit(text); - } - - /** - * Returns if a specific frequency exists in the subscriptionParameterList - */ - getIsChecked(frequency): boolean { - return !!this.subscriptionForm.get('subscriptionParameterList').value.find(el => el.value === frequency.value); - } -} diff --git a/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.scss b/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.scss deleted file mode 100644 index 62dd1105e7..0000000000 --- a/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.scss +++ /dev/null @@ -1,12 +0,0 @@ -.alert{ - font-weight: bold; - color:red; -} - -// .modal-footer{ -// justify-content: space-between; -// } - -.add-button{ - padding: 0px 15px 15px 15px; -} \ No newline at end of file diff --git a/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.spec.ts b/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.spec.ts deleted file mode 100644 index 088ec3004c..0000000000 --- a/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.spec.ts +++ /dev/null @@ -1,223 +0,0 @@ -import { ComponentFixture, ComponentFixtureAutoDetect, TestBed } from '@angular/core/testing'; - -import { of as observableOf } from 'rxjs'; - -// Import modules -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule } from '@angular/forms'; -import { By } from '@angular/platform-browser'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { DebugElement } from '@angular/core'; - -import { SubscriptionModalComponent } from './subscription-modal.component'; - -// Import mocks -import { TranslateLoaderMock } from '../../../mocks/translate-loader.mock'; -import { findByEPersonAndDsoRes, findByEPersonAndDsoResEmpty } from '../../../testing/subscriptions-data.mock'; -import { ItemInfo } from '../../../testing/relationships-mocks'; - -// Import utils -import { NotificationsService } from '../../../notifications/notifications.service'; -import { SubscriptionService } from '../../subscription.service'; - -import { createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils'; - - -describe('SubscriptionModalComponent', () => { - let component: SubscriptionModalComponent; - let fixture: ComponentFixture; - let de: DebugElement; - - let subscriptionServiceStub; - const notificationServiceStub = { - notificationWithAnchor() { - return true; - } - }; - - - describe('when empty subscriptions', () => { - - beforeEach(async () => { - - subscriptionServiceStub = jasmine.createSpyObj('SubscriptionService', { - getSubscriptionByPersonDSO: observableOf(findByEPersonAndDsoResEmpty), - createSubscription: createSuccessfulRemoteDataObject$({}), - updateSubscription: createSuccessfulRemoteDataObject$({}), - }); - - await TestBed.configureTestingModule({ - imports: [ - CommonModule, - NgbModule, - ReactiveFormsModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useClass: TranslateLoaderMock - } - }), - ], - declarations: [SubscriptionModalComponent], - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true }, - { provide: NotificationsService, useValue: notificationServiceStub }, - { provide: SubscriptionService, useValue: subscriptionServiceStub }, - ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(SubscriptionModalComponent); - component = fixture.componentInstance; - component.ePersonId = 'testid123'; - component.dso = ItemInfo.payload; - de = fixture.debugElement; - - await fixture.whenStable(); - await fixture.whenRenderingDone(); - - fixture.detectChanges(); - - }); - - it('should be no table', () => { - expect(de.query(By.css('table'))).toBeNull(); - }); - - it('should show empty form', () => { - expect(de.query(By.css('form'))).toBeTruthy(); - }); - - it('should show form with empty checkboxes', () => { - expect(de.query(By.css('#checkbox-0'))?.nativeElement?.checked).toEqual(false); - expect(de.query(By.css('#checkbox-1'))?.nativeElement?.checked).toEqual(false); - expect(de.query(By.css('#checkbox-2'))?.nativeElement?.checked).toEqual(false); - }); - - }); - - - describe('when we have subscriptions', () => { - - beforeEach(async () => { - - subscriptionServiceStub = jasmine.createSpyObj('SubscriptionService', { - getSubscriptionByPersonDSO: observableOf(findByEPersonAndDsoRes), - createSubscription: createSuccessfulRemoteDataObject$({}), - updateSubscription: createSuccessfulRemoteDataObject$({}), - }); - - await TestBed.configureTestingModule({ - imports: [ - CommonModule, - NgbModule, - ReactiveFormsModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useClass: TranslateLoaderMock - } - }), - ], - declarations: [SubscriptionModalComponent], - providers: [ - { provide: ComponentFixtureAutoDetect, useValue: true }, - { provide: NotificationsService, useValue: notificationServiceStub }, - { provide: SubscriptionService, useValue: subscriptionServiceStub }, - ] - }) - .compileComponents(); - - fixture = TestBed.createComponent(SubscriptionModalComponent); - component = fixture.componentInstance; - component.ePersonId = 'testid123'; - component.dso = ItemInfo.payload; - de = fixture.debugElement; - await fixture.whenStable(); - await fixture.whenRenderingDone(); - - fixture.detectChanges(); - - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - it('should render 2 subscriptions', () => { - expect(de.queryAll(By.css('tbody > tr')).length).toEqual(2); - }); - - it('should show no form', () => { - expect(de.query(By.css('form'))).toBeNull(); - }); - - it('should have 2 edit buttons', () => { - expect(de.queryAll(By.css('.btn-outline-primary')).length).toEqual(2); - }); - - it('should have 2 delete buttons', () => { - expect(de.queryAll(By.css('.btn-outline-danger')).length).toEqual(2); - }); - - describe('When creating new subscription', () => { - - beforeEach(() => { - // add button click - const button = de.query(By.css('.btn-success')).nativeElement; - button.click(); - }); - - - it('should show form when add button click event', () => { - expect(de.query(By.css('form'))).toBeTruthy(); - }); - - it('should show form with empty checkboxes', () => { - expect(de.query(By.css('#checkbox-0'))?.nativeElement?.checked).toEqual(false); - expect(de.query(By.css('#checkbox-1'))?.nativeElement?.checked).toEqual(false); - expect(de.query(By.css('#checkbox-2'))?.nativeElement?.checked).toEqual(false); - }); - - it('should call create request when submit click event', () => { - const checkbox = de.query(By.css('#checkbox-2')).nativeElement; - checkbox.click(); - - const button = de.queryAll(By.css('.btn-success'))[1].nativeElement; - button.click(); - expect(subscriptionServiceStub.createSubscription).toHaveBeenCalled(); - }); - - }); - - - describe('When updating subscription', () => { - - beforeEach(() => { - // edit button click - const button = de.query(By.css('.btn-outline-primary')).nativeElement; - button.click(); - }); - - it('should show form when edit button click event', () => { - expect(de.query(By.css('form'))).toBeTruthy(); - }); - - it('should show form with empty checkboxes', () => { - expect(de.query(By.css('#checkbox-0'))?.nativeElement?.checked).toEqual(false); - expect(de.query(By.css('#checkbox-1'))?.nativeElement?.checked).toEqual(true); - expect(de.query(By.css('#checkbox-2'))?.nativeElement?.checked).toEqual(false); - }); - - it('should call update request when submit click event', () => { - const button = de.queryAll(By.css('.btn-success'))[1].nativeElement; - button.click(); - expect(subscriptionServiceStub.updateSubscription).toHaveBeenCalled(); - }); - - }); - - }); - -}); diff --git a/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.ts b/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.ts deleted file mode 100644 index b283e12d34..0000000000 --- a/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.ts +++ /dev/null @@ -1,270 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; - -import { FormBuilder, FormGroup } from '@angular/forms'; - -import { Subscription } from '../../models/subscription.model'; - -import { BehaviorSubject, Observable, shareReplay } from 'rxjs'; - -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; - -import { SubscriptionService } from '../../subscription.service'; -import { NotificationsService } from '../../../notifications/notifications.service'; - -import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'; - -import { PaginatedList } from '../../../../core/data/paginated-list.model'; - -import { map, switchMap, take, tap } from 'rxjs/operators'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; -import { AuthService } from '../../../../core/auth/auth.service'; -import { NotificationType } from '../../../notifications/models/notification-type'; -import { NotificationOptions } from '../../../notifications/models/notification-options.model'; - -@Component({ - selector: 'ds-subscription-modal', - templateUrl: './subscription-modal.component.html', - styleUrls: ['./subscription-modal.component.scss'] -}) -export class SubscriptionModalComponent implements OnInit { - - /** - * DSpaceObject of which to get the subscriptions - */ - @Input() dso: DSpaceObject; - - /** - * List of subscription for the dso object and eperson relation - */ - subscriptions: Subscription[]; - - /** - * A boolean representing if a request operation is pending - * @type {BehaviorSubject} - */ - public processing$ = new BehaviorSubject(false); - - /** - * Reactive form group that will be used to add subscriptions - */ - subscriptionForm: FormGroup; - - /** - * Used to show validation errors when user submits - */ - submitted = false; - - ePersonId$: Observable; - - ePersonId: string; - - /** - * Types of subscription to be shown on select - */ - subscriptionTypes = [ 'content', 'statistics' ]; - - /** - * Frequencies to be shown as checkboxes - */ - frequencies = [ 'D', 'M', 'W' ]; - - constructor( - private formBuilder: FormBuilder, - private modalService: NgbModal, - private notificationsService: NotificationsService, - private subscriptionService: SubscriptionService, - public activeModal: NgbActiveModal, - private authService: AuthService, - ) { - } - - /** - * When component starts initialize starting functionality - */ - ngOnInit(): void { - - this.ePersonId$ = this.authService.getAuthenticatedUserFromStore().pipe( - take(1), - map((ePerson) => ePerson.uuid), - tap((res) => { - this.ePersonId = res; - }), - shareReplay(), - ); - - this.subscriptionForm = this.formBuilder.group({}); - - for (let f of this.frequencies) { - this.subscriptionForm.addControl(f, this.formBuilder.control(false)); - } - - // TODO iterate over subscription types - - /*this.subscriptionForm = this.formBuilder.group({}); - for (let t of this.subscriptionTypes) { - this.subscriptionForm.addControl(t, this.formBuilder.group({})); - for (let f of this.frequencies) { - this.subscriptionForm[t].addControl(f, this.formBuilder.control(false)); - } - }*/ - - - this.initSubscription(); - - } - - /** - * Get subscription for the eperson & dso object relation - * If no subscription start with an empty form - */ - initSubscription(): void { - this.processing$.next(true); - this.ePersonId$.pipe( - tap(console.log), - switchMap((ePersonId: string) => this.getSubscription(ePersonId, this.dso?.uuid)), - getFirstSucceededRemoteDataPayload(), - ).subscribe({ - next: (res: PaginatedList) => { - if (res.pageInfo.totalElements > 0) { - this.subscriptions = res.page; - - // TODO loop over subscription types - // for (let type of this.subscriptionTypes) { - const type = 'content'; // TODO remove - const subscription = this.subscriptions.find((s) => s.subscriptionType === type); - // TODO manage multiple subscriptions with same type (there should be only one) - for (let parameter of subscription.subscriptionParameterList.filter((p) => p.name === 'frequency')) { - this.subscriptionForm.controls[parameter.value]?.setValue(true); - } - // } - - } - this.processing$.next(false); - }, - error: err => { - this.processing$.next(false); - } - }); - } - - /** - * Function to get subscriptions based on the eperson & dso - * - * @param ePersonId Eperson that is logged in - * @param uuid DSpaceObject id that subscriptions are related to - */ - getSubscription(ePersonId: string, uuid: string): Observable>> { - return this.subscriptionService.getSubscriptionByPersonDSO(ePersonId, uuid); - } - - - - submit() { - - // for (let type of this.subscriptionTypes) { - - const type = 'content'; // TODO remove - - const currentSubscription = this.subscriptions?.find((s) => s.subscriptionType === type); - - const body = { - id: currentSubscription?.id, - type, - subscriptionParameterList: [] - }; - - let someCheckboxSelected = false; - - for (let frequency of this.frequencies) { - if (this.subscriptionForm.value[frequency]) { // TODO read the value for the type - someCheckboxSelected = true; - body.subscriptionParameterList.push( - { - name: 'frequency', - value: frequency, - } - ); - } - } - - if (currentSubscription) { - const subscriptionsToBeRemobed = this.subscriptions?.filter( - (s) => s.subscriptionType === type && s.id !== currentSubscription.id - ); - for (let s of subscriptionsToBeRemobed) { - this.subscriptionService.deleteSubscription(currentSubscription.id).pipe( - getFirstCompletedRemoteData(), - ).subscribe((res) => { - if (res.hasSucceeded) { - console.warn(`An additional subscription with type=${type} and id=${s.id} has been removed`); - } else { - this.notifyFailure(); - } - }); - } - } - - - if (currentSubscription && someCheckboxSelected) { - // Update the existing subscription - this.subscriptionService.updateSubscription(body, this.ePersonId, this.dso.uuid).pipe( - getFirstCompletedRemoteData(), - ).subscribe((res) => { - if (res.hasSucceeded) { - this.notifySuccess(); - this.activeModal.close(); - } else { - this.notifyFailure(); - } - }); - } else if (currentSubscription && !someCheckboxSelected) { - // Delete the existing subscription - this.subscriptionService.deleteSubscription(currentSubscription.id).subscribe(console.log); - // TODO handle notifications - } else if (someCheckboxSelected) { - // Create a new subscription - this.subscriptionService.createSubscription(body, this.ePersonId, this.dso.uuid).subscribe(console.log); - // TODO handle notifications - } - - - // } - - // this.subscriptionService.createSubscription(body, this.ePersonId, this.dso.uuid).subscribe((res) => { - // // this.refresh(); - // // this.notify(); - // // this.processing$.next(false); - // }, - // err => { - // // this.processing$.next(false); - // } - // ); - - } - - - - /** - * Creates a notification with the link to the subscription summary page - */ - notifySuccess(): void { - const options = new NotificationOptions(); - options.timeOut = 0; - const link = '/subscriptions'; - this.notificationsService.notificationWithAnchor( - NotificationType.Success, - options, - link, - 'context-menu.actions.subscription.notification.here-text', - 'context-menu.actions.subscription.notification.content', - 'here' - ); - } - - notifyFailure() { - console.error('error'); - // TODO - } - -} diff --git a/src/app/shared/subscriptions/models/subscription.model.ts b/src/app/shared/subscriptions/models/subscription.model.ts index b5d6977d39..36e43ce996 100644 --- a/src/app/shared/subscriptions/models/subscription.model.ts +++ b/src/app/shared/subscriptions/models/subscription.model.ts @@ -1,11 +1,14 @@ +import { Observable } from 'rxjs'; import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; -import { typedObject } from '../../../core/cache/builders/build-decorators'; +import { link, typedObject } from '../../../core/cache/builders/build-decorators'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { HALLink } from '../../../core/shared/hal-link.model'; import { SUBSCRIPTION } from './subscription.resource-type'; import { EPerson } from '../../../core/eperson/models/eperson.model'; - +import { RemoteData } from '../../../core/data/remote-data'; +import { EPERSON } from '../../../core/eperson/models/eperson.resource-type'; +import { DSPACE_OBJECT } from '../../../core/shared/dspace-object.resource-type'; @typedObject @inheritSerialization(DSpaceObject) @@ -40,14 +43,27 @@ export class Subscription extends DSpaceObject { dSpaceObject: HALLink; }; + /** + * The logo for this Community + * Will be undefined unless the logo {@link HALLink} has been resolved. + */ + @link(EPERSON) + ePerson?: Observable>; + + /** + * The logo for this Community + * Will be undefined unless the logo {@link HALLink} has been resolved. + */ + @link(DSPACE_OBJECT) + dSpaceObject?: Observable>; /** * The embedded ePerson & dSpaceObject for this Subscription */ - @deserialize - _embedded: { - ePerson: EPerson; - dSpaceObject: DSpaceObject; - }; + /* @deserialize + _embedded: { + ePerson: EPerson; + dSpaceObject: DSpaceObject; + };*/ } export interface SubscriptionParameterList { diff --git a/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.html b/src/app/shared/subscriptions/subscription-modal/subscription-modal.component.html similarity index 64% rename from src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.html rename to src/app/shared/subscriptions/subscription-modal/subscription-modal.component.html index 52746fb5c8..ef9e26032d 100644 --- a/src/app/shared/subscriptions/components/subscription-modal/subscription-modal.component.html +++ b/src/app/shared/subscriptions/subscription-modal/subscription-modal.component.html @@ -1,4 +1,4 @@ -
+ - - - - - diff --git a/src/app/shared/subscriptions/subscription-view/subscription-view.component.scss b/src/app/shared/subscriptions/subscription-view/subscription-view.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/subscriptions/components/subscription-view/subscription-view.component.spec.ts b/src/app/shared/subscriptions/subscription-view/subscription-view.component.spec.ts similarity index 77% rename from src/app/shared/subscriptions/components/subscription-view/subscription-view.component.spec.ts rename to src/app/shared/subscriptions/subscription-view/subscription-view.component.spec.ts index e32112c5a0..3ec826d6c5 100644 --- a/src/app/shared/subscriptions/components/subscription-view/subscription-view.component.spec.ts +++ b/src/app/shared/subscriptions/subscription-view/subscription-view.component.spec.ts @@ -6,27 +6,27 @@ import { ReactiveFormsModule } from '@angular/forms'; import { BrowserModule, By } from '@angular/platform-browser'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { SharedModule } from '../../../shared.module'; +import { SharedModule } from '../../shared.module'; import { DebugElement } from '@angular/core'; import { RouterTestingModule } from '@angular/router/testing'; import { SubscriptionViewComponent } from './subscription-view.component'; // Import mocks -import { TranslateLoaderMock } from '../../../mocks/translate-loader.mock'; -import { ItemInfo } from '../../../testing/relationships-mocks'; -import { findByEPersonAndDsoResEmpty, subscription } from '../../../testing/subscriptions-data.mock'; +import { TranslateLoaderMock } from '../../mocks/translate-loader.mock'; +import { findByEPersonAndDsoResEmpty, subscriptionMock } from '../../testing/subscriptions-data.mock'; // Import utils -import { NotificationsService } from '../../../notifications/notifications.service'; -import { NotificationsServiceStub } from '../../../testing/notifications-service.stub'; -import { SubscriptionService } from '../../subscription.service'; -import { Subscription } from '../../models/subscription.model'; +import { NotificationsService } from '../../notifications/notifications.service'; +import { NotificationsServiceStub } from '../../testing/notifications-service.stub'; +import { SubscriptionService } from '../subscription.service'; +import { Subscription } from '../models/subscription.model'; import { of as observableOf } from 'rxjs'; -import { createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils'; - +import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; +import { Item } from '../../../core/shared/item.model'; +import { ITEM } from '../../../core/shared/item.resource-type'; describe('SubscriptionViewComponent', () => { let component: SubscriptionViewComponent; @@ -40,6 +40,19 @@ describe('SubscriptionViewComponent', () => { updateSubscription: createSuccessfulRemoteDataObject$({}), }); + const mockItem = Object.assign(new Item(), { + id: 'fake-id', + uuid: 'fake-id', + handle: 'fake/handle', + lastModified: '2018', + type: ITEM, + _links: { + self: { + href: 'https://localhost:8000/items/fake-id' + } + } + }); + beforeEach(async () => { await TestBed.configureTestingModule({ imports: [ @@ -70,8 +83,8 @@ describe('SubscriptionViewComponent', () => { fixture = TestBed.createComponent(SubscriptionViewComponent); component = fixture.componentInstance; component.eperson = 'testid123'; - component.dso = ItemInfo.payload; - component.subscription = Object.assign(new Subscription(), subscription); + component.dso = mockItem; + component.subscription = Object.assign(new Subscription(), subscriptionMock); de = fixture.debugElement; fixture.detectChanges(); }); diff --git a/src/app/shared/subscriptions/components/subscription-view/subscription-view.component.ts b/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts similarity index 66% rename from src/app/shared/subscriptions/components/subscription-view/subscription-view.component.ts rename to src/app/shared/subscriptions/subscription-view/subscription-view.component.ts index cb831534b6..4844be5b79 100644 --- a/src/app/shared/subscriptions/components/subscription-view/subscription-view.component.ts +++ b/src/app/shared/subscriptions/subscription-view/subscription-view.component.ts @@ -1,13 +1,17 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { Subscription } from '../../models/subscription.model'; -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; +import { Subscription } from '../models/subscription.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { take } from 'rxjs/operators'; - import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; -import { hasValue } from '../../../empty.util'; -import { ConfirmationModalComponent } from '../../../confirmation-modal/confirmation-modal.component'; -import { SubscriptionService } from '../../subscription.service'; + +import { hasValue } from '../../empty.util'; +import { ConfirmationModalComponent } from '../../confirmation-modal/confirmation-modal.component'; +import { SubscriptionService } from '../subscription.service'; +import { getCommunityModuleRoute } from '../../../community-page/community-page-routing-paths'; +import { getCollectionModuleRoute } from '../../../collection-page/collection-page-routing-paths'; +import { getItemModuleRoute } from '../../../item-page/item-page-routing-paths'; +import { SubscriptionModalComponent } from '../subscription-modal/subscription-modal.component'; @Component({ // eslint-disable-next-line @angular-eslint/component-selector @@ -47,16 +51,6 @@ export class SubscriptionViewComponent { private subscriptionService: SubscriptionService, ) { } - - /** - * Open modal - * - * @param content - */ - public openSubscription(content: any) { - this.modalRef = this.modalService.open(content); - } - /** * Return the prefix of the route to the dso object page ( e.g. "items") */ @@ -64,13 +58,13 @@ export class SubscriptionViewComponent { let routePrefix; switch (this.dso.type.toString()) { case 'community': - routePrefix = '/communities'; + routePrefix = getCommunityModuleRoute(); break; case 'collection': - routePrefix = '/collections'; + routePrefix = getCollectionModuleRoute(); break; case 'item': - routePrefix = '/items'; + routePrefix = getItemModuleRoute(); break; } return routePrefix; @@ -99,4 +93,14 @@ export class SubscriptionViewComponent { }); } } + + public openSubscriptionModal() { + this.modalRef = this.modalService.open(SubscriptionModalComponent); + this.modalRef.componentInstance.dso = this.dso; + this.modalRef.componentInstance.subscription = this.subscription; + this.modalRef.componentInstance.updateSubscription.pipe(take(1)).subscribe((subscription: Subscription) => { + this.subscription = subscription; + }) + + } } diff --git a/src/app/shared/subscriptions/subscription.service.ts b/src/app/shared/subscriptions/subscription.service.ts index 5010286e72..480598a15a 100644 --- a/src/app/shared/subscriptions/subscription.service.ts +++ b/src/app/shared/subscriptions/subscription.service.ts @@ -70,7 +70,7 @@ export class SubscriptionService extends IdentifiableDataService { * @param eperson The eperson to search for * @param uuid The uuid of the dsobjcet to search for */ - getSubscriptionByPersonDSO(eperson: string, uuid: string): Observable>> { + getSubscriptionsByPersonDSO(eperson: string, uuid: string): Observable>> { const optionsWithObject = Object.assign(new FindListOptions(), { searchParams: [ @@ -160,7 +160,14 @@ export class SubscriptionService extends IdentifiableDataService { ] }); - return this.searchData.searchBy(this.findByEpersonLinkPath, optionsWithObject, true, true, followLink('dSpaceObject'), followLink('ePerson')); + // return this.searchData.searchBy(this.findByEpersonLinkPath, optionsWithObject, true, true, followLink('dSpaceObject'), followLink('ePerson')); + + return this.getEndpoint().pipe( + map(href => `${href}/search/${this.findByEpersonLinkPath}`), + switchMap(href => this.findListByHref(href, optionsWithObject, true, true, followLink('dSpaceObject'), followLink('ePerson'))) + ); + + } } diff --git a/src/app/shared/subscriptions/subscriptions.module.ts b/src/app/shared/subscriptions/subscriptions.module.ts index 9b72493f67..122bf5ca8d 100644 --- a/src/app/shared/subscriptions/subscriptions.module.ts +++ b/src/app/shared/subscriptions/subscriptions.module.ts @@ -2,16 +2,16 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ReactiveFormsModule } from '@angular/forms'; -import { SubscriptionViewComponent } from './components/subscription-view/subscription-view.component'; -import { SubscriptionModalComponent } from './components/subscription-modal/subscription-modal.component'; -import { SubscriptionEditModalComponent } from './components/subscription-edit-modal/subscription-edit-modal.component'; +import { SubscriptionViewComponent } from './subscription-view/subscription-view.component'; +import { SubscriptionModalComponent } from './subscription-modal/subscription-modal.component'; import { TranslateModule } from '@ngx-translate/core'; import { RouterModule } from '@angular/router'; +import { SharedModule } from '../shared.module'; +import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap'; const COMPONENTS = [ SubscriptionViewComponent, - SubscriptionModalComponent, - SubscriptionEditModalComponent, + SubscriptionModalComponent ]; @NgModule({ @@ -20,12 +20,15 @@ const COMPONENTS = [ ], imports: [ CommonModule, + NgbModalModule, ReactiveFormsModule, TranslateModule, - RouterModule + RouterModule, + SharedModule ], exports: [ ...COMPONENTS ] }) -export class SubscriptionsModule { } +export class SubscriptionsModule { +} diff --git a/src/app/shared/testing/subscriptions-data.mock.ts b/src/app/shared/testing/subscriptions-data.mock.ts index 971f69786e..191fc46252 100644 --- a/src/app/shared/testing/subscriptions-data.mock.ts +++ b/src/app/shared/testing/subscriptions-data.mock.ts @@ -4435,7 +4435,7 @@ export const findByEPersonAndDsoResEmpty = { 'page': [] }; -export const subscription = { +export const subscriptionMock = { 'id': 21, 'type': 'subscription', 'subscriptionParameterList': [ @@ -4450,18 +4450,41 @@ export const subscription = { 'value': 'M' } ], - 'subscriptionType': 'content', + 'subscriptionType': 'test1', '_links': { 'dSpaceObject': { - 'href': 'https://dspacecris7.4science.cloud/server/api/core/subscriptions/21/dSpaceObject' + 'href': 'https://dspace/server/api/core/subscriptions/21/dSpaceObject' }, 'ePerson': { - 'href': 'https://dspacecris7.4science.cloud/server/api/core/subscriptions/21/ePerson' + 'href': 'https://dspace/server/api/core/subscriptions/21/ePerson' }, 'self': { - 'href': 'https://dspacecris7.4science.cloud/server/api/core/subscriptions/21' + 'href': 'https://dspace/server/api/core/subscriptions/21' } } }; +export const subscriptionMock2 = { + 'id': 21, + 'type': 'subscription', + 'subscriptionParameterList': [ + { + 'id': 77, + 'name': 'frequency', + 'value': 'D' + }, + ], + 'subscriptionType': 'test2', + '_links': { + 'dSpaceObject': { + 'href': 'https://dspacecris7.4science.cloud/server/api/core/subscriptions/21/dSpaceObject' + }, + 'ePerson': { + 'href': 'https://dspacecris7.4science.cloud/server/api/core/subscriptions/21/ePerson' + }, + 'self': { + 'href': 'https://dspacecris7.4science.cloud/server/api/core/subscriptions/21' + } + } +}; diff --git a/src/app/subscriptions-page/subscriptions-page.component.html b/src/app/subscriptions-page/subscriptions-page.component.html index 9d1e6d504e..56e4980ca7 100644 --- a/src/app/subscriptions-page/subscriptions-page.component.html +++ b/src/app/subscriptions-page/subscriptions-page.component.html @@ -4,13 +4,12 @@

{{'subscriptions.title' | translate}}

- + @@ -25,16 +24,20 @@ - +
-
+ {{ 'subscriptions.table.empty.message' | translate }} -
+
diff --git a/src/app/subscriptions-page/subscriptions-page.component.ts b/src/app/subscriptions-page/subscriptions-page.component.ts index 2951cf037c..a99daa9d68 100644 --- a/src/app/subscriptions-page/subscriptions-page.component.ts +++ b/src/app/subscriptions-page/subscriptions-page.component.ts @@ -1,6 +1,8 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { BehaviorSubject, combineLatestWith, Observable, of, shareReplay, Subscription as rxSubscription } from 'rxjs'; -import { combineLatest, map, switchMap, take, tap } from 'rxjs/operators'; +import { Component, OnInit } from '@angular/core'; + +import { BehaviorSubject, combineLatestWith, Observable, shareReplay } from 'rxjs'; +import { map, switchMap, take, tap } from 'rxjs/operators'; + import { Subscription } from '../shared/subscriptions/models/subscription.model'; import { buildPaginatedList, PaginatedList } from '../core/data/paginated-list.model'; import { SubscriptionService } from '../shared/subscriptions/subscription.service'; @@ -16,7 +18,7 @@ import { getFirstSucceededRemoteDataPayload } from '../core/shared/operators'; templateUrl: './subscriptions-page.component.html', styleUrls: ['./subscriptions-page.component.scss'] }) -export class SubscriptionsPageComponent implements OnInit, OnDestroy { +export class SubscriptionsPageComponent implements OnInit { /** * The subscriptions to show on this page, as an Observable list. @@ -33,11 +35,6 @@ export class SubscriptionsPageComponent implements OnInit, OnDestroy { currentPage: 1 }); - /** - * Subscription to be unsubscribed - */ - sub: rxSubscription; - /** * A boolean representing if is loading */ @@ -69,7 +66,11 @@ export class SubscriptionsPageComponent implements OnInit, OnDestroy { this.ePersonId = ePersonId; }),*/ ); - const currentPagination$ = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( + this.retrieveSubscriptions(); + } + + private retrieveSubscriptions() { + this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( tap(console.log), combineLatestWith(this.ePersonId$), tap(() => {this.loading$.next(true);}), @@ -77,10 +78,12 @@ export class SubscriptionsPageComponent implements OnInit, OnDestroy { currentPage: currentPagination.currentPage, elementsPerPage: currentPagination.pageSize })), + getFirstSucceededRemoteDataPayload(), tap((x) => console.log('find', x)), // getFirstSucceededRemoteDataPayload(), ).subscribe({ next: (res: any) => { + console.log('next',res); this.subscriptions$.next(res); this.loading$.next(false); }, @@ -89,41 +92,11 @@ export class SubscriptionsPageComponent implements OnInit, OnDestroy { } }); } - /** * When an action is made and the information is changed refresh the information */ refresh(): void { - /*this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( - take(1), - switchMap((findListOptions) => { - this.loading$.next(true); - return this.subscriptionService.findByEPerson(this.ePersonId,{ - currentPage: findListOptions.currentPage, - elementsPerPage: findListOptions.pageSize - }); - } - ) - ).subscribe({ - next: (res: any) => { - this.subscriptions$.next(res); - this.loading$.next(false); - }, - error: () => { - this.loading$.next(false); - } - });*/ - } - - /** - * Unsubscribe from pagination subscription - */ - ngOnDestroy(): void { - this.sub.unsubscribe(); - } - - obs(v) { - return of(v); + this.retrieveSubscriptions(); } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 2af33eb11d..ea0c87b858 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1450,6 +1450,13 @@ "confirmation-modal.delete-profile.confirm": "Delete", + "confirmation-modal.delete-subscription.header": "Delete Subscription", + + "confirmation-modal.delete-subscription.info": "Are you sure you want to delete subscription for \"{{ dsoName }}\"", + + "confirmation-modal.delete-subscription.cancel": "Cancel", + + "confirmation-modal.delete-subscription.confirm": "Delete", "error.bitstream": "Error fetching bitstream", @@ -4512,6 +4519,20 @@ "subscriptions.frequency.W": "Weekly", + + + "subscriptions.modal.create.success": "Subscribed to {{ type }} successfully.", + + "subscriptions.modal.delete.success": "Subscription deleted successfully", + + "subscriptions.modal.update.success": "Subscription to {{ type }} updated successfully", + + "subscriptions.modal.create.error": "An error occurs during the subscription creation", + + "subscriptions.modal.delete.error": "An error occurs during the subscription delete", + + "subscriptions.modal.update.error": "An error occurs during the subscription update", + "subscriptions.table.dso": "Subject", "subscriptions.table.subscription_type": "Subscription Type",