Skip to content

Commit 17fb659

Browse files
authored
Merge pull request #4283 from guillermo-escire/feature/4220
Fix button not updating label after subscription #4195
2 parents 1423c1a + 3520af9 commit 17fb659

4 files changed

Lines changed: 126 additions & 45 deletions

File tree

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,54 @@
1+
import { PLATFORM_ID } from '@angular/core';
12
import { TestBed } from '@angular/core/testing';
3+
import { AuthService } from '@dspace/core/auth/auth.service';
24
import { AuthorizationDataService } from '@dspace/core/data/feature-authorization/authorization-data.service';
5+
import { SubscriptionsDataService } from '@dspace/core/data/subscriptions-data.service';
36
import { Collection } from '@dspace/core/shared/collection.model';
47
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
8+
import { TranslateService } from '@ngx-translate/core';
59
import { of } from 'rxjs';
610

711
import { MenuItemType } from '../menu-item-type.model';
8-
import { PartialMenuSection } from '../menu-provider.model';
912
import { SubscribeMenuProvider } from './comcol-subscribe.menu';
1013

1114
describe('SubscribeMenuProvider', () => {
1215

13-
const expectedSections: PartialMenuSection[] = [
14-
{
15-
visible: true,
16-
model: {
17-
type: MenuItemType.ONCLICK,
18-
text: 'subscriptions.tooltip',
19-
function: jasmine.any(Function) as any,
20-
},
21-
icon: 'bell',
22-
},
23-
];
24-
2516
let provider: SubscribeMenuProvider;
2617

27-
const dso: Collection = Object.assign(new Collection(), { _links: { self: { href: 'self-link' } } });
28-
18+
const dso: Collection = Object.assign(new Collection(), {
19+
uuid: 'mock-uuid',
20+
_links: { self: { href: 'self-link' } },
21+
});
2922

3023
let authorizationService;
3124
let modalService;
25+
let authService;
26+
let subscriptionsDataService;
3227

3328
beforeEach(() => {
34-
3529
authorizationService = jasmine.createSpyObj('authorizationService', {
36-
'isAuthorized': of(true),
30+
isAuthorized: of(true),
3731
});
3832

3933
modalService = jasmine.createSpyObj('modalService', ['open']);
4034

35+
authService = jasmine.createSpyObj('authService', {
36+
getAuthenticatedUserFromStore: of({ id: 'mock-user-id' }),
37+
});
38+
39+
subscriptionsDataService = jasmine.createSpyObj('subscriptionsDataService', {
40+
getSubscriptionsByPersonDSO: of({ payload: { page: [] } }),
41+
});
42+
4143
TestBed.configureTestingModule({
4244
providers: [
4345
SubscribeMenuProvider,
4446
{ provide: AuthorizationDataService, useValue: authorizationService },
4547
{ provide: NgbModal, useValue: modalService },
48+
{ provide: AuthService, useValue: authService },
49+
{ provide: SubscriptionsDataService, useValue: subscriptionsDataService },
50+
{ provide: TranslateService, useValue: {} },
51+
{ provide: PLATFORM_ID, useValue: 'browser' },
4652
],
4753
});
4854
provider = TestBed.inject(SubscribeMenuProvider);
@@ -53,13 +59,32 @@ describe('SubscribeMenuProvider', () => {
5359
});
5460

5561
describe('getSectionsForContext', () => {
56-
it('should return the expected sections', (done) => {
57-
provider.getSectionsForContext(dso).subscribe((sections) => {
58-
expect(sections).toEqual(expectedSections);
59-
done();
60-
});
62+
it('should return subscribe section when user has no subscription', (done) => {
63+
provider.getSectionsForContext(dso)
64+
.pipe()
65+
.subscribe((sections) => {
66+
if (sections.length > 0 && sections[0].visible) {
67+
expect(sections[0].model.type).toBe(MenuItemType.ONCLICK);
68+
expect((sections[0].model as any).text).toBe('subscriptions.tooltip');
69+
expect(sections[0].icon).toBe('bell');
70+
done();
71+
}
72+
});
6173
});
62-
});
6374

75+
it('should return manage subscription section when user is already subscribed', (done) => {
76+
subscriptionsDataService.getSubscriptionsByPersonDSO.and.returnValue(
77+
of({ payload: { page: [{ id: 'sub-1' }] } }),
78+
);
6479

80+
provider.getSectionsForContext(dso)
81+
.pipe()
82+
.subscribe((sections) => {
83+
if (sections.length > 0 && sections[0].visible) {
84+
expect((sections[0].model as any).text).toBe('subscriptions.manage');
85+
done();
86+
}
87+
});
88+
});
89+
});
6590
});

src/app/shared/menu/providers/comcol-subscribe.menu.ts

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,32 @@
55
*
66
* http://www.dspace.org/license/
77
*/
8-
import { Injectable } from '@angular/core';
8+
import { isPlatformBrowser } from '@angular/common';
9+
import {
10+
Inject,
11+
Injectable,
12+
PLATFORM_ID,
13+
} from '@angular/core';
14+
import { AuthService } from '@dspace/core/auth/auth.service';
915
import { AuthorizationDataService } from '@dspace/core/data/feature-authorization/authorization-data.service';
1016
import { FeatureID } from '@dspace/core/data/feature-authorization/feature-id';
17+
import { SubscriptionsDataService } from '@dspace/core/data/subscriptions-data.service';
1118
import { DSpaceObject } from '@dspace/core/shared/dspace-object.model';
1219
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
20+
import { TranslateService } from '@ngx-translate/core';
1321
import {
1422
combineLatest,
1523
Observable,
24+
of,
25+
Subject,
1626
} from 'rxjs';
17-
import { map } from 'rxjs/operators';
27+
import {
28+
catchError,
29+
first,
30+
map,
31+
startWith,
32+
switchMap,
33+
} from 'rxjs/operators';
1834

1935
import { SubscriptionModalComponent } from '../../subscriptions/subscription-modal/subscription-modal.component';
2036
import { OnClickMenuItemModel } from '../menu-item/models/onclick.model';
@@ -27,33 +43,70 @@ import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu';
2743
*/
2844
@Injectable()
2945
export class SubscribeMenuProvider extends DSpaceObjectPageMenuProvider {
46+
private refresh$ = new Subject<void>();
47+
3048
constructor(
49+
protected authService: AuthService,
3150
protected authorizationService: AuthorizationDataService,
51+
protected subscriptionService: SubscriptionsDataService,
3252
protected modalService: NgbModal,
53+
protected translateService: TranslateService,
54+
@Inject(PLATFORM_ID) private platformId: unknown,
3355
) {
3456
super();
3557
}
3658

3759
public getSectionsForContext(dso: DSpaceObject): Observable<PartialMenuSection[]> {
38-
return combineLatest([
39-
this.authorizationService.isAuthorized(FeatureID.CanSubscribe, dso.self),
40-
]).pipe(
41-
map(([canSubscribe]) => {
42-
return [
43-
{
44-
visible: canSubscribe,
45-
model: {
46-
type: MenuItemType.ONCLICK,
47-
text: 'subscriptions.tooltip',
48-
function: () => {
49-
const modalRef = this.modalService.open(SubscriptionModalComponent);
50-
modalRef.componentInstance.dso = dso;
51-
},
52-
} as OnClickMenuItemModel,
53-
icon: 'bell',
54-
},
55-
] as PartialMenuSection[];
60+
if (!isPlatformBrowser(this.platformId)) {
61+
return of([]);
62+
}
63+
const sectionId = `subscribe-btn-${dso.uuid}`;
64+
65+
return this.refresh$.pipe(
66+
startWith(null),
67+
switchMap(() => combineLatest([
68+
this.authorizationService.isAuthorized(FeatureID.CanSubscribe, dso.self),
69+
this.authService.getAuthenticatedUserFromStore().pipe(first()),
70+
])),
71+
switchMap(([canSubscribe, user]) => {
72+
const baseSection = {
73+
id: sectionId,
74+
visible: false,
75+
model: null,
76+
} as PartialMenuSection;
77+
78+
if (!canSubscribe || !user) {
79+
return of([baseSection]);
80+
}
81+
82+
const openModal = () => {
83+
const modalRef = this.modalService.open(SubscriptionModalComponent);
84+
modalRef.componentInstance.dso = dso;
85+
modalRef.componentInstance.updated.subscribe(() => this.refresh$.next());
86+
};
87+
88+
return this.subscriptionService.getSubscriptionsByPersonDSO(user.id, dso.uuid).pipe(
89+
map(rd => {
90+
const subscription = rd.payload?.page?.[0];
91+
return [{
92+
...baseSection,
93+
visible: true,
94+
model: {
95+
type: MenuItemType.ONCLICK,
96+
text: subscription ? 'subscriptions.manage' : 'subscriptions.tooltip',
97+
function: openModal,
98+
} as OnClickMenuItemModel,
99+
icon: 'bell',
100+
}];
101+
}),
102+
catchError(() => of([baseSection])),
103+
);
56104
}),
105+
startWith([{
106+
id: sectionId,
107+
visible: false,
108+
model: null,
109+
} as PartialMenuSection]),
57110
);
58111
}
59112
}

src/app/shared/subscriptions/subscription-modal/subscription-modal.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ export class SubscriptionModalComponent implements OnInit {
130130
*/
131131
@Output() updateSubscription: EventEmitter<Subscription> = new EventEmitter<Subscription>();
132132

133+
@Output() updated = new EventEmitter<void>();
134+
133135
constructor(
134136
private formBuilder: UntypedFormBuilder,
135137
private modalService: NgbModal,
@@ -303,7 +305,8 @@ export class SubscriptionModalComponent implements OnInit {
303305
}
304306

305307
combineLatest([...toBeProcessed]).subscribe((res) => {
306-
this.activeModal.close();
308+
this.updated.emit();
309+
this.activeModal.close('updated');
307310
});
308311

309312
}

src/assets/i18n/en.json5

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6135,7 +6135,7 @@
61356135

61366136
"subscriptions.tooltip": "Subscribe",
61376137

6138-
"subscriptions.unsubscribe": "Unsubscribe",
6138+
"subscriptions.manage": "Manage Subscription",
61396139

61406140
"subscriptions.modal.title": "Subscriptions",
61416141

0 commit comments

Comments
 (0)