From 276d96529529621d5f70473990095495f2743c29 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 18 Dec 2018 11:32:37 +0100 Subject: [PATCH] Add ability to disable and clear history --- .../my-account-history.component.html | 14 +++- .../my-account-history.component.scss | 31 +++++++++ .../my-account-history.component.ts | 41 +++++++++++ .../src/app/+my-account/my-account.module.ts | 4 +- client/src/app/core/auth/auth-user.model.ts | 10 ++- .../app/core/routing/login-guard.service.ts | 8 +-- client/src/app/shared/users/user.model.ts | 33 ++------- .../video-upload.component.scss | 4 +- client/src/sass/primeng-custom.scss | 68 +++++++++++++++---- server/models/account/user.ts | 1 + shared/models/users/user.model.ts | 4 ++ 11 files changed, 163 insertions(+), 55 deletions(-) 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 index 653b33f89..d42af37d4 100644 --- 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 @@ -1,4 +1,16 @@ -
You don't have history yet.
+
+
+ + +
+ +
+ +
+
+ + +
You don't have videos history yet.
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 index 115bb0e5c..82150cbe3 100644 --- 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 @@ -1,6 +1,37 @@ @import '_variables'; @import '_mixins'; +.no-history { + display: flex; + justify-content: center; + margin-top: 50px; + font-weight: $font-semibold; + font-size: 16px; +} + +.top-buttons { + margin-bottom: 20px; + display: flex; + + .history-switch { + display: flex; + flex-grow: 1; + + label { + margin: 0 0 0 5px; + } + } + + .delete-history { + font-size: 15px; + + button { + @include peertube-button; + @include grey-button; + } + } +} + .video { @include row-blocks; 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 index 508552167..6ec4fefe8 100644 --- 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 @@ -11,6 +11,7 @@ import { VideoService } from '../../shared/video/video.service' import { I18n } from '@ngx-translate/i18n-polyfill' import { ScreenService } from '@app/shared/misc/screen.service' import { UserHistoryService } from '@app/shared/users/user-history.service' +import { UserService } from '@app/shared' @Component({ selector: 'my-account-history', @@ -25,6 +26,7 @@ export class MyAccountHistoryComponent extends AbstractVideoList implements OnIn itemsPerPage: 5, totalItems: null } + videosHistoryEnabled: boolean protected baseVideoWidth = -1 protected baseVideoHeight = 155 @@ -33,6 +35,7 @@ export class MyAccountHistoryComponent extends AbstractVideoList implements OnIn protected router: Router, protected route: ActivatedRoute, protected authService: AuthService, + protected userService: UserService, protected notificationsService: NotificationsService, protected location: Location, protected screenService: ScreenService, @@ -48,6 +51,8 @@ export class MyAccountHistoryComponent extends AbstractVideoList implements OnIn ngOnInit () { super.ngOnInit() + + this.videosHistoryEnabled = this.authService.getUser().videosHistoryEnabled } ngOnDestroy () { @@ -63,4 +68,40 @@ export class MyAccountHistoryComponent extends AbstractVideoList implements OnIn generateSyndicationList () { throw new Error('Method not implemented.') } + + onVideosHistoryChange () { + this.userService.updateMyProfile({ videosHistoryEnabled: this.videosHistoryEnabled }) + .subscribe( + () => { + const message = this.videosHistoryEnabled === true ? + this.i18n('Videos history is enabled') : + this.i18n('Videos history is disabled') + + this.notificationsService.success(this.i18n('Success'), message) + + this.authService.refreshUserInformation() + }, + + err => this.notificationsService.error(this.i18n('Error'), err.message) + ) + } + + async deleteHistory () { + const title = this.i18n('Delete videos history') + const message = this.i18n('Are you sure you want to delete all your videos history?') + + const res = await this.confirmService.confirm(message, title) + if (res !== true) return + + this.userHistoryService.deleteUserVideosHistory() + .subscribe( + () => { + this.notificationsService.success(this.i18n('Success'), this.i18n('Videos history deleted')) + + this.reloadVideos() + }, + + err => this.notificationsService.error(this.i18n('Error'), err.message) + ) + } } diff --git a/client/src/app/+my-account/my-account.module.ts b/client/src/app/+my-account/my-account.module.ts index c05406438..80d9f0cf7 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 @@ import { TableModule } from 'primeng/table' import { NgModule } from '@angular/core' import { AutoCompleteModule } from 'primeng/autocomplete' +import { InputSwitchModule } from 'primeng/inputswitch' import { SharedModule } from '../shared' import { MyAccountRoutingModule } from './my-account-routing.module' import { MyAccountChangePasswordComponent } from './my-account-settings/my-account-change-password/my-account-change-password.component' @@ -29,7 +30,8 @@ import { MyAccountHistoryComponent } from '@app/+my-account/my-account-history/m MyAccountRoutingModule, AutoCompleteModule, SharedModule, - TableModule + TableModule, + InputSwitchModule ], declarations: [ diff --git a/client/src/app/core/auth/auth-user.model.ts b/client/src/app/core/auth/auth-user.model.ts index acd13d9c5..abb11fdc2 100644 --- a/client/src/app/core/auth/auth-user.model.ts +++ b/client/src/app/core/auth/auth-user.model.ts @@ -1,8 +1,9 @@ import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' import { UserRight } from '../../../../../shared/models/users/user-right.enum' +import { User as ServerUserModel } from '../../../../../shared/models/users/user.model' // Do not use the barrel (dependency loop) import { hasUserRight, UserRole } from '../../../../../shared/models/users/user-role' -import { User, UserConstructorHash } from '../../shared/users/user.model' +import { User } from '../../shared/users/user.model' import { NSFWPolicyType } from '../../../../../shared/models/videos/nsfw-policy.type' export type TokenOptions = { @@ -70,6 +71,7 @@ export class AuthUser extends User { ID: 'id', ROLE: 'role', EMAIL: 'email', + VIDEOS_HISTORY_ENABLED: 'videos-history-enabled', USERNAME: 'username', NSFW_POLICY: 'nsfw_policy', WEBTORRENT_ENABLED: 'peertube-videojs-' + 'webtorrent_enabled', @@ -89,7 +91,8 @@ export class AuthUser extends User { role: parseInt(peertubeLocalStorage.getItem(this.KEYS.ROLE), 10) as UserRole, nsfwPolicy: peertubeLocalStorage.getItem(this.KEYS.NSFW_POLICY) as NSFWPolicyType, webTorrentEnabled: peertubeLocalStorage.getItem(this.KEYS.WEBTORRENT_ENABLED) === 'true', - autoPlayVideo: peertubeLocalStorage.getItem(this.KEYS.AUTO_PLAY_VIDEO) === 'true' + autoPlayVideo: peertubeLocalStorage.getItem(this.KEYS.AUTO_PLAY_VIDEO) === 'true', + videosHistoryEnabled: peertubeLocalStorage.getItem(this.KEYS.VIDEOS_HISTORY_ENABLED) === 'true' }, Tokens.load() ) @@ -104,12 +107,13 @@ export class AuthUser extends User { peertubeLocalStorage.removeItem(this.KEYS.ROLE) peertubeLocalStorage.removeItem(this.KEYS.NSFW_POLICY) peertubeLocalStorage.removeItem(this.KEYS.WEBTORRENT_ENABLED) + peertubeLocalStorage.removeItem(this.KEYS.VIDEOS_HISTORY_ENABLED) peertubeLocalStorage.removeItem(this.KEYS.AUTO_PLAY_VIDEO) peertubeLocalStorage.removeItem(this.KEYS.EMAIL) Tokens.flush() } - constructor (userHash: UserConstructorHash, hashTokens: TokenOptions) { + constructor (userHash: Partial, hashTokens: TokenOptions) { super(userHash) this.tokens = new Tokens(hashTokens) } diff --git a/client/src/app/core/routing/login-guard.service.ts b/client/src/app/core/routing/login-guard.service.ts index 18bc41ca6..7b1c37ee8 100644 --- a/client/src/app/core/routing/login-guard.service.ts +++ b/client/src/app/core/routing/login-guard.service.ts @@ -1,11 +1,5 @@ import { Injectable } from '@angular/core' -import { - ActivatedRouteSnapshot, - CanActivateChild, - RouterStateSnapshot, - CanActivate, - Router -} from '@angular/router' +import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router, RouterStateSnapshot } from '@angular/router' import { AuthService } from '../auth/auth.service' diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts index 9819829fd..3663a7b61 100644 --- a/client/src/app/shared/users/user.model.ts +++ b/client/src/app/shared/users/user.model.ts @@ -1,33 +1,8 @@ -import { - Account as AccountServerModel, - hasUserRight, - User as UserServerModel, - UserRight, - UserRole, - VideoChannel -} from '../../../../../shared' +import { hasUserRight, User as UserServerModel, UserRight, UserRole, VideoChannel } from '../../../../../shared' import { NSFWPolicyType } from '../../../../../shared/models/videos/nsfw-policy.type' import { Account } from '@app/shared/account/account.model' import { Avatar } from '../../../../../shared/models/avatars/avatar.model' -export type UserConstructorHash = { - id: number, - username: string, - email: string, - role: UserRole, - emailVerified?: boolean, - videoQuota?: number, - videoQuotaDaily?: number, - nsfwPolicy?: NSFWPolicyType, - webTorrentEnabled?: boolean, - autoPlayVideo?: boolean, - createdAt?: Date, - account?: AccountServerModel, - videoChannels?: VideoChannel[] - - blocked?: boolean - blockedReason?: string -} export class User implements UserServerModel { id: number username: string @@ -35,8 +10,11 @@ export class User implements UserServerModel { emailVerified: boolean role: UserRole nsfwPolicy: NSFWPolicyType + webTorrentEnabled: boolean autoPlayVideo: boolean + videosHistoryEnabled: boolean + videoQuota: number videoQuotaDaily: number account: Account @@ -46,7 +24,7 @@ export class User implements UserServerModel { blocked: boolean blockedReason?: string - constructor (hash: UserConstructorHash) { + constructor (hash: Partial) { this.id = hash.id this.username = hash.username this.email = hash.email @@ -57,6 +35,7 @@ export class User implements UserServerModel { this.videoQuotaDaily = hash.videoQuotaDaily this.nsfwPolicy = hash.nsfwPolicy this.webTorrentEnabled = hash.webTorrentEnabled + this.videosHistoryEnabled = hash.videosHistoryEnabled this.autoPlayVideo = hash.autoPlayVideo this.createdAt = hash.createdAt this.blocked = hash.blocked diff --git a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.scss b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.scss index cf1725ef9..4b2c86ae9 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.scss +++ b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.scss @@ -54,9 +54,7 @@ /deep/ .ui-progressbar { font-size: 15px !important; - color: #fff !important; height: 30px !important; - line-height: 30px !important; border-radius: 3px !important; background-color: rgba(11, 204, 41, 0.16) !important; @@ -68,6 +66,8 @@ text-align: left; padding-left: 18px; margin-top: 0 !important; + color: #fff !important; + line-height: 30px !important; } } diff --git a/client/src/sass/primeng-custom.scss b/client/src/sass/primeng-custom.scss index 0568de4e2..1d6eebcfa 100644 --- a/client/src/sass/primeng-custom.scss +++ b/client/src/sass/primeng-custom.scss @@ -2,7 +2,7 @@ @import '_mixins'; @import '~primeng/resources/primeng.css'; -@import '~primeng/resources/themes/bootstrap/theme.css'; +@import '~primeng/resources/themes/nova-light/theme.css'; @mixin glyphicon-light { font-family: 'Glyphicons Halflings'; @@ -12,10 +12,9 @@ // data table customizations p-table { - font-size: 15px !important; - .ui-table-caption { - border: none; + border: none !important; + background-color: #fff !important; .caption { height: 40px; @@ -24,6 +23,17 @@ p-table { } } + th { + background-color: #fff !important; + outline: 0; + } + + td, th { + font-family: $main-fonts; + font-size: 15px !important; + color: var(--mainForegroundColor) !important; + } + td { padding-left: 15px !important; @@ -35,12 +45,16 @@ p-table { } tr { + outline: 0; background-color: var(--mainBackgroundColor) !important; height: 46px; &.ui-state-highlight { - background-color:var(--submenuColor) !important; - color:var(--mainForegroundColor) !important; + background-color: var(--submenuColor) !important; + + td, td > a { + color: var(--mainForegroundColor) !important; + } } } @@ -56,6 +70,10 @@ p-table { } } + td { + border: none !important; + } + &:first-child td { border-top: none !important; } @@ -93,14 +111,14 @@ p-table { } &.ui-state-highlight { - background-color:var(--submenuColor) !important; + background-color: var(--submenuColor) !important; .pi { @extend .glyphicon; - color: #000; - font-size: 11px; - top: 0; + color: #000 !important; + font-size: 11px !important; + top: 0 !important; &.pi-sort-up { @extend .glyphicon-triangle-top; @@ -177,11 +195,12 @@ p-table { a { color: #000 !important; font-weight: $font-semibold !important; - margin: 0 10px !important; + margin: 0 5px !important; outline: 0 !important; border-radius: 3px !important; padding: 5px 2px !important; height: auto !important; + line-height: initial !important; &.ui-state-active { &, &:hover, &:active, &:focus { @@ -210,11 +229,23 @@ p-calendar .ui-datepicker { .ui-datepicker-next { @extend .glyphicon-chevron-right; @include glyphicon-light; + + text-align: right; + + .pi.pi-chevron-right { + display: none !important; + } } .ui-datepicker-prev { @extend .glyphicon-chevron-left; @include glyphicon-light; + + text-align: left; + + .pi.pi-chevron-left { + display: none !important; + } } } @@ -232,6 +263,7 @@ p-calendar .ui-datepicker { } } + .ui-chkbox-box { &.ui-state-active { border-color: var(--mainColor) !important; @@ -240,13 +272,15 @@ p-calendar .ui-datepicker { .ui-chkbox-icon { position: relative; + overflow: visible !important; &:after { content: ''; position: absolute; - left: 5px; + top: 1px; + left: 7px; width: 5px; - height: 12px; + height: 13px; opacity: 0; transform: rotate(45deg) scale(0); border-right: 2px solid var(--mainBackgroundColor); @@ -258,4 +292,10 @@ p-calendar .ui-datepicker { transform: rotate(45deg) scale(1); } } -} \ No newline at end of file +} + +p-inputswitch { + .ui-inputswitch-checked .ui-inputswitch-slider { + background-color: var(--mainColor) !important; + } +} diff --git a/server/models/account/user.ts b/server/models/account/user.ts index ea017c338..180ced810 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts @@ -370,6 +370,7 @@ export class UserModel extends Model { emailVerified: this.emailVerified, nsfwPolicy: this.nsfwPolicy, webTorrentEnabled: this.webTorrentEnabled, + videosHistoryEnabled: this.videosHistoryEnabled, autoPlayVideo: this.autoPlayVideo, role: this.role, roleLabel: USER_ROLE_LABELS[ this.role ], diff --git a/shared/models/users/user.model.ts b/shared/models/users/user.model.ts index 82af17516..2aabff494 100644 --- a/shared/models/users/user.model.ts +++ b/shared/models/users/user.model.ts @@ -9,7 +9,11 @@ export interface User { email: string emailVerified: boolean nsfwPolicy: NSFWPolicyType + autoPlayVideo: boolean + webTorrentEnabled: boolean + videosHistoryEnabled: boolean + role: UserRole videoQuota: number videoQuotaDaily: number