Add ability to disable and clear history
This commit is contained in:
parent
80bfd33c0b
commit
276d965295
11 changed files with 163 additions and 55 deletions
|
@ -1,4 +1,16 @@
|
|||
<div i18n *ngIf="pagination.totalItems === 0">You don't have history yet.</div>
|
||||
<div class="top-buttons">
|
||||
<div class="history-switch">
|
||||
<p-inputSwitch [(ngModel)]="videosHistoryEnabled" (ngModelChange)="onVideosHistoryChange()"></p-inputSwitch>
|
||||
<label i18n>History enabled</label>
|
||||
</div>
|
||||
|
||||
<div class="delete-history">
|
||||
<button (click)="deleteHistory()" i18n>Delete history</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="no-history" i18n *ngIf="pagination.totalItems === 0">You don't have videos history yet.</div>
|
||||
|
||||
<div myInfiniteScroller (nearOfBottom)="onNearOfBottom()" class="videos" #videosElement>
|
||||
<div *ngFor="let videos of videoPages;" class="videos-page">
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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<ServerUserModel>, hashTokens: TokenOptions) {
|
||||
super(userHash)
|
||||
this.tokens = new Tokens(hashTokens)
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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<UserServerModel>) {
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,14 +45,18 @@ p-table {
|
|||
}
|
||||
|
||||
tr {
|
||||
outline: 0;
|
||||
background-color: var(--mainBackgroundColor) !important;
|
||||
height: 46px;
|
||||
|
||||
&.ui-state-highlight {
|
||||
background-color: var(--submenuColor) !important;
|
||||
|
||||
td, td > a {
|
||||
color: var(--mainForegroundColor) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ui-table-tbody {
|
||||
tr {
|
||||
|
@ -56,6 +70,10 @@ p-table {
|
|||
}
|
||||
}
|
||||
|
||||
td {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
&:first-child td {
|
||||
border-top: none !important;
|
||||
}
|
||||
|
@ -98,9 +116,9 @@ p-table {
|
|||
.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);
|
||||
|
@ -259,3 +293,9 @@ p-calendar .ui-datepicker {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
p-inputswitch {
|
||||
.ui-inputswitch-checked .ui-inputswitch-slider {
|
||||
background-color: var(--mainColor) !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,6 +370,7 @@ export class UserModel extends Model<UserModel> {
|
|||
emailVerified: this.emailVerified,
|
||||
nsfwPolicy: this.nsfwPolicy,
|
||||
webTorrentEnabled: this.webTorrentEnabled,
|
||||
videosHistoryEnabled: this.videosHistoryEnabled,
|
||||
autoPlayVideo: this.autoPlayVideo,
|
||||
role: this.role,
|
||||
roleLabel: USER_ROLE_LABELS[ this.role ],
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue