Skip to content

Commit 60ac6eb

Browse files
David Florxkureck
authored andcommitted
feat(profile): url routing based on selected vo/resource
* The mailing lists segment of profile settings now allows routing via VO shortname / resource name as query parameters * By adding query parameter 'action' with values subscribe/unsubscribe user can quickly opt in and out of mailing list * Added a notification when opting in/out
1 parent 369bfd4 commit 60ac6eb

File tree

4 files changed

+159
-26
lines changed

4 files changed

+159
-26
lines changed

apps/user-profile/src/app/pages/settings-page/settings-mailing-lists/settings-mailing-lists.component.html

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ <h1 class="page-title">{{'OPT_OUT_MAILING_LISTS.TITLE' | customTranslate | trans
33
[placeholder]="'OPT_OUT_MAILING_LISTS.FILTER' | customTranslate | translate"
44
(filter)="applyFilter($event)"></perun-web-apps-immediate-filter>
55
<mat-accordion>
6-
<mat-expansion-panel *ngFor="let vo of filteredVos" (opened)="getMailingLists(vo)">
6+
<mat-expansion-panel
7+
*ngFor="let vo of filteredVos"
8+
(closed)="deselectVo()"
9+
(afterExpand)="changeSelectedVo(vo)"
10+
[expanded]="vo.shortName === selectedVo">
711
<mat-expansion-panel-header>
812
<mat-panel-title>
913
{{vo.name}}
@@ -19,18 +23,20 @@ <h1 class="page-title">{{'OPT_OUT_MAILING_LISTS.TITLE' | customTranslate | trans
1923
<mat-accordion *ngIf="resources.length && !loading">
2024
<mat-expansion-panel
2125
*ngFor="let resource of resources"
22-
(opened)="getOptOutAttribute(resource)">
26+
(closed)="deselectResource()"
27+
(afterExpand)="changeSelectedResource(resource)"
28+
[expanded]="resource.name === selectedResource">
2329
<mat-expansion-panel-header>
2430
<mat-panel-title>
2531
{{resource.name}}
2632
</mat-panel-title>
2733
</mat-expansion-panel-header>
2834
<div class="row">
29-
<p>{{'OPT_OUT_MAILING_LISTS.OPT_OUT_LABEL' | customTranslate | translate}}</p>
3035
<mat-checkbox
31-
class="ml-3"
36+
class="ml-3 mr-2"
3237
[checked]="optOutAttribute && optOutAttribute.value !== null"
3338
(change)="setOptOut()"></mat-checkbox>
39+
<p>{{'OPT_OUT_MAILING_LISTS.OPT_OUT_LABEL' | customTranslate | translate}}</p>
3440
</div>
3541
</mat-expansion-panel>
3642
</mat-accordion>

apps/user-profile/src/app/pages/settings-page/settings-mailing-lists/settings-mailing-lists.component.ts

Lines changed: 141 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, OnDestroy } from '@angular/core';
2+
import { ActivatedRoute, Router } from '@angular/router';
23
import {
34
Attribute,
45
AttributesManagerService,
@@ -10,42 +11,109 @@ import {
1011
UsersManagerService,
1112
Vo,
1213
} from '@perun-web-apps/perun/openapi';
13-
import { StoreService } from '@perun-web-apps/perun/services';
14+
import { StoreService, NotificatorService } from '@perun-web-apps/perun/services';
15+
import { TranslateService } from '@ngx-translate/core';
1416

1517
@Component({
1618
selector: 'perun-web-apps-settings-mailing-lists',
1719
templateUrl: './settings-mailing-lists.component.html',
1820
styleUrls: ['./settings-mailing-lists.component.scss'],
1921
})
20-
export class SettingsMailingListsComponent implements OnInit {
22+
export class SettingsMailingListsComponent implements OnInit, OnDestroy {
2123
user: User;
2224
vos: Vo[] = [];
2325
resources: RichResource[] = [];
24-
mailingLists: string[] = [];
2526
optOuts: InputSetMemberResourceAttribute[] = [];
2627
optOutAttribute: Attribute;
2728
index: number;
2829
filteredVos: Vo[] = [];
29-
loading: boolean;
30+
loading = true;
31+
selectedVo: string = null;
32+
selectedResource: string = null;
33+
changeOptOut: string;
3034

3135
constructor(
3236
private store: StoreService,
3337
private usersManagerService: UsersManagerService,
3438
private membersService: MembersManagerService,
3539
private resourcesManagerService: ResourcesManagerService,
36-
private attributesManagerService: AttributesManagerService
40+
private attributesManagerService: AttributesManagerService,
41+
private route: ActivatedRoute,
42+
private router: Router,
43+
private notificator: NotificatorService,
44+
private translate: TranslateService
3745
) {}
3846

47+
ngOnDestroy(): void {
48+
void this.router.navigate([], {
49+
relativeTo: this.route,
50+
queryParams: { vo: null, resource: null },
51+
replaceUrl: true,
52+
});
53+
}
54+
3955
ngOnInit(): void {
40-
this.user = this.store.getPerunPrincipal().user;
56+
this.route.queryParams
57+
.subscribe((params) => {
58+
this.selectedVo = params['vo'] as string;
59+
this.selectedResource = params['resource'] as string;
60+
this.changeOptOut = params['action'] as string;
61+
62+
this.user = this.store.getPerunPrincipal().user;
63+
64+
this.usersManagerService.getVosWhereUserIsMember(this.user.id).subscribe((vos) => {
65+
this.vos = vos;
66+
this.filteredVos = vos;
67+
if (this.selectedResource !== undefined) {
68+
const vo = this.vos.find((obj) => obj.shortName === this.selectedVo);
69+
if (vo) {
70+
this.getMailingLists(vo);
71+
}
72+
} else if (this.selectedVo !== undefined) {
73+
const vo = this.vos.find((obj) => obj.shortName === this.selectedVo);
74+
if (vo) {
75+
this.getMailingLists(vo);
76+
this.changeSelectedVo(vo);
77+
}
78+
}
79+
});
80+
})
81+
.unsubscribe();
82+
}
83+
84+
changeSelectedResource(resource: RichResource): void {
85+
if (this.selectedResource !== resource.name) {
86+
this.getOptOutAttribute(resource);
87+
}
88+
if (this.changeOptOut) {
89+
if (this.changeOptOut === 'subscribe') {
90+
this.subscribe();
91+
} else if (this.changeOptOut === 'unsubscribe') {
92+
this.unsubscribe();
93+
}
94+
this.changeOptOut = null;
95+
}
96+
void this.router.navigate([], {
97+
relativeTo: this.route,
98+
queryParams: { vo: this.selectedVo, resource: this.selectedResource, action: null },
99+
queryParamsHandling: 'merge',
100+
});
101+
}
41102

42-
this.usersManagerService.getVosWhereUserIsMember(this.user.id).subscribe((vos) => {
43-
this.vos = vos;
44-
this.filteredVos = vos;
103+
changeSelectedVo(vo: Vo): void {
104+
if (this.selectedVo !== vo.shortName) {
105+
this.getMailingLists(vo);
106+
this.selectedResource = null;
107+
}
108+
void this.router.navigate([], {
109+
relativeTo: this.route,
110+
queryParams: { vo: this.selectedVo, resource: this.selectedResource },
111+
queryParamsHandling: 'merge',
45112
});
46113
}
47114

48115
getMailingLists(vo: Vo): void {
116+
this.selectedVo = vo.shortName;
49117
this.loading = true;
50118
this.resources = [];
51119
this.membersService.getMemberByUser(vo.id, this.user.id).subscribe((member) => {
@@ -80,6 +148,10 @@ export class SettingsMailingListsComponent implements OnInit {
80148
attribute: attribute,
81149
});
82150
this.resources.push(resource);
151+
if (this.selectedResource === resource.name) {
152+
this.getOptOutAttribute(resource);
153+
this.changeSelectedResource(resource);
154+
}
83155
}
84156
this.loading = count !== 0;
85157
});
@@ -90,24 +162,75 @@ export class SettingsMailingListsComponent implements OnInit {
90162
}
91163

92164
getOptOutAttribute(resource: RichResource): void {
165+
this.selectedResource = resource.name;
93166
this.index = this.resources.indexOf(resource);
94167
this.optOutAttribute = this.optOuts[this.index].attribute;
95168
}
96169

170+
unsubscribe(): void {
171+
const originalState = this.optOuts[this.index].attribute.value;
172+
this.optOuts[this.index].attribute.value = 'true' as unknown as object;
173+
this.attributesManagerService.setMemberResourceAttribute(this.optOuts[this.index]).subscribe(
174+
() => {
175+
this.notificator.showSuccess(
176+
(this.translate.instant('OPT_OUT_MAILING_LISTS.UNSUBSCRIBED') as string) +
177+
this.selectedResource +
178+
'.'
179+
);
180+
},
181+
() => {
182+
this.optOuts[this.index].attribute.value = originalState;
183+
}
184+
);
185+
}
186+
subscribe(): void {
187+
const originalState = this.optOuts[this.index].attribute.value;
188+
this.optOuts[this.index].attribute.value = null;
189+
this.attributesManagerService.setMemberResourceAttribute(this.optOuts[this.index]).subscribe(
190+
() => {
191+
this.notificator.showSuccess(
192+
(this.translate.instant('OPT_OUT_MAILING_LISTS.SUBSCRIBED') as string) +
193+
this.selectedResource +
194+
'.'
195+
);
196+
},
197+
() => {
198+
this.optOuts[this.index].attribute.value = originalState;
199+
}
200+
);
201+
}
202+
97203
setOptOut(): void {
98-
this.optOuts[this.index].attribute.value = this.optOutAttribute.value
99-
? null
100-
: ('true' as unknown as object);
101-
this.attributesManagerService
102-
.setMemberResourceAttribute(this.optOuts[this.index])
103-
.subscribe(() => {
104-
// console.log('done');
105-
});
204+
if (this.optOutAttribute.value) {
205+
this.subscribe();
206+
} else {
207+
this.unsubscribe();
208+
}
106209
}
107210

108211
applyFilter(filter: string): void {
109212
this.filteredVos = this.vos.filter((vo) =>
110213
vo.name.toLowerCase().includes(filter.toLowerCase())
111214
);
112215
}
216+
217+
deselectVo(): void {
218+
this.loading = true;
219+
this.selectedVo = null;
220+
this.selectedResource = null;
221+
void this.router.navigate([], {
222+
relativeTo: this.route,
223+
queryParams: { vo: this.selectedVo, resource: this.selectedResource },
224+
queryParamsHandling: 'merge',
225+
});
226+
}
227+
228+
deselectResource(): void {
229+
this.selectedResource = null;
230+
void this.router.navigate([], {
231+
relativeTo: this.route,
232+
queryParams: { vo: this.selectedVo, resource: this.selectedResource },
233+
queryParamsHandling: 'merge',
234+
});
235+
}
113236
}

apps/user-profile/src/assets/i18n/cs.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,10 @@
154154
"OPT_OUT_MAILING_LISTS": {
155155
"TITLE": "Vyřazení ze seznamu adresátů",
156156
"FILTER": "Filtrovat seznamy adresátů dle jména organizace",
157-
"OPT_OUT_LABEL": "Vyřadit mě z tohoto seznamu adresátů",
158-
"NO_MAILING_LISTS_ALERT": "Nemáte žádné seznamy adresátů v této organizaci"
157+
"OPT_OUT_LABEL": "Vyřadit mě z adresátů",
158+
"NO_MAILING_LISTS_ALERT": "Nemáte žádné seznamy adresátů v této organizaci",
159+
"SUBSCRIBED": "Už nejste vyřazen z adresátů ",
160+
"UNSUBSCRIBED": "Nyní jste vyřazen z adresátů "
159161
},
160162
"AUTHENTICATION": {
161163
"TITLE": "Bezpečnostní obrázek",

apps/user-profile/src/assets/i18n/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,10 @@
154154
"OPT_OUT_MAILING_LISTS": {
155155
"TITLE": "Opt out mailing lists",
156156
"FILTER": "Filter opt out mailing lists by organization's name",
157-
"OPT_OUT_LABEL": "Exclude me from this mailing list",
158-
"NO_MAILING_LISTS_ALERT": "You have no mailing lists assigned under this virtual organization"
157+
"OPT_OUT_LABEL": "Exclude me from mailing list",
158+
"NO_MAILING_LISTS_ALERT": "You have no mailing lists assigned under this virtual organization",
159+
"SUBSCRIBED": "You are no longer excluded from the mailing list of ",
160+
"UNSUBSCRIBED": "You are now excluded from the mailing list of "
159161
},
160162
"AUTHENTICATION": {
161163
"TITLE": "Security image",

0 commit comments

Comments
 (0)