aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+my-account
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/+my-account')
-rw-r--r--client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts13
-rw-r--r--client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts11
-rw-r--r--client/src/app/+my-account/my-account-history/my-account-history.component.html27
-rw-r--r--client/src/app/+my-account/my-account-history/my-account-history.component.scss99
-rw-r--r--client/src/app/+my-account/my-account-history/my-account-history.component.ts107
-rw-r--r--client/src/app/+my-account/my-account-notifications/my-account-notifications.component.html13
-rw-r--r--client/src/app/+my-account/my-account-notifications/my-account-notifications.component.scss25
-rw-r--r--client/src/app/+my-account/my-account-notifications/my-account-notifications.component.ts14
-rw-r--r--client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.html3
-rw-r--r--client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.ts9
-rw-r--r--client/src/app/+my-account/my-account-ownership/my-account-ownership.component.html4
-rw-r--r--client/src/app/+my-account/my-account-ownership/my-account-ownership.component.ts15
-rw-r--r--client/src/app/+my-account/my-account-routing.module.ts20
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts7
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts8
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-notification-preferences/index.ts1
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html19
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.scss25
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts99
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts6
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-settings.component.html11
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-settings.component.ts8
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts8
-rw-r--r--client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts6
-rw-r--r--client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts9
-rw-r--r--client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts14
-rw-r--r--client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html2
-rw-r--r--client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss2
-rw-r--r--client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts21
-rw-r--r--client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.ts6
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.html6
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.scss13
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.ts20
-rw-r--r--client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.html3
-rw-r--r--client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.ts14
-rw-r--r--client/src/app/+my-account/my-account.component.html37
-rw-r--r--client/src/app/+my-account/my-account.component.scss15
-rw-r--r--client/src/app/+my-account/my-account.component.ts105
-rw-r--r--client/src/app/+my-account/my-account.module.ts12
-rw-r--r--client/src/app/+my-account/shared/actor-avatar-info.component.ts6
40 files changed, 628 insertions, 215 deletions
diff --git a/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts b/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts
index fbad28410..e3025dec4 100644
--- a/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts
+++ b/client/src/app/+my-account/my-account-blocklist/my-account-blocklist.component.ts
@@ -1,9 +1,9 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { I18n } from '@ngx-translate/i18n-polyfill' 3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared' 4import { RestPagination, RestTable } from '@app/shared'
5import { SortMeta } from 'primeng/components/common/sortmeta' 5import { SortMeta } from 'primeng/components/common/sortmeta'
6import { BlocklistService, AccountBlock } from '@app/shared/blocklist' 6import { AccountBlock, BlocklistService } from '@app/shared/blocklist'
7 7
8@Component({ 8@Component({
9 selector: 'my-account-blocklist', 9 selector: 'my-account-blocklist',
@@ -18,7 +18,7 @@ export class MyAccountBlocklistComponent extends RestTable implements OnInit {
18 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 18 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
19 19
20 constructor ( 20 constructor (
21 private notificationsService: NotificationsService, 21 private notifier: Notifier,
22 private blocklistService: BlocklistService, 22 private blocklistService: BlocklistService,
23 private i18n: I18n 23 private i18n: I18n
24 ) { 24 ) {
@@ -35,10 +35,7 @@ export class MyAccountBlocklistComponent extends RestTable implements OnInit {
35 this.blocklistService.unblockAccountByUser(blockedAccount) 35 this.blocklistService.unblockAccountByUser(blockedAccount)
36 .subscribe( 36 .subscribe(
37 () => { 37 () => {
38 this.notificationsService.success( 38 this.notifier.success(this.i18n('Account {{nameWithHost}} unmuted.', { nameWithHost: blockedAccount.nameWithHost }))
39 this.i18n('Success'),
40 this.i18n('Account {{nameWithHost}} unmuted.', { nameWithHost: blockedAccount.nameWithHost })
41 )
42 39
43 this.loadData() 40 this.loadData()
44 } 41 }
@@ -53,7 +50,7 @@ export class MyAccountBlocklistComponent extends RestTable implements OnInit {
53 this.totalRecords = resultList.total 50 this.totalRecords = resultList.total
54 }, 51 },
55 52
56 err => this.notificationsService.error(this.i18n('Error'), err.message) 53 err => this.notifier.error(err.message)
57 ) 54 )
58 } 55 }
59} 56}
diff --git a/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts b/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts
index b411d6926..4c5cc28b8 100644
--- a/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts
+++ b/client/src/app/+my-account/my-account-blocklist/my-account-server-blocklist.component.ts
@@ -1,5 +1,5 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { I18n } from '@ngx-translate/i18n-polyfill' 3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared' 4import { RestPagination, RestTable } from '@app/shared'
5import { SortMeta } from 'primeng/components/common/sortmeta' 5import { SortMeta } from 'primeng/components/common/sortmeta'
@@ -19,7 +19,7 @@ export class MyAccountServerBlocklistComponent extends RestTable implements OnIn
19 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 19 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
20 20
21 constructor ( 21 constructor (
22 private notificationsService: NotificationsService, 22 private notifier: Notifier,
23 private blocklistService: BlocklistService, 23 private blocklistService: BlocklistService,
24 private i18n: I18n 24 private i18n: I18n
25 ) { 25 ) {
@@ -36,10 +36,7 @@ export class MyAccountServerBlocklistComponent extends RestTable implements OnIn
36 this.blocklistService.unblockServerByUser(host) 36 this.blocklistService.unblockServerByUser(host)
37 .subscribe( 37 .subscribe(
38 () => { 38 () => {
39 this.notificationsService.success( 39 this.notifier.success(this.i18n('Instance {{host}} unmuted.', { host }))
40 this.i18n('Success'),
41 this.i18n('Instance {{host}} unmuted.', { host })
42 )
43 40
44 this.loadData() 41 this.loadData()
45 } 42 }
@@ -54,7 +51,7 @@ export class MyAccountServerBlocklistComponent extends RestTable implements OnIn
54 this.totalRecords = resultList.total 51 this.totalRecords = resultList.total
55 }, 52 },
56 53
57 err => this.notificationsService.error(this.i18n('Error'), err.message) 54 err => this.notifier.error(err.message)
58 ) 55 )
59 } 56 }
60} 57}
diff --git a/client/src/app/+my-account/my-account-history/my-account-history.component.html b/client/src/app/+my-account/my-account-history/my-account-history.component.html
new file mode 100644
index 000000000..d42af37d4
--- /dev/null
+++ b/client/src/app/+my-account/my-account-history/my-account-history.component.html
@@ -0,0 +1,27 @@
1<div class="top-buttons">
2 <div class="history-switch">
3 <p-inputSwitch [(ngModel)]="videosHistoryEnabled" (ngModelChange)="onVideosHistoryChange()"></p-inputSwitch>
4 <label i18n>History enabled</label>
5 </div>
6
7 <div class="delete-history">
8 <button (click)="deleteHistory()" i18n>Delete history</button>
9 </div>
10</div>
11
12
13<div class="no-history" i18n *ngIf="pagination.totalItems === 0">You don't have videos history yet.</div>
14
15<div myInfiniteScroller (nearOfBottom)="onNearOfBottom()" class="videos" #videosElement>
16 <div *ngFor="let videos of videoPages;" class="videos-page">
17 <div class="video" *ngFor="let video of videos">
18 <my-video-thumbnail [video]="video"></my-video-thumbnail>
19
20 <div class="video-info">
21 <a tabindex="-1" class="video-info-name" [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name">{{ video.name }}</a>
22 <span i18n class="video-info-date-views">{{ video.views | myNumberFormatter }} views</span>
23 <a tabindex="-1" class="video-info-account" [routerLink]="[ '/accounts', video.byAccount ]">{{ video.byAccount }}</a>
24 </div>
25 </div>
26 </div>
27</div>
diff --git a/client/src/app/+my-account/my-account-history/my-account-history.component.scss b/client/src/app/+my-account/my-account-history/my-account-history.component.scss
new file mode 100644
index 000000000..e7c6863f1
--- /dev/null
+++ b/client/src/app/+my-account/my-account-history/my-account-history.component.scss
@@ -0,0 +1,99 @@
1@import '_variables';
2@import '_mixins';
3
4.no-history {
5 display: flex;
6 justify-content: center;
7 margin-top: 50px;
8 font-weight: $font-semibold;
9 font-size: 16px;
10}
11
12.top-buttons {
13 margin-bottom: 20px;
14 display: flex;
15
16 .history-switch {
17 display: flex;
18 flex-grow: 1;
19
20 label {
21 margin: 0 0 0 5px;
22 }
23 }
24
25 .delete-history {
26 font-size: 15px;
27
28 button {
29 @include peertube-button;
30 @include grey-button;
31 }
32 }
33}
34
35.video {
36 @include row-blocks;
37
38 my-video-thumbnail {
39 margin-right: 10px;
40 }
41
42 .video-info {
43 flex-grow: 1;
44
45 .video-info-name {
46 @include disable-default-a-behaviour;
47
48 color: var(--mainForegroundColor);
49 display: block;
50 width: fit-content;
51 font-size: 18px;
52 font-weight: $font-semibold;
53 }
54
55 .video-info-date-views {
56 font-size: 14px;
57 }
58
59 .video-info-account {
60 @include disable-default-a-behaviour;
61
62 display: block;
63 width: fit-content;
64 overflow: hidden;
65 text-overflow: ellipsis;
66 white-space: nowrap;
67 font-size: 14px;
68 color: $grey-foreground-color;
69
70 &:hover {
71 color: $grey-foreground-hover-color;
72 }
73 }
74 }
75}
76
77@media screen and (max-width: $small-view) {
78 .video {
79 flex-direction: column;
80 height: auto;
81 text-align: center;
82
83 .video-info-name {
84 margin: auto;
85 }
86
87 input[type=checkbox] {
88 display: none;
89 }
90
91 my-video-thumbnail {
92 margin-right: 0;
93 }
94
95 .video-buttons {
96 margin-top: 10px;
97 }
98 }
99}
diff --git a/client/src/app/+my-account/my-account-history/my-account-history.component.ts b/client/src/app/+my-account/my-account-history/my-account-history.component.ts
new file mode 100644
index 000000000..394091bad
--- /dev/null
+++ b/client/src/app/+my-account/my-account-history/my-account-history.component.ts
@@ -0,0 +1,107 @@
1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router'
3import { Location } from '@angular/common'
4import { immutableAssign } from '@app/shared/misc/utils'
5import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
6import { AuthService } from '../../core/auth'
7import { ConfirmService } from '../../core/confirm'
8import { AbstractVideoList } from '../../shared/video/abstract-video-list'
9import { VideoService } from '../../shared/video/video.service'
10import { I18n } from '@ngx-translate/i18n-polyfill'
11import { ScreenService } from '@app/shared/misc/screen.service'
12import { UserHistoryService } from '@app/shared/users/user-history.service'
13import { UserService } from '@app/shared'
14import { Notifier } from '@app/core'
15
16@Component({
17 selector: 'my-account-history',
18 templateUrl: './my-account-history.component.html',
19 styleUrls: [ './my-account-history.component.scss' ]
20})
21export class MyAccountHistoryComponent extends AbstractVideoList implements OnInit, OnDestroy {
22 titlePage: string
23 currentRoute = '/my-account/history/videos'
24 pagination: ComponentPagination = {
25 currentPage: 1,
26 itemsPerPage: 5,
27 totalItems: null
28 }
29 videosHistoryEnabled: boolean
30
31 protected baseVideoWidth = -1
32 protected baseVideoHeight = 155
33
34 constructor (
35 protected router: Router,
36 protected route: ActivatedRoute,
37 protected authService: AuthService,
38 protected userService: UserService,
39 protected notifier: Notifier,
40 protected location: Location,
41 protected screenService: ScreenService,
42 protected i18n: I18n,
43 private confirmService: ConfirmService,
44 private videoService: VideoService,
45 private userHistoryService: UserHistoryService
46 ) {
47 super()
48
49 this.titlePage = this.i18n('My videos history')
50 }
51
52 ngOnInit () {
53 super.ngOnInit()
54
55 this.videosHistoryEnabled = this.authService.getUser().videosHistoryEnabled
56 }
57
58 ngOnDestroy () {
59 super.ngOnDestroy()
60 }
61
62 getVideosObservable (page: number) {
63 const newPagination = immutableAssign(this.pagination, { currentPage: page })
64
65 return this.userHistoryService.getUserVideosHistory(newPagination)
66 }
67
68 generateSyndicationList () {
69 throw new Error('Method not implemented.')
70 }
71
72 onVideosHistoryChange () {
73 this.userService.updateMyProfile({ videosHistoryEnabled: this.videosHistoryEnabled })
74 .subscribe(
75 () => {
76 const message = this.videosHistoryEnabled === true ?
77 this.i18n('Videos history is enabled') :
78 this.i18n('Videos history is disabled')
79
80 this.notifier.success(message)
81
82 this.authService.refreshUserInformation()
83 },
84
85 err => this.notifier.error(err.message)
86 )
87 }
88
89 async deleteHistory () {
90 const title = this.i18n('Delete videos history')
91 const message = this.i18n('Are you sure you want to delete all your videos history?')
92
93 const res = await this.confirmService.confirm(message, title)
94 if (res !== true) return
95
96 this.userHistoryService.deleteUserVideosHistory()
97 .subscribe(
98 () => {
99 this.notifier.success(this.i18n('Videos history deleted'))
100
101 this.reloadVideos()
102 },
103
104 err => this.notifier.error(err.message)
105 )
106 }
107}
diff --git a/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.html b/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.html
new file mode 100644
index 000000000..d518b22ec
--- /dev/null
+++ b/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.html
@@ -0,0 +1,13 @@
1<div class="header">
2 <a routerLink="/my-account/settings" fragment="notifications" i18n>
3 <my-global-icon iconName="cog"></my-global-icon>
4 Notification preferences
5 </a>
6
7 <button (click)="markAllAsRead()" i18n>
8 <my-global-icon iconName="circle-tick"></my-global-icon>
9 Mark all as read
10 </button>
11</div>
12
13<my-user-notifications #userNotification></my-user-notifications>
diff --git a/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.scss b/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.scss
new file mode 100644
index 000000000..43d1f82ab
--- /dev/null
+++ b/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.scss
@@ -0,0 +1,25 @@
1@import '_variables';
2@import '_mixins';
3
4.header {
5 display: flex;
6 justify-content: space-between;
7 font-size: 15px;
8 margin-bottom: 20px;
9
10 a {
11 @include peertube-button-link;
12 @include grey-button;
13 @include button-with-icon(18px, 3px, -1px);
14 }
15
16 button {
17 @include peertube-button;
18 @include grey-button;
19 @include button-with-icon(20px, 3px, -1px);
20 }
21}
22
23my-user-notifications {
24 font-size: 15px;
25}
diff --git a/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.ts b/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.ts
new file mode 100644
index 000000000..3e197088d
--- /dev/null
+++ b/client/src/app/+my-account/my-account-notifications/my-account-notifications.component.ts
@@ -0,0 +1,14 @@
1import { Component, ViewChild } from '@angular/core'
2import { UserNotificationsComponent } from '@app/shared'
3
4@Component({
5 templateUrl: './my-account-notifications.component.html',
6 styleUrls: [ './my-account-notifications.component.scss' ]
7})
8export class MyAccountNotificationsComponent {
9 @ViewChild('userNotification') userNotification: UserNotificationsComponent
10
11 markAllAsRead () {
12 this.userNotification.markAllAsRead()
13 }
14}
diff --git a/client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.html b/client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.html
index fd7d7d23b..674a4e8a2 100644
--- a/client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.html
+++ b/client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.html
@@ -1,7 +1,8 @@
1<ng-template #modal let-close="close" let-dismiss="dismiss"> 1<ng-template #modal let-close="close" let-dismiss="dismiss">
2 <div class="modal-header"> 2 <div class="modal-header">
3 <h4 i18n class="modal-title">Accept ownership</h4> 3 <h4 i18n class="modal-title">Accept ownership</h4>
4 <span class="close" aria-label="Close" role="button" (click)="dismiss()"></span> 4
5 <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="dismiss()"></my-global-icon>
5 </div> 6 </div>
6 7
7 <div class="modal-body" [formGroup]="form"> 8 <div class="modal-body" [formGroup]="form">
diff --git a/client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.ts b/client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.ts
index a68b452ec..79d29b139 100644
--- a/client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.ts
+++ b/client/src/app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component.ts
@@ -1,5 +1,5 @@
1import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core' 1import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { AuthService, Notifier } from '@app/core'
3import { FormReactive } from '@app/shared' 3import { FormReactive } from '@app/shared'
4import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' 4import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
5import { VideoOwnershipService } from '@app/shared/video-ownership' 5import { VideoOwnershipService } from '@app/shared/video-ownership'
@@ -8,7 +8,6 @@ import { VideoAcceptOwnershipValidatorsService } from '@app/shared/forms/form-va
8import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 8import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
9import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' 9import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
10import { I18n } from '@ngx-translate/i18n-polyfill' 10import { I18n } from '@ngx-translate/i18n-polyfill'
11import { AuthService } from '@app/core'
12import { NgbModal } from '@ng-bootstrap/ng-bootstrap' 11import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
13 12
14@Component({ 13@Component({
@@ -31,7 +30,7 @@ export class MyAccountAcceptOwnershipComponent extends FormReactive implements O
31 protected formValidatorService: FormValidatorService, 30 protected formValidatorService: FormValidatorService,
32 private videoChangeOwnershipValidatorsService: VideoAcceptOwnershipValidatorsService, 31 private videoChangeOwnershipValidatorsService: VideoAcceptOwnershipValidatorsService,
33 private videoOwnershipService: VideoOwnershipService, 32 private videoOwnershipService: VideoOwnershipService,
34 private notificationsService: NotificationsService, 33 private notifier: Notifier,
35 private authService: AuthService, 34 private authService: AuthService,
36 private videoChannelService: VideoChannelService, 35 private videoChannelService: VideoChannelService,
37 private modalService: NgbModal, 36 private modalService: NgbModal,
@@ -68,12 +67,12 @@ export class MyAccountAcceptOwnershipComponent extends FormReactive implements O
68 .acceptOwnership(videoChangeOwnership.id, { channelId: channel }) 67 .acceptOwnership(videoChangeOwnership.id, { channelId: channel })
69 .subscribe( 68 .subscribe(
70 () => { 69 () => {
71 this.notificationsService.success(this.i18n('Success'), this.i18n('Ownership accepted')) 70 this.notifier.success(this.i18n('Ownership accepted'))
72 if (this.accepted) this.accepted.emit() 71 if (this.accepted) this.accepted.emit()
73 this.videoChangeOwnership = undefined 72 this.videoChangeOwnership = undefined
74 }, 73 },
75 74
76 err => this.notificationsService.error(this.i18n('Error'), err.message) 75 err => this.notifier.error(err.message)
77 ) 76 )
78 } 77 }
79} 78}
diff --git a/client/src/app/+my-account/my-account-ownership/my-account-ownership.component.html b/client/src/app/+my-account/my-account-ownership/my-account-ownership.component.html
index 379fd8bb1..5709e9f54 100644
--- a/client/src/app/+my-account/my-account-ownership/my-account-ownership.component.html
+++ b/client/src/app/+my-account/my-account-ownership/my-account-ownership.component.html
@@ -40,10 +40,10 @@
40 <td class="action-cell"> 40 <td class="action-cell">
41 <ng-container *ngIf="videoChangeOwnership.status === 'WAITING'"> 41 <ng-container *ngIf="videoChangeOwnership.status === 'WAITING'">
42 <my-button i18n label="Accept" 42 <my-button i18n label="Accept"
43 icon="icon-tick" 43 icon="tick"
44 (click)="openAcceptModal(videoChangeOwnership)"></my-button> 44 (click)="openAcceptModal(videoChangeOwnership)"></my-button>
45 <my-button i18n label="Refuse" 45 <my-button i18n label="Refuse"
46 icon="icon-cross" 46 icon="cross"
47 (click)="refuse(videoChangeOwnership)">Refuse</my-button> 47 (click)="refuse(videoChangeOwnership)">Refuse</my-button>
48 </ng-container> 48 </ng-container>
49 </td> 49 </td>
diff --git a/client/src/app/+my-account/my-account-ownership/my-account-ownership.component.ts b/client/src/app/+my-account/my-account-ownership/my-account-ownership.component.ts
index 0b51ac13c..77857c4fd 100644
--- a/client/src/app/+my-account/my-account-ownership/my-account-ownership.component.ts
+++ b/client/src/app/+my-account/my-account-ownership/my-account-ownership.component.ts
@@ -1,13 +1,11 @@
1import { Component, OnInit, ViewChild } from '@angular/core' 1import { Component, OnInit, ViewChild } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { RestPagination, RestTable } from '@app/shared' 3import { RestPagination, RestTable } from '@app/shared'
5import { SortMeta } from 'primeng/components/common/sortmeta' 4import { SortMeta } from 'primeng/components/common/sortmeta'
6import { VideoChangeOwnership } from '../../../../../shared' 5import { VideoChangeOwnership } from '../../../../../shared'
7import { VideoOwnershipService } from '@app/shared/video-ownership' 6import { VideoOwnershipService } from '@app/shared/video-ownership'
8import { Account } from '@app/shared/account/account.model' 7import { Account } from '@app/shared/account/account.model'
9import { MyAccountAcceptOwnershipComponent } 8import { MyAccountAcceptOwnershipComponent } from './my-account-accept-ownership/my-account-accept-ownership.component'
10from '@app/+my-account/my-account-ownership/my-account-accept-ownership/my-account-accept-ownership.component'
11 9
12@Component({ 10@Component({
13 selector: 'my-account-ownership', 11 selector: 'my-account-ownership',
@@ -23,9 +21,8 @@ export class MyAccountOwnershipComponent extends RestTable implements OnInit {
23 @ViewChild('myAccountAcceptOwnershipComponent') myAccountAcceptOwnershipComponent: MyAccountAcceptOwnershipComponent 21 @ViewChild('myAccountAcceptOwnershipComponent') myAccountAcceptOwnershipComponent: MyAccountAcceptOwnershipComponent
24 22
25 constructor ( 23 constructor (
26 private notificationsService: NotificationsService, 24 private notifier: Notifier,
27 private videoOwnershipService: VideoOwnershipService, 25 private videoOwnershipService: VideoOwnershipService
28 private i18n: I18n
29 ) { 26 ) {
30 super() 27 super()
31 } 28 }
@@ -50,7 +47,7 @@ export class MyAccountOwnershipComponent extends RestTable implements OnInit {
50 this.videoOwnershipService.refuseOwnership(videoChangeOwnership.id) 47 this.videoOwnershipService.refuseOwnership(videoChangeOwnership.id)
51 .subscribe( 48 .subscribe(
52 () => this.loadData(), 49 () => this.loadData(),
53 err => this.notificationsService.error(this.i18n('Error'), err.message) 50 err => this.notifier.error(err.message)
54 ) 51 )
55 } 52 }
56 53
@@ -62,7 +59,7 @@ export class MyAccountOwnershipComponent extends RestTable implements OnInit {
62 this.totalRecords = resultList.total 59 this.totalRecords = resultList.total
63 }, 60 },
64 61
65 err => this.notificationsService.error(this.i18n('Error'), err.message) 62 err => this.notifier.error(err.message)
66 ) 63 )
67 } 64 }
68} 65}
diff --git a/client/src/app/+my-account/my-account-routing.module.ts b/client/src/app/+my-account/my-account-routing.module.ts
index 601e517b4..9996218ca 100644
--- a/client/src/app/+my-account/my-account-routing.module.ts
+++ b/client/src/app/+my-account/my-account-routing.module.ts
@@ -13,6 +13,8 @@ import { MyAccountSubscriptionsComponent } from '@app/+my-account/my-account-sub
13import { MyAccountOwnershipComponent } from '@app/+my-account/my-account-ownership/my-account-ownership.component' 13import { MyAccountOwnershipComponent } from '@app/+my-account/my-account-ownership/my-account-ownership.component'
14import { MyAccountBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-blocklist.component' 14import { MyAccountBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-blocklist.component'
15import { MyAccountServerBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-server-blocklist.component' 15import { MyAccountServerBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-server-blocklist.component'
16import { MyAccountHistoryComponent } from '@app/+my-account/my-account-history/my-account-history.component'
17import { MyAccountNotificationsComponent } from '@app/+my-account/my-account-notifications/my-account-notifications.component'
16 18
17const myAccountRoutes: Routes = [ 19const myAccountRoutes: Routes = [
18 { 20 {
@@ -114,6 +116,24 @@ const myAccountRoutes: Routes = [
114 title: 'Muted instances' 116 title: 'Muted instances'
115 } 117 }
116 } 118 }
119 },
120 {
121 path: 'history/videos',
122 component: MyAccountHistoryComponent,
123 data: {
124 meta: {
125 title: 'Videos history'
126 }
127 }
128 },
129 {
130 path: 'notifications',
131 component: MyAccountNotificationsComponent,
132 data: {
133 meta: {
134 title: 'Notifications'
135 }
136 }
117 } 137 }
118 ] 138 ]
119 } 139 }
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
index e5343b33d..cbb068c7c 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
@@ -1,11 +1,10 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { AuthService, Notifier } from '@app/core'
3import { FormReactive, UserService } from '../../../shared' 3import { FormReactive, UserService } from '../../../shared'
4import { I18n } from '@ngx-translate/i18n-polyfill' 4import { I18n } from '@ngx-translate/i18n-polyfill'
5import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' 5import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
6import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service' 6import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
7import { filter } from 'rxjs/operators' 7import { filter } from 'rxjs/operators'
8import { AuthService } from '@app/core'
9import { User } from '../../../../../../shared' 8import { User } from '../../../../../../shared'
10 9
11@Component({ 10@Component({
@@ -20,7 +19,7 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
20 constructor ( 19 constructor (
21 protected formValidatorService: FormValidatorService, 20 protected formValidatorService: FormValidatorService,
22 private userValidatorsService: UserValidatorsService, 21 private userValidatorsService: UserValidatorsService,
23 private notificationsService: NotificationsService, 22 private notifier: Notifier,
24 private authService: AuthService, 23 private authService: AuthService,
25 private userService: UserService, 24 private userService: UserService,
26 private i18n: I18n 25 private i18n: I18n
@@ -50,7 +49,7 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
50 49
51 this.userService.changePassword(currentPassword, newPassword).subscribe( 50 this.userService.changePassword(currentPassword, newPassword).subscribe(
52 () => { 51 () => {
53 this.notificationsService.success(this.i18n('Success'), this.i18n('Password updated.')) 52 this.notifier.success(this.i18n('Password updated.'))
54 53
55 this.form.reset() 54 this.form.reset()
56 this.error = null 55 this.error = null
diff --git a/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts b/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts
index 63a121f64..3f79efe20 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts
@@ -1,5 +1,5 @@
1import { Component, Input } from '@angular/core' 1import { Component, Input } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { AuthService, ConfirmService, RedirectService } from '../../../core' 3import { AuthService, ConfirmService, RedirectService } from '../../../core'
4import { UserService } from '../../../shared' 4import { UserService } from '../../../shared'
5import { I18n } from '@ngx-translate/i18n-polyfill' 5import { I18n } from '@ngx-translate/i18n-polyfill'
@@ -15,7 +15,7 @@ export class MyAccountDangerZoneComponent {
15 15
16 constructor ( 16 constructor (
17 private authService: AuthService, 17 private authService: AuthService,
18 private notificationsService: NotificationsService, 18 private notifier: Notifier,
19 private userService: UserService, 19 private userService: UserService,
20 private confirmService: ConfirmService, 20 private confirmService: ConfirmService,
21 private redirectService: RedirectService, 21 private redirectService: RedirectService,
@@ -34,13 +34,13 @@ export class MyAccountDangerZoneComponent {
34 34
35 this.userService.deleteMe().subscribe( 35 this.userService.deleteMe().subscribe(
36 () => { 36 () => {
37 this.notificationsService.success(this.i18n('Success'), this.i18n('Your account is deleted.')) 37 this.notifier.success(this.i18n('Your account is deleted.'))
38 38
39 this.authService.logout() 39 this.authService.logout()
40 this.redirectService.redirectToHomepage() 40 this.redirectService.redirectToHomepage()
41 }, 41 },
42 42
43 err => this.notificationsService.error(this.i18n('Error'), err.message) 43 err => this.notifier.error(err.message)
44 ) 44 )
45 } 45 }
46} 46}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/index.ts b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/index.ts
new file mode 100644
index 000000000..5e1d51339
--- /dev/null
+++ b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/index.ts
@@ -0,0 +1 @@
export * from './my-account-notification-preferences.component'
diff --git a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html
new file mode 100644
index 000000000..59422d682
--- /dev/null
+++ b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.html
@@ -0,0 +1,19 @@
1<div class="custom-row">
2 <div i18n>Activities</div>
3 <div i18n>Web</div>
4 <div i18n *ngIf="emailEnabled">Email</div>
5</div>
6
7<div class="custom-row" *ngFor="let notificationType of notificationSettingKeys">
8 <ng-container *ngIf="hasUserRight(notificationType)">
9 <div>{{ labelNotifications[notificationType] }}</div>
10
11 <div>
12 <p-inputSwitch [(ngModel)]="webNotifications[notificationType]" (onChange)="updateWebSetting(notificationType, $event.checked)"></p-inputSwitch>
13 </div>
14
15 <div *ngIf="emailEnabled">
16 <p-inputSwitch [(ngModel)]="emailNotifications[notificationType]" (onChange)="updateEmailSetting(notificationType, $event.checked)"></p-inputSwitch>
17 </div>
18 </ng-container>
19</div>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.scss b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.scss
new file mode 100644
index 000000000..6feb16ab1
--- /dev/null
+++ b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.scss
@@ -0,0 +1,25 @@
1@import '_variables';
2@import '_mixins';
3
4.custom-row {
5 display: flex;
6 align-items: center;
7 border-bottom: 1px solid rgba(0, 0, 0, 0.10);
8
9 &:first-child {
10 font-size: 16px;
11
12 & > div {
13 font-weight: $font-semibold;
14 }
15 }
16
17 & > div {
18 width: 350px;
19 }
20
21 & > div {
22 padding: 10px
23 }
24}
25
diff --git a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts
new file mode 100644
index 000000000..519bdfab4
--- /dev/null
+++ b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts
@@ -0,0 +1,99 @@
1import { Component, Input, OnInit } from '@angular/core'
2import { User } from '@app/shared'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { Subject } from 'rxjs'
5import { UserNotificationSetting, UserNotificationSettingValue, UserRight } from '../../../../../../shared'
6import { Notifier, ServerService } from '@app/core'
7import { debounce } from 'lodash-es'
8import { UserNotificationService } from '@app/shared/users/user-notification.service'
9
10@Component({
11 selector: 'my-account-notification-preferences',
12 templateUrl: './my-account-notification-preferences.component.html',
13 styleUrls: [ './my-account-notification-preferences.component.scss' ]
14})
15export class MyAccountNotificationPreferencesComponent implements OnInit {
16 @Input() user: User = null
17 @Input() userInformationLoaded: Subject<any>
18
19 notificationSettingKeys: (keyof UserNotificationSetting)[] = []
20 emailNotifications: { [ id in keyof UserNotificationSetting ]: boolean } = {} as any
21 webNotifications: { [ id in keyof UserNotificationSetting ]: boolean } = {} as any
22 labelNotifications: { [ id in keyof UserNotificationSetting ]: string } = {} as any
23 rightNotifications: { [ id in keyof Partial<UserNotificationSetting> ]: UserRight } = {} as any
24 emailEnabled: boolean
25
26 private savePreferences = debounce(this.savePreferencesImpl.bind(this), 500)
27
28 constructor (
29 private i18n: I18n,
30 private userNotificationService: UserNotificationService,
31 private serverService: ServerService,
32 private notifier: Notifier
33 ) {
34 this.labelNotifications = {
35 newVideoFromSubscription: this.i18n('New video from your subscriptions'),
36 newCommentOnMyVideo: this.i18n('New comment on your video'),
37 videoAbuseAsModerator: this.i18n('New video abuse on local video'),
38 blacklistOnMyVideo: this.i18n('One of your video is blacklisted/unblacklisted'),
39 myVideoPublished: this.i18n('Video published (after transcoding/scheduled update)'),
40 myVideoImportFinished: this.i18n('Video import finished'),
41 newUserRegistration: this.i18n('A new user registered on your instance'),
42 newFollow: this.i18n('You or your channel(s) has a new follower'),
43 commentMention: this.i18n('Someone mentioned you in video comments')
44 }
45 this.notificationSettingKeys = Object.keys(this.labelNotifications) as (keyof UserNotificationSetting)[]
46
47 this.rightNotifications = {
48 videoAbuseAsModerator: UserRight.MANAGE_VIDEO_ABUSES,
49 newUserRegistration: UserRight.MANAGE_USERS
50 }
51
52 this.emailEnabled = this.serverService.getConfig().email.enabled
53 }
54
55 ngOnInit () {
56 this.userInformationLoaded.subscribe(() => this.loadNotificationSettings())
57 }
58
59 hasUserRight (field: keyof UserNotificationSetting) {
60 const rightToHave = this.rightNotifications[field]
61 if (!rightToHave) return true // No rights needed
62
63 return this.user.hasRight(rightToHave)
64 }
65
66 updateEmailSetting (field: keyof UserNotificationSetting, value: boolean) {
67 if (value === true) this.user.notificationSettings[field] |= UserNotificationSettingValue.EMAIL
68 else this.user.notificationSettings[field] &= ~UserNotificationSettingValue.EMAIL
69
70 this.savePreferences()
71 }
72
73 updateWebSetting (field: keyof UserNotificationSetting, value: boolean) {
74 if (value === true) this.user.notificationSettings[field] |= UserNotificationSettingValue.WEB
75 else this.user.notificationSettings[field] &= ~UserNotificationSettingValue.WEB
76
77 this.savePreferences()
78 }
79
80 private savePreferencesImpl () {
81 this.userNotificationService.updateNotificationSettings(this.user, this.user.notificationSettings)
82 .subscribe(
83 () => {
84 this.notifier.success(this.i18n('Preferences saved'), undefined, 2000)
85 },
86
87 err => this.notifier.error(err.message)
88 )
89 }
90
91 private loadNotificationSettings () {
92 for (const key of Object.keys(this.user.notificationSettings)) {
93 const value = this.user.notificationSettings[key]
94 this.emailNotifications[key] = value & UserNotificationSettingValue.EMAIL
95
96 this.webNotifications[key] = value & UserNotificationSettingValue.WEB
97 }
98 }
99}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts
index 967e21f0b..a9503ed1b 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts
@@ -1,5 +1,5 @@
1import { Component, Input, OnInit } from '@angular/core' 1import { Component, Input, OnInit } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { FormReactive, UserService } from '../../../shared' 3import { FormReactive, UserService } from '../../../shared'
4import { User } from '@app/shared' 4import { User } from '@app/shared'
5import { I18n } from '@ngx-translate/i18n-polyfill' 5import { I18n } from '@ngx-translate/i18n-polyfill'
@@ -21,7 +21,7 @@ export class MyAccountProfileComponent extends FormReactive implements OnInit {
21 constructor ( 21 constructor (
22 protected formValidatorService: FormValidatorService, 22 protected formValidatorService: FormValidatorService,
23 private userValidatorsService: UserValidatorsService, 23 private userValidatorsService: UserValidatorsService,
24 private notificationsService: NotificationsService, 24 private notifier: Notifier,
25 private userService: UserService, 25 private userService: UserService,
26 private i18n: I18n 26 private i18n: I18n
27 ) { 27 ) {
@@ -53,7 +53,7 @@ export class MyAccountProfileComponent extends FormReactive implements OnInit {
53 this.user.account.displayName = displayName 53 this.user.account.displayName = displayName
54 this.user.account.description = description 54 this.user.account.description = description
55 55
56 this.notificationsService.success(this.i18n('Success'), this.i18n('Profile updated.')) 56 this.notifier.success(this.i18n('Profile updated.'))
57 }, 57 },
58 58
59 err => this.error = err.message 59 err => this.error = err.message
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-settings.component.html
index c7e23cd1f..ad64f28fe 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.html
@@ -4,10 +4,11 @@
4 <span i18n class="user-quota-label">Video quota:</span> {{ userVideoQuotaUsed | bytes: 0 }} / {{ userVideoQuota }} 4 <span i18n class="user-quota-label">Video quota:</span> {{ userVideoQuotaUsed | bytes: 0 }} / {{ userVideoQuota }}
5</div> 5</div>
6 6
7<ng-template [ngIf]="user && user.account"> 7<div i18n class="account-title">Profile</div>
8 <div i18n class="account-title">Profile</div> 8<my-account-profile [user]="user" [userInformationLoaded]="userInformationLoaded"></my-account-profile>
9 <my-account-profile [user]="user" [userInformationLoaded]="userInformationLoaded"></my-account-profile> 9
10</ng-template> 10<div i18n class="account-title" id="notifications">Notifications</div>
11<my-account-notification-preferences [user]="user" [userInformationLoaded]="userInformationLoaded"></my-account-notification-preferences>
11 12
12<div i18n class="account-title">Password</div> 13<div i18n class="account-title">Password</div>
13<my-account-change-password></my-account-change-password> 14<my-account-change-password></my-account-change-password>
@@ -16,4 +17,4 @@
16<my-account-video-settings [user]="user" [userInformationLoaded]="userInformationLoaded"></my-account-video-settings> 17<my-account-video-settings [user]="user" [userInformationLoaded]="userInformationLoaded"></my-account-video-settings>
17 18
18<div i18n class="account-title">Danger zone</div> 19<div i18n class="account-title">Danger zone</div>
19<my-account-danger-zone [user]="user"></my-account-danger-zone> \ No newline at end of file 20<my-account-danger-zone [user]="user"></my-account-danger-zone>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
index 62053d97b..f4b954e54 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
@@ -1,5 +1,5 @@
1import { Component, OnInit, ViewChild } from '@angular/core' 1import { Component, OnInit, ViewChild } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { BytesPipe } from 'ngx-pipes' 3import { BytesPipe } from 'ngx-pipes'
4import { AuthService } from '../../core' 4import { AuthService } from '../../core'
5import { User } from '../../shared' 5import { User } from '../../shared'
@@ -19,7 +19,7 @@ export class MyAccountSettingsComponent implements OnInit {
19 constructor ( 19 constructor (
20 private userService: UserService, 20 private userService: UserService,
21 private authService: AuthService, 21 private authService: AuthService,
22 private notificationsService: NotificationsService, 22 private notifier: Notifier,
23 private i18n: I18n 23 private i18n: I18n
24 ) {} 24 ) {}
25 25
@@ -48,12 +48,12 @@ export class MyAccountSettingsComponent implements OnInit {
48 this.userService.changeAvatar(formData) 48 this.userService.changeAvatar(formData)
49 .subscribe( 49 .subscribe(
50 data => { 50 data => {
51 this.notificationsService.success(this.i18n('Success'), this.i18n('Avatar changed.')) 51 this.notifier.success(this.i18n('Avatar changed.'))
52 52
53 this.user.updateAccountAvatar(data.avatar) 53 this.user.updateAccountAvatar(data.avatar)
54 }, 54 },
55 55
56 err => this.notificationsService.error(this.i18n('Error'), err.message) 56 err => this.notifier.error(err.message)
57 ) 57 )
58 } 58 }
59} 59}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
index 6c9a7ce75..b8f80bc1a 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
@@ -1,5 +1,5 @@
1import { Component, Input, OnInit } from '@angular/core' 1import { Component, Input, OnInit } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { UserUpdateMe } from '../../../../../../shared' 3import { UserUpdateMe } from '../../../../../../shared'
4import { AuthService } from '../../../core' 4import { AuthService } from '../../../core'
5import { FormReactive, User, UserService } from '../../../shared' 5import { FormReactive, User, UserService } from '../../../shared'
@@ -19,7 +19,7 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
19 constructor ( 19 constructor (
20 protected formValidatorService: FormValidatorService, 20 protected formValidatorService: FormValidatorService,
21 private authService: AuthService, 21 private authService: AuthService,
22 private notificationsService: NotificationsService, 22 private notifier: Notifier,
23 private userService: UserService, 23 private userService: UserService,
24 private i18n: I18n 24 private i18n: I18n
25 ) { 25 ) {
@@ -54,12 +54,12 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
54 54
55 this.userService.updateMyProfile(details).subscribe( 55 this.userService.updateMyProfile(details).subscribe(
56 () => { 56 () => {
57 this.notificationsService.success(this.i18n('Success'), this.i18n('Information updated.')) 57 this.notifier.success(this.i18n('Information updated.'))
58 58
59 this.authService.refreshUserInformation() 59 this.authService.refreshUserInformation()
60 }, 60 },
61 61
62 err => this.notificationsService.error(this.i18n('Error'), err.message) 62 err => this.notifier.error(err.message)
63 ) 63 )
64 } 64 }
65} 65}
diff --git a/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts b/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts
index 9517a3705..9d2dccdf0 100644
--- a/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts
+++ b/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts
@@ -1,5 +1,5 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 3import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
4import { I18n } from '@ngx-translate/i18n-polyfill' 4import { I18n } from '@ngx-translate/i18n-polyfill'
5import { UserSubscriptionService } from '@app/shared/user-subscription' 5import { UserSubscriptionService } from '@app/shared/user-subscription'
@@ -21,7 +21,7 @@ export class MyAccountSubscriptionsComponent implements OnInit {
21 21
22 constructor ( 22 constructor (
23 private userSubscriptionService: UserSubscriptionService, 23 private userSubscriptionService: UserSubscriptionService,
24 private notificationsService: NotificationsService, 24 private notifier: Notifier,
25 private i18n: I18n 25 private i18n: I18n
26 ) {} 26 ) {}
27 27
@@ -37,7 +37,7 @@ export class MyAccountSubscriptionsComponent implements OnInit {
37 this.pagination.totalItems = res.total 37 this.pagination.totalItems = res.total
38 }, 38 },
39 39
40 error => this.notificationsService.error(this.i18n('Error'), error.message) 40 error => this.notifier.error(error.message)
41 ) 41 )
42 } 42 }
43 43
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts
index 81608d837..a68f79b47 100644
--- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts
+++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts
@@ -1,10 +1,9 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { Router } from '@angular/router' 2import { Router } from '@angular/router'
3import { NotificationsService } from 'angular2-notifications' 3import { AuthService, Notifier } from '@app/core'
4import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit' 4import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
5import { VideoChannelCreate } from '../../../../../shared/models/videos' 5import { VideoChannelCreate } from '../../../../../shared/models/videos'
6import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' 6import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
7import { AuthService } from '@app/core'
8import { I18n } from '@ngx-translate/i18n-polyfill' 7import { I18n } from '@ngx-translate/i18n-polyfill'
9import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' 8import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
10import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service' 9import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service'
@@ -21,7 +20,7 @@ export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelE
21 protected formValidatorService: FormValidatorService, 20 protected formValidatorService: FormValidatorService,
22 private authService: AuthService, 21 private authService: AuthService,
23 private videoChannelValidatorsService: VideoChannelValidatorsService, 22 private videoChannelValidatorsService: VideoChannelValidatorsService,
24 private notificationsService: NotificationsService, 23 private notifier: Notifier,
25 private router: Router, 24 private router: Router,
26 private videoChannelService: VideoChannelService, 25 private videoChannelService: VideoChannelService,
27 private i18n: I18n 26 private i18n: I18n
@@ -56,8 +55,8 @@ export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelE
56 this.videoChannelService.createVideoChannel(videoChannelCreate).subscribe( 55 this.videoChannelService.createVideoChannel(videoChannelCreate).subscribe(
57 () => { 56 () => {
58 this.authService.refreshUserInformation() 57 this.authService.refreshUserInformation()
59 this.notificationsService.success( 58
60 this.i18n('Success'), 59 this.notifier.success(
61 this.i18n('Video channel {{videoChannelName}} created.', { videoChannelName: videoChannelCreate.displayName }) 60 this.i18n('Video channel {{videoChannelName}} created.', { videoChannelName: videoChannelCreate.displayName })
62 ) 61 )
63 this.router.navigate([ '/my-account', 'video-channels' ]) 62 this.router.navigate([ '/my-account', 'video-channels' ])
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts
index 5d43956f2..da4fb645a 100644
--- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts
+++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts
@@ -1,12 +1,11 @@
1import { Component, OnDestroy, OnInit } from '@angular/core' 1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { NotificationsService } from 'angular2-notifications' 3import { AuthService, Notifier, ServerService } from '@app/core'
4import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit' 4import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
5import { VideoChannelUpdate } from '../../../../../shared/models/videos' 5import { VideoChannelUpdate } from '../../../../../shared/models/videos'
6import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' 6import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
7import { Subscription } from 'rxjs' 7import { Subscription } from 'rxjs'
8import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 8import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
9import { AuthService, ServerService } from '@app/core'
10import { I18n } from '@ngx-translate/i18n-polyfill' 9import { I18n } from '@ngx-translate/i18n-polyfill'
11import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' 10import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
12import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service' 11import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators/video-channel-validators.service'
@@ -26,7 +25,7 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE
26 protected formValidatorService: FormValidatorService, 25 protected formValidatorService: FormValidatorService,
27 private authService: AuthService, 26 private authService: AuthService,
28 private videoChannelValidatorsService: VideoChannelValidatorsService, 27 private videoChannelValidatorsService: VideoChannelValidatorsService,
29 private notificationsService: NotificationsService, 28 private notifier: Notifier,
30 private router: Router, 29 private router: Router,
31 private route: ActivatedRoute, 30 private route: ActivatedRoute,
32 private videoChannelService: VideoChannelService, 31 private videoChannelService: VideoChannelService,
@@ -79,10 +78,11 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE
79 this.videoChannelService.updateVideoChannel(this.videoChannelToUpdate.name, videoChannelUpdate).subscribe( 78 this.videoChannelService.updateVideoChannel(this.videoChannelToUpdate.name, videoChannelUpdate).subscribe(
80 () => { 79 () => {
81 this.authService.refreshUserInformation() 80 this.authService.refreshUserInformation()
82 this.notificationsService.success( 81
83 this.i18n('Success'), 82 this.notifier.success(
84 this.i18n('Video channel {{videoChannelName}} updated.', { videoChannelName: videoChannelUpdate.displayName }) 83 this.i18n('Video channel {{videoChannelName}} updated.', { videoChannelName: videoChannelUpdate.displayName })
85 ) 84 )
85
86 this.router.navigate([ '/my-account', 'video-channels' ]) 86 this.router.navigate([ '/my-account', 'video-channels' ])
87 }, 87 },
88 88
@@ -94,12 +94,12 @@ export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelE
94 this.videoChannelService.changeVideoChannelAvatar(this.videoChannelToUpdate.name, formData) 94 this.videoChannelService.changeVideoChannelAvatar(this.videoChannelToUpdate.name, formData)
95 .subscribe( 95 .subscribe(
96 data => { 96 data => {
97 this.notificationsService.success(this.i18n('Success'), this.i18n('Avatar changed.')) 97 this.notifier.success(this.i18n('Avatar changed.'))
98 98
99 this.videoChannelToUpdate.updateAvatar(data.avatar) 99 this.videoChannelToUpdate.updateAvatar(data.avatar)
100 }, 100 },
101 101
102 err => this.notificationsService.error(this.i18n('Error'), err.message) 102 err => this.notifier.error(err.message)
103 ) 103 )
104 } 104 }
105 105
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html
index df74b19b6..51db2e75d 100644
--- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html
+++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html
@@ -1,6 +1,6 @@
1<div class="video-channels-header"> 1<div class="video-channels-header">
2 <a class="create-button" routerLink="create"> 2 <a class="create-button" routerLink="create">
3 <span class="icon icon-add"></span> 3 <my-global-icon iconName="add"></my-global-icon>
4 <ng-container i18n>Create another video channel</ng-container> 4 <ng-container i18n>Create another video channel</ng-container>
5 </a> 5 </a>
6</div> 6</div>
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss
index 472cbb723..77fce138b 100644
--- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss
+++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss
@@ -2,7 +2,7 @@
2@import '_mixins'; 2@import '_mixins';
3 3
4.create-button { 4.create-button {
5 @include create-button('../../../assets/images/global/add.svg'); 5 @include create-button;
6} 6}
7 7
8/deep/ .action-button { 8/deep/ .action-button {
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts
index 6d1098865..da2c5bcd3 100644
--- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts
+++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts
@@ -1,5 +1,5 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { AuthService } from '../../core/auth' 3import { AuthService } from '../../core/auth'
4import { ConfirmService } from '../../core/confirm' 4import { ConfirmService } from '../../core/confirm'
5import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 5import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
@@ -20,7 +20,7 @@ export class MyAccountVideoChannelsComponent implements OnInit {
20 20
21 constructor ( 21 constructor (
22 private authService: AuthService, 22 private authService: AuthService,
23 private notificationsService: NotificationsService, 23 private notifier: Notifier,
24 private confirmService: ConfirmService, 24 private confirmService: ConfirmService,
25 private videoChannelService: VideoChannelService, 25 private videoChannelService: VideoChannelService,
26 private i18n: I18n 26 private i18n: I18n
@@ -35,10 +35,14 @@ export class MyAccountVideoChannelsComponent implements OnInit {
35 async deleteVideoChannel (videoChannel: VideoChannel) { 35 async deleteVideoChannel (videoChannel: VideoChannel) {
36 const res = await this.confirmService.confirmWithInput( 36 const res = await this.confirmService.confirmWithInput(
37 this.i18n( 37 this.i18n(
38 'Do you really want to delete {{videoChannelName}}? It will delete all videos uploaded in this channel too.', 38 'Do you really want to delete {{channelDisplayName}}? It will delete all videos uploaded in this channel, ' +
39 { videoChannelName: videoChannel.displayName } 39 'and you will not be able to create another channel with the same name ({{channelName}})!',
40 { channelDisplayName: videoChannel.displayName, channelName: videoChannel.name }
41 ),
42 this.i18n(
43 'Please type the display name of the video channel ({{displayName}}) to confirm',
44 { displayName: videoChannel.displayName }
40 ), 45 ),
41 this.i18n('Please type the name of the video channel to confirm'),
42 videoChannel.displayName, 46 videoChannel.displayName,
43 this.i18n('Delete') 47 this.i18n('Delete')
44 ) 48 )
@@ -46,15 +50,14 @@ export class MyAccountVideoChannelsComponent implements OnInit {
46 50
47 this.videoChannelService.removeVideoChannel(videoChannel) 51 this.videoChannelService.removeVideoChannel(videoChannel)
48 .subscribe( 52 .subscribe(
49 status => { 53 () => {
50 this.loadVideoChannels() 54 this.loadVideoChannels()
51 this.notificationsService.success( 55 this.notifier.success(
52 this.i18n('Success'),
53 this.i18n('Video channel {{videoChannelName}} deleted.', { videoChannelName: videoChannel.displayName }) 56 this.i18n('Video channel {{videoChannelName}} deleted.', { videoChannelName: videoChannel.displayName })
54 ) 57 )
55 }, 58 },
56 59
57 error => this.notificationsService.error(this.i18n('Error'), error.message) 60 error => this.notifier.error(error.message)
58 ) 61 )
59 } 62 }
60 63
diff --git a/client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.ts b/client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.ts
index 5b920c98d..21a10c8ff 100644
--- a/client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.ts
+++ b/client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.ts
@@ -1,7 +1,7 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { RestPagination, RestTable } from '@app/shared' 2import { RestPagination, RestTable } from '@app/shared'
3import { SortMeta } from 'primeng/components/common/sortmeta' 3import { SortMeta } from 'primeng/components/common/sortmeta'
4import { NotificationsService } from 'angular2-notifications' 4import { Notifier } from '@app/core'
5import { I18n } from '@ngx-translate/i18n-polyfill' 5import { I18n } from '@ngx-translate/i18n-polyfill'
6import { VideoImport, VideoImportState } from '../../../../../shared/models/videos' 6import { VideoImport, VideoImportState } from '../../../../../shared/models/videos'
7import { VideoImportService } from '@app/shared/video-import' 7import { VideoImportService } from '@app/shared/video-import'
@@ -19,7 +19,7 @@ export class MyAccountVideoImportsComponent extends RestTable implements OnInit
19 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 19 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
20 20
21 constructor ( 21 constructor (
22 private notificationsService: NotificationsService, 22 private notifier: Notifier,
23 private videoImportService: VideoImportService, 23 private videoImportService: VideoImportService,
24 private i18n: I18n 24 private i18n: I18n
25 ) { 25 ) {
@@ -58,7 +58,7 @@ export class MyAccountVideoImportsComponent extends RestTable implements OnInit
58 this.totalRecords = resultList.total 58 this.totalRecords = resultList.total
59 }, 59 },
60 60
61 err => this.notificationsService.error(this.i18n('Error'), err.message) 61 err => this.notifier.error(err.message)
62 ) 62 )
63 } 63 }
64} 64}
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
index a6911e4bf..69748ef37 100644
--- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
@@ -32,7 +32,7 @@
32 </span> 32 </span>
33 33
34 <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()"> 34 <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
35 <span class="icon icon-delete-white"></span> 35 <my-global-icon iconName="delete"></my-global-icon>
36 <ng-container i18n>Delete</ng-container> 36 <ng-container i18n>Delete</ng-container>
37 </span> 37 </span>
38 </div> 38 </div>
@@ -45,7 +45,7 @@
45 45
46 <my-button i18n-label label="Change ownership" 46 <my-button i18n-label label="Change ownership"
47 className="action-button-change-ownership" 47 className="action-button-change-ownership"
48 icon="icon-im-with-her" 48 icon="im-with-her"
49 (click)="changeOwnership($event, video)" 49 (click)="changeOwnership($event, video)"
50 ></my-button> 50 ></my-button>
51 </div> 51 </div>
@@ -53,4 +53,4 @@
53 </div> 53 </div>
54</div> 54</div>
55 55
56<my-video-change-ownership #videoChangeOwnershipModal></my-video-change-ownership> \ No newline at end of file 56<my-video-change-ownership #videoChangeOwnershipModal></my-video-change-ownership>
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
index 2db81a3fe..39d0cf2f7 100644
--- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
@@ -23,14 +23,11 @@
23 .action-button-delete-selection { 23 .action-button-delete-selection {
24 @include peertube-button; 24 @include peertube-button;
25 @include orange-button; 25 @include orange-button;
26 } 26 @include button-with-icon(21px);
27
28 .icon.icon-delete-white {
29 @include icon(21px);
30 27
31 position: relative; 28 my-global-icon {
32 top: -2px; 29 @include apply-svg-color(#fff);
33 background-image: url('../../../assets/images/global/delete-white.svg'); 30 }
34 } 31 }
35 } 32 }
36} 33}
@@ -97,7 +94,7 @@
97 } 94 }
98} 95}
99 96
100@media screen and (max-width: 800px) { 97@media screen and (max-width: $small-view) {
101 .video { 98 .video {
102 flex-direction: column; 99 flex-direction: column;
103 height: auto; 100 height: auto;
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts b/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
index 2d88ac760..41608f796 100644
--- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
@@ -5,7 +5,7 @@ import { ActivatedRoute, Router } from '@angular/router'
5import { Location } from '@angular/common' 5import { Location } from '@angular/common'
6import { immutableAssign } from '@app/shared/misc/utils' 6import { immutableAssign } from '@app/shared/misc/utils'
7import { ComponentPagination } from '@app/shared/rest/component-pagination.model' 7import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
8import { NotificationsService } from 'angular2-notifications' 8import { Notifier } from '@app/core'
9import { AuthService } from '../../core/auth' 9import { AuthService } from '../../core/auth'
10import { ConfirmService } from '../../core/confirm' 10import { ConfirmService } from '../../core/confirm'
11import { AbstractVideoList } from '../../shared/video/abstract-video-list' 11import { AbstractVideoList } from '../../shared/video/abstract-video-list'
@@ -40,7 +40,7 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
40 protected router: Router, 40 protected router: Router,
41 protected route: ActivatedRoute, 41 protected route: ActivatedRoute,
42 protected authService: AuthService, 42 protected authService: AuthService,
43 protected notificationsService: NotificationsService, 43 protected notifier: Notifier,
44 protected location: Location, 44 protected location: Location,
45 protected screenService: ScreenService, 45 protected screenService: ScreenService,
46 protected i18n: I18n, 46 protected i18n: I18n,
@@ -102,16 +102,13 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
102 .pipe(concatAll()) 102 .pipe(concatAll())
103 .subscribe( 103 .subscribe(
104 res => { 104 res => {
105 this.notificationsService.success( 105 this.notifier.success(this.i18n('{{deleteLength}} videos deleted.', { deleteLength: toDeleteVideosIds.length }))
106 this.i18n('Success'),
107 this.i18n('{{deleteLength}} videos deleted.', { deleteLength: toDeleteVideosIds.length })
108 )
109 106
110 this.abortSelectionMode() 107 this.abortSelectionMode()
111 this.reloadVideos() 108 this.reloadVideos()
112 }, 109 },
113 110
114 err => this.notificationsService.error(this.i18n('Error'), err.message) 111 err => this.notifier.error(err.message)
115 ) 112 )
116 } 113 }
117 114
@@ -124,15 +121,12 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
124 121
125 this.videoService.removeVideo(video.id) 122 this.videoService.removeVideo(video.id)
126 .subscribe( 123 .subscribe(
127 status => { 124 () => {
128 this.notificationsService.success( 125 this.notifier.success(this.i18n('Video {{videoName}} deleted.', { videoName: video.name }))
129 this.i18n('Success'),
130 this.i18n('Video {{videoName}} deleted.', { videoName: video.name })
131 )
132 this.reloadVideos() 126 this.reloadVideos()
133 }, 127 },
134 128
135 error => this.notificationsService.error(this.i18n('Error'), error.message) 129 error => this.notifier.error(error.message)
136 ) 130 )
137 } 131 }
138 132
diff --git a/client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.html b/client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.html
index 7c0df850d..22f127904 100644
--- a/client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.html
+++ b/client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.html
@@ -1,7 +1,8 @@
1<ng-template #modal let-close="close" let-dismiss="dismiss"> 1<ng-template #modal let-close="close" let-dismiss="dismiss">
2 <div class="modal-header"> 2 <div class="modal-header">
3 <h4 i18n class="modal-title">Change ownership</h4> 3 <h4 i18n class="modal-title">Change ownership</h4>
4 <span class="close" aria-label="Close" role="button" (click)="dismiss()"></span> 4
5 <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="dismiss()"></my-global-icon>
5 </div> 6 </div>
6 7
7 <div class="modal-body" [formGroup]="form"> 8 <div class="modal-body" [formGroup]="form">
diff --git a/client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.ts b/client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.ts
index 9f94f3c13..37d7cf2a4 100644
--- a/client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.ts
+++ b/client/src/app/+my-account/my-account-videos/video-change-ownership/video-change-ownership.component.ts
@@ -1,5 +1,5 @@
1import { Component, ElementRef, OnInit, ViewChild } from '@angular/core' 1import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'
2import { NotificationsService } from 'angular2-notifications' 2import { Notifier } from '@app/core'
3import { NgbModal } from '@ng-bootstrap/ng-bootstrap' 3import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
4import { FormReactive, UserService } from '../../../shared/index' 4import { FormReactive, UserService } from '../../../shared/index'
5import { Video } from '@app/shared/video/video.model' 5import { Video } from '@app/shared/video/video.model'
@@ -25,7 +25,7 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
25 protected formValidatorService: FormValidatorService, 25 protected formValidatorService: FormValidatorService,
26 private videoChangeOwnershipValidatorsService: VideoChangeOwnershipValidatorsService, 26 private videoChangeOwnershipValidatorsService: VideoChangeOwnershipValidatorsService,
27 private videoOwnershipService: VideoOwnershipService, 27 private videoOwnershipService: VideoOwnershipService,
28 private notificationsService: NotificationsService, 28 private notifier: Notifier,
29 private userService: UserService, 29 private userService: UserService,
30 private modalService: NgbModal, 30 private modalService: NgbModal,
31 private i18n: I18n 31 private i18n: I18n
@@ -53,11 +53,9 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
53 const query = event.query 53 const query = event.query
54 this.userService.autocomplete(query) 54 this.userService.autocomplete(query)
55 .subscribe( 55 .subscribe(
56 usernames => { 56 usernames => this.usernamePropositions = usernames,
57 this.usernamePropositions = usernames
58 },
59 57
60 err => this.notificationsService.error('Error', err.message) 58 err => this.notifier.error(err.message)
61 ) 59 )
62 } 60 }
63 61
@@ -67,9 +65,9 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
67 this.videoOwnershipService 65 this.videoOwnershipService
68 .changeOwnership(this.video.id, username) 66 .changeOwnership(this.video.id, username)
69 .subscribe( 67 .subscribe(
70 () => this.notificationsService.success(this.i18n('Success'), this.i18n('Ownership change request sent.')), 68 () => this.notifier.success(this.i18n('Ownership change request sent.')),
71 69
72 err => this.notificationsService.error(this.i18n('Error'), err.message) 70 err => this.notifier.error(err.message)
73 ) 71 )
74 } 72 }
75} 73}
diff --git a/client/src/app/+my-account/my-account.component.html b/client/src/app/+my-account/my-account.component.html
index 41333c25a..3999252be 100644
--- a/client/src/app/+my-account/my-account.component.html
+++ b/client/src/app/+my-account/my-account.component.html
@@ -1,40 +1,5 @@
1<div class="row"> 1<div class="row">
2 <div class="sub-menu"> 2 <my-top-menu-dropdown [menuEntries]="menuEntries"></my-top-menu-dropdown>
3 <a i18n routerLink="/my-account/settings" routerLinkActive="active" class="title-page">My settings</a>
4
5 <div ngbDropdown class="my-library">
6 <span role="button" class="title-page" [ngClass]="{ active: libraryLabel !== '' }" ngbDropdownToggle>
7 <ng-container i18n>My library</ng-container>
8 <ng-container *ngIf="libraryLabel"> - {{ libraryLabel }}</ng-container>
9 </span>
10
11 <div ngbDropdownMenu>
12 <a class="dropdown-item" i18n routerLink="/my-account/video-channels">My channels</a>
13
14 <a class="dropdown-item" i18n routerLink="/my-account/videos">My videos</a>
15
16 <a class="dropdown-item" i18n routerLink="/my-account/subscriptions">My subscriptions</a>
17
18 <a class="dropdown-item" *ngIf="isVideoImportEnabled()" i18n routerLink="/my-account/video-imports">My imports</a>
19 </div>
20 </div>
21
22 <div ngbDropdown class="misc">
23 <span role="button" class="title-page" [ngClass]="{ active: miscLabel !== '' }" ngbDropdownToggle>
24 <ng-container i18n>Misc</ng-container>
25 <ng-container *ngIf="miscLabel"> - {{ miscLabel }}</ng-container>
26 </span>
27
28 <div ngbDropdownMenu>
29 <a class="dropdown-item" i18n routerLink="/my-account/blocklist/accounts">Muted accounts</a>
30
31 <a class="dropdown-item" i18n routerLink="/my-account/blocklist/servers">Muted instances</a>
32
33 <a class="dropdown-item" i18n routerLink="/my-account/ownership">Ownership changes</a>
34 </div>
35 </div>
36
37 </div>
38 3
39 <div class="margin-content"> 4 <div class="margin-content">
40 <router-outlet></router-outlet> 5 <router-outlet></router-outlet>
diff --git a/client/src/app/+my-account/my-account.component.scss b/client/src/app/+my-account/my-account.component.scss
index 6243c6dcf..4f111efdf 100644
--- a/client/src/app/+my-account/my-account.component.scss
+++ b/client/src/app/+my-account/my-account.component.scss
@@ -1,14 +1,3 @@
1.my-library, .misc { 1.row {
2 span[role=button] { 2 flex-direction: column;
3 cursor: pointer;
4 }
5
6 a {
7 display: block;
8 }
9} 3}
10
11/deep/ .dropdown-toggle::after {
12 position: relative;
13 top: 2px;
14} \ No newline at end of file
diff --git a/client/src/app/+my-account/my-account.component.ts b/client/src/app/+my-account/my-account.component.ts
index d728caf07..8a4102d80 100644
--- a/client/src/app/+my-account/my-account.component.ts
+++ b/client/src/app/+my-account/my-account.component.ts
@@ -1,38 +1,80 @@
1import { Component, OnDestroy, OnInit } from '@angular/core' 1import { Component } from '@angular/core'
2import { ServerService } from '@app/core' 2import { ServerService } from '@app/core'
3import { NavigationStart, Router } from '@angular/router'
4import { filter } from 'rxjs/operators'
5import { I18n } from '@ngx-translate/i18n-polyfill' 3import { I18n } from '@ngx-translate/i18n-polyfill'
6import { Subscription } from 'rxjs' 4import { TopMenuDropdownParam } from '@app/shared/menu/top-menu-dropdown.component'
7 5
8@Component({ 6@Component({
9 selector: 'my-my-account', 7 selector: 'my-my-account',
10 templateUrl: './my-account.component.html', 8 templateUrl: './my-account.component.html',
11 styleUrls: [ './my-account.component.scss' ] 9 styleUrls: [ './my-account.component.scss' ]
12}) 10})
13export class MyAccountComponent implements OnInit, OnDestroy { 11export class MyAccountComponent {
14 12 menuEntries: TopMenuDropdownParam[] = []
15 libraryLabel = ''
16 miscLabel = ''
17
18 private routeSub: Subscription
19 13
20 constructor ( 14 constructor (
21 private serverService: ServerService, 15 private serverService: ServerService,
22 private router: Router,
23 private i18n: I18n 16 private i18n: I18n
24 ) {} 17 ) {
18
19 const libraryEntries: TopMenuDropdownParam = {
20 label: this.i18n('My library'),
21 children: [
22 {
23 label: this.i18n('My channels'),
24 routerLink: '/my-account/video-channels'
25 },
26 {
27 label: this.i18n('My videos'),
28 routerLink: '/my-account/videos'
29 },
30 {
31 label: this.i18n('My subscriptions'),
32 routerLink: '/my-account/subscriptions'
33 },
34 {
35 label: this.i18n('My history'),
36 routerLink: '/my-account/history/videos'
37 }
38 ]
39 }
25 40
26 ngOnInit () { 41 if (this.isVideoImportEnabled()) {
27 this.updateLabels(this.router.url) 42 libraryEntries.children.push({
43 label: 'My imports',
44 routerLink: '/my-account/video-imports'
45 })
46 }
28 47
29 this.routeSub = this.router.events 48 const miscEntries: TopMenuDropdownParam = {
30 .pipe(filter(event => event instanceof NavigationStart)) 49 label: this.i18n('Misc'),
31 .subscribe((event: NavigationStart) => this.updateLabels(event.url)) 50 children: [
32 } 51 {
52 label: this.i18n('Muted accounts'),
53 routerLink: '/my-account/blocklist/accounts'
54 },
55 {
56 label: this.i18n('Muted instances'),
57 routerLink: '/my-account/blocklist/servers'
58 },
59 {
60 label: this.i18n('Ownership changes'),
61 routerLink: '/my-account/ownership'
62 }
63 ]
64 }
33 65
34 ngOnDestroy () { 66 this.menuEntries = [
35 if (this.routeSub) this.routeSub.unsubscribe() 67 {
68 label: this.i18n('My settings'),
69 routerLink: '/my-account/settings'
70 },
71 {
72 label: this.i18n('My notifications'),
73 routerLink: '/my-account/notifications'
74 },
75 libraryEntries,
76 miscEntries
77 ]
36 } 78 }
37 79
38 isVideoImportEnabled () { 80 isVideoImportEnabled () {
@@ -41,27 +83,4 @@ export class MyAccountComponent implements OnInit, OnDestroy {
41 return importConfig.http.enabled || importConfig.torrent.enabled 83 return importConfig.http.enabled || importConfig.torrent.enabled
42 } 84 }
43 85
44 private updateLabels (url: string) {
45 const [ path ] = url.split('?')
46
47 if (path.startsWith('/my-account/video-channels')) {
48 this.libraryLabel = this.i18n('Channels')
49 } else if (path.startsWith('/my-account/videos')) {
50 this.libraryLabel = this.i18n('Videos')
51 } else if (path.startsWith('/my-account/subscriptions')) {
52 this.libraryLabel = this.i18n('Subscriptions')
53 } else if (path.startsWith('/my-account/video-imports')) {
54 this.libraryLabel = this.i18n('Video imports')
55 } else {
56 this.libraryLabel = ''
57 }
58
59 if (path.startsWith('/my-account/blocklist/accounts')) {
60 this.miscLabel = this.i18n('Muted accounts')
61 } else if (path.startsWith('/my-account/blocklist/servers')) {
62 this.miscLabel = this.i18n('Muted instances')
63 } else {
64 this.miscLabel = ''
65 }
66 }
67} 86}
diff --git a/client/src/app/+my-account/my-account.module.ts b/client/src/app/+my-account/my-account.module.ts
index 017ebd57d..18f51f171 100644
--- a/client/src/app/+my-account/my-account.module.ts
+++ b/client/src/app/+my-account/my-account.module.ts
@@ -1,6 +1,7 @@
1import { TableModule } from 'primeng/table' 1import { TableModule } from 'primeng/table'
2import { NgModule } from '@angular/core' 2import { NgModule } from '@angular/core'
3import { AutoCompleteModule } from 'primeng/autocomplete' 3import { AutoCompleteModule } from 'primeng/autocomplete'
4import { InputSwitchModule } from 'primeng/inputswitch'
4import { SharedModule } from '../shared' 5import { SharedModule } from '../shared'
5import { MyAccountRoutingModule } from './my-account-routing.module' 6import { MyAccountRoutingModule } from './my-account-routing.module'
6import { MyAccountChangePasswordComponent } from './my-account-settings/my-account-change-password/my-account-change-password.component' 7import { MyAccountChangePasswordComponent } from './my-account-settings/my-account-change-password/my-account-change-password.component'
@@ -21,6 +22,9 @@ import { MyAccountDangerZoneComponent } from '@app/+my-account/my-account-settin
21import { MyAccountSubscriptionsComponent } from '@app/+my-account/my-account-subscriptions/my-account-subscriptions.component' 22import { MyAccountSubscriptionsComponent } from '@app/+my-account/my-account-subscriptions/my-account-subscriptions.component'
22import { MyAccountBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-blocklist.component' 23import { MyAccountBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-blocklist.component'
23import { MyAccountServerBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-server-blocklist.component' 24import { MyAccountServerBlocklistComponent } from '@app/+my-account/my-account-blocklist/my-account-server-blocklist.component'
25import { MyAccountHistoryComponent } from '@app/+my-account/my-account-history/my-account-history.component'
26import { MyAccountNotificationsComponent } from '@app/+my-account/my-account-notifications/my-account-notifications.component'
27import { MyAccountNotificationPreferencesComponent } from '@app/+my-account/my-account-settings/my-account-notification-preferences'
24 28
25@NgModule({ 29@NgModule({
26 imports: [ 30 imports: [
@@ -28,7 +32,8 @@ import { MyAccountServerBlocklistComponent } from '@app/+my-account/my-account-b
28 MyAccountRoutingModule, 32 MyAccountRoutingModule,
29 AutoCompleteModule, 33 AutoCompleteModule,
30 SharedModule, 34 SharedModule,
31 TableModule 35 TableModule,
36 InputSwitchModule
32 ], 37 ],
33 38
34 declarations: [ 39 declarations: [
@@ -49,7 +54,10 @@ import { MyAccountServerBlocklistComponent } from '@app/+my-account/my-account-b
49 MyAccountDangerZoneComponent, 54 MyAccountDangerZoneComponent,
50 MyAccountSubscriptionsComponent, 55 MyAccountSubscriptionsComponent,
51 MyAccountBlocklistComponent, 56 MyAccountBlocklistComponent,
52 MyAccountServerBlocklistComponent 57 MyAccountServerBlocklistComponent,
58 MyAccountHistoryComponent,
59 MyAccountNotificationsComponent,
60 MyAccountNotificationPreferencesComponent
53 ], 61 ],
54 62
55 exports: [ 63 exports: [
diff --git a/client/src/app/+my-account/shared/actor-avatar-info.component.ts b/client/src/app/+my-account/shared/actor-avatar-info.component.ts
index 54bacc212..72c815a0c 100644
--- a/client/src/app/+my-account/shared/actor-avatar-info.component.ts
+++ b/client/src/app/+my-account/shared/actor-avatar-info.component.ts
@@ -1,8 +1,8 @@
1import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core' 1import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'
2import { ServerService } from '../../core/server' 2import { ServerService } from '../../core/server'
3import { NotificationsService } from 'angular2-notifications'
4import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 3import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
5import { Account } from '@app/shared/account/account.model' 4import { Account } from '@app/shared/account/account.model'
5import { Notifier } from '@app/core'
6 6
7@Component({ 7@Component({
8 selector: 'my-actor-avatar-info', 8 selector: 'my-actor-avatar-info',
@@ -18,13 +18,13 @@ export class ActorAvatarInfoComponent {
18 18
19 constructor ( 19 constructor (
20 private serverService: ServerService, 20 private serverService: ServerService,
21 private notificationsService: NotificationsService 21 private notifier: Notifier
22 ) {} 22 ) {}
23 23
24 onAvatarChange () { 24 onAvatarChange () {
25 const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ] 25 const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ]
26 if (avatarfile.size > this.maxAvatarSize) { 26 if (avatarfile.size > this.maxAvatarSize) {
27 this.notificationsService.error('Error', 'This image is too large.') 27 this.notifier.error('Error', 'This image is too large.')
28 return 28 return
29 } 29 }
30 30