aboutsummaryrefslogtreecommitdiffhomepage
path: root/client
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2017-12-06 15:07:17 +0100
committerChocobozzz <florian.bigard@gmail.com>2017-12-06 15:07:17 +0100
commitce0e281d46a7b574dcccb47958743656532bd312 (patch)
treeb2d26aef176f39ebdf37e5e7c28d6f6fb905bf10 /client
parent7d763d97497df1bbf7a01f61aa916d99a1338a33 (diff)
downloadPeerTube-ce0e281d46a7b574dcccb47958743656532bd312.tar.gz
PeerTube-ce0e281d46a7b574dcccb47958743656532bd312.tar.zst
PeerTube-ce0e281d46a7b574dcccb47958743656532bd312.zip
Client bulk delete
Diffstat (limited to 'client')
-rw-r--r--client/src/app/account/account-videos/account-videos.component.html36
-rw-r--r--client/src/app/account/account-videos/account-videos.component.scss102
-rw-r--r--client/src/app/account/account-videos/account-videos.component.ts49
-rw-r--r--client/src/assets/images/account/delete-grey.svg (renamed from client/src/assets/images/account/delete.svg)0
-rw-r--r--client/src/assets/images/account/delete-white.svg14
-rw-r--r--client/src/sass/_mixins.scss4
-rw-r--r--client/src/sass/_variables.scss1
7 files changed, 157 insertions, 49 deletions
diff --git a/client/src/app/account/account-videos/account-videos.component.html b/client/src/app/account/account-videos/account-videos.component.html
index 30db69429..030c2f19c 100644
--- a/client/src/app/account/account-videos/account-videos.component.html
+++ b/client/src/app/account/account-videos/account-videos.component.html
@@ -5,7 +5,9 @@
5 (scrolled)="onNearOfBottom()" 5 (scrolled)="onNearOfBottom()"
6 (scrolledUp)="onNearOfTop()" 6 (scrolledUp)="onNearOfTop()"
7> 7>
8 <div class="video" *ngFor="let video of videos"> 8 <div class="video" *ngFor="let video of videos; let i = index">
9 <input type="checkbox" [(ngModel)]="checkedVideos[video.id]" />
10
9 <my-video-thumbnail [video]="video"></my-video-thumbnail> 11 <my-video-thumbnail [video]="video"></my-video-thumbnail>
10 12
11 <div class="video-info"> 13 <div class="video-info">
@@ -13,14 +15,30 @@
13 <span class="video-info-date-views">{{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span> 15 <span class="video-info-date-views">{{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
14 </div> 16 </div>
15 17
16 <a class="action-button action-button-delete" (click)="deleteVideo(video)"> 18 <!-- Display only once -->
17 <span class="icon icon-delete"></span> 19 <div class="action-selection-mode" *ngIf="isInSelectionMode() === true && i === 0">
18 Delete 20 <div class="action-selection-mode-child">
19 </a> 21 <span class="action-button" (click)="abortSelectionMode()">
22 Cancel
23 </span>
24
25 <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
26 <span class="icon icon-delete-white"></span>
27 Delete
28 </span>
29 </div>
30 </div>
31
32 <ng-template [ngIf]="isInSelectionMode() === false">
33 <span class="action-button action-button-delete" (click)="deleteVideo(video)">
34 <span class="icon icon-delete-grey"></span>
35 Delete
36 </span>
20 37
21 <a class="action-button" [routerLink]="[ '/videos', video.id, '/edit' ]"> 38 <a class="action-button" [routerLink]="[ '/videos', 'edit', video.uuid ]">
22 <span class="icon icon-edit"></span> 39 <span class="icon icon-edit"></span>
23 Edit 40 Edit
24 </a> 41 </a>
42 </ng-template>
25 </div> 43 </div>
26</div> 44</div>
diff --git a/client/src/app/account/account-videos/account-videos.component.scss b/client/src/app/account/account-videos/account-videos.component.scss
index e7fe662b1..e76e3f4e5 100644
--- a/client/src/app/account/account-videos/account-videos.component.scss
+++ b/client/src/app/account/account-videos/account-videos.component.scss
@@ -1,8 +1,74 @@
1.action-selection-mode {
2 width: 174px;
3
4 .action-selection-mode-child {
5 position: fixed;
6 }
7}
8
9.action-button {
10 @include peertube-button-link;
11
12 font-size: 15px;
13 font-weight: $font-semibold;
14 color: #585858;
15 background-color: #E5E5E5;
16
17 &:hover {
18 background-color: #EFEFEF;
19 }
20
21 &.action-button-delete {
22 margin-right: 10px;
23 }
24
25 &.action-button-delete-selection {
26 background-color: $orange-color;
27 color: #fff;
28
29 &:hover {
30 background-color: $orange-hoover-color;
31 }
32 }
33
34 .icon {
35 display: inline-block;
36 background-repeat: no-repeat;
37 background-size: contain;
38 width: 21px;
39 height: 21px;
40 vertical-align: middle;
41 position: relative;
42 top: -2px;
43
44 &.icon-edit {
45 background-image: url('../../../assets/images/account/edit.svg');
46 }
47
48 &.icon-delete-grey {
49 background-image: url('../../../assets/images/account/delete-grey.svg');
50 }
51
52 &.icon-delete-white {
53 background-image: url('../../../assets/images/account/delete-white.svg');
54 }
55 }
56}
57
1.video { 58.video {
2 display: flex; 59 display: flex;
3 height: 130px; 60 height: 130px;
4 padding-bottom: 20px; 61 padding-bottom: 20px;
5 62
63 input[type=checkbox] {
64 margin-right: 20px;
65 outline: 0;
66 }
67
68 &:first-child {
69 margin-top: 47px;
70 }
71
6 &:not(:last-child) { 72 &:not(:last-child) {
7 margin-bottom: 20px; 73 margin-bottom: 20px;
8 border-bottom: 1px solid #C6C6C6; 74 border-bottom: 1px solid #C6C6C6;
@@ -24,40 +90,4 @@
24 font-size: 13px; 90 font-size: 13px;
25 } 91 }
26 } 92 }
27
28 .action-button {
29 @include peertube-button-link;
30
31 font-size: 15px;
32 font-weight: $font-semibold;
33 color: #585858;
34 background-color: #E5E5E5;
35
36 &:hover {
37 background-color: #EFEFEF;
38 }
39
40 &.action-button-delete {
41 margin-right: 10px;
42 }
43
44 .icon.icon-edit, .icon.icon-delete {
45 display: inline-block;
46 background-repeat: no-repeat;
47 background-size: contain;
48 width: 21px;
49 height: 21px;
50 vertical-align: middle;
51 position: relative;
52 top: -2px;
53
54 &.icon-edit {
55 background-image: url('../../../assets/images/account/edit.svg');
56 }
57
58 &.icon-delete {
59 background-image: url('../../../assets/images/account/delete.svg');
60 }
61 }
62 }
63} 93}
diff --git a/client/src/app/account/account-videos/account-videos.component.ts b/client/src/app/account/account-videos/account-videos.component.ts
index 9c2cc2404..5f12cfce0 100644
--- a/client/src/app/account/account-videos/account-videos.component.ts
+++ b/client/src/app/account/account-videos/account-videos.component.ts
@@ -1,6 +1,9 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { NotificationsService } from 'angular2-notifications' 3import { NotificationsService } from 'angular2-notifications'
4import 'rxjs/add/observable/from'
5import 'rxjs/add/operator/concatAll'
6import { Observable } from 'rxjs/Observable'
4import { ConfirmService } from '../../core/confirm' 7import { ConfirmService } from '../../core/confirm'
5import { AbstractVideoList } from '../../shared/video/abstract-video-list' 8import { AbstractVideoList } from '../../shared/video/abstract-video-list'
6import { Video } from '../../shared/video/video.model' 9import { Video } from '../../shared/video/video.model'
@@ -14,6 +17,7 @@ import { VideoService } from '../../shared/video/video.service'
14export class AccountVideosComponent extends AbstractVideoList implements OnInit { 17export class AccountVideosComponent extends AbstractVideoList implements OnInit {
15 titlePage = 'My videos' 18 titlePage = 'My videos'
16 currentRoute = '/account/videos' 19 currentRoute = '/account/videos'
20 checkedVideos: { [ id: number ]: boolean } = {}
17 21
18 constructor (protected router: Router, 22 constructor (protected router: Router,
19 protected route: ActivatedRoute, 23 protected route: ActivatedRoute,
@@ -27,10 +31,47 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
27 super.ngOnInit() 31 super.ngOnInit()
28 } 32 }
29 33
34 abortSelectionMode () {
35 this.checkedVideos = {}
36 }
37
38 isInSelectionMode () {
39 return Object.keys(this.checkedVideos).some(k => this.checkedVideos[k] === true)
40 }
41
30 getVideosObservable () { 42 getVideosObservable () {
31 return this.videoService.getMyVideos(this.pagination, this.sort) 43 return this.videoService.getMyVideos(this.pagination, this.sort)
32 } 44 }
33 45
46 deleteSelectedVideos () {
47 const toDeleteVideosIds = Object.keys(this.checkedVideos)
48 .filter(k => this.checkedVideos[k] === true)
49 .map(k => parseInt(k, 10))
50
51 this.confirmService.confirm(`Do you really want to delete ${toDeleteVideosIds.length} videos?`, 'Delete').subscribe(
52 res => {
53 if (res === false) return
54
55 const observables: Observable<any>[] = []
56 for (const videoId of toDeleteVideosIds) {
57 const o = this.videoService
58 .removeVideo(videoId)
59 .do(() => this.spliceVideosById(videoId))
60
61 observables.push(o)
62 }
63
64 Observable.from(observables)
65 .concatAll()
66 .subscribe(
67 res => this.notificationsService.success('Success', `${toDeleteVideosIds.length} videos deleted.`),
68
69 err => this.notificationsService.error('Error', err.text)
70 )
71 }
72 )
73 }
74
34 deleteVideo (video: Video) { 75 deleteVideo (video: Video) {
35 this.confirmService.confirm(`Do you really want to delete ${video.name}?`, 'Delete').subscribe( 76 this.confirmService.confirm(`Do you really want to delete ${video.name}?`, 'Delete').subscribe(
36 res => { 77 res => {
@@ -40,8 +81,7 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
40 .subscribe( 81 .subscribe(
41 status => { 82 status => {
42 this.notificationsService.success('Success', `Video ${video.name} deleted.`) 83 this.notificationsService.success('Success', `Video ${video.name} deleted.`)
43 const index = this.videos.findIndex(v => v.id === video.id) 84 this.spliceVideosById(video.id)
44 this.videos.splice(index, 1)
45 }, 85 },
46 86
47 error => this.notificationsService.error('Error', error.text) 87 error => this.notificationsService.error('Error', error.text)
@@ -49,4 +89,9 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
49 } 89 }
50 ) 90 )
51 } 91 }
92
93 private spliceVideosById (id: number) {
94 const index = this.videos.findIndex(v => v.id === id)
95 this.videos.splice(index, 1)
96 }
52} 97}
diff --git a/client/src/assets/images/account/delete.svg b/client/src/assets/images/account/delete-grey.svg
index 67e9e2ce7..67e9e2ce7 100644
--- a/client/src/assets/images/account/delete.svg
+++ b/client/src/assets/images/account/delete-grey.svg
diff --git a/client/src/assets/images/account/delete-white.svg b/client/src/assets/images/account/delete-white.svg
new file mode 100644
index 000000000..9c52de557
--- /dev/null
+++ b/client/src/assets/images/account/delete-white.svg
@@ -0,0 +1,14 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3 <defs></defs>
4 <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
5 <g id="Artboard-4" transform="translate(-224.000000, -159.000000)">
6 <g id="25" transform="translate(224.000000, 159.000000)">
7 <path d="M5,7 L5,20.0081158 C5,21.1082031 5.89706013,22 7.00585866,22 L16.9941413,22 C18.1019465,22 19,21.1066027 19,20.0081158 L19,7" id="Path-296" stroke="#ffffff" stroke-width="2"></path>
8 <rect id="Rectangle-424" fill="#ffffff" x="2" y="4" width="20" height="2" rx="1"></rect>
9 <path d="M9,10.9970301 C9,10.4463856 9.44386482,10 10,10 C10.5522847,10 11,10.4530363 11,10.9970301 L11,17.0029699 C11,17.5536144 10.5561352,18 10,18 C9.44771525,18 9,17.5469637 9,17.0029699 L9,10.9970301 Z M13,10.9970301 C13,10.4463856 13.4438648,10 14,10 C14.5522847,10 15,10.4530363 15,10.9970301 L15,17.0029699 C15,17.5536144 14.5561352,18 14,18 C13.4477153,18 13,17.5469637 13,17.0029699 L13,10.9970301 Z" id="Combined-Shape" fill="#ffffff"></path>
10 <path d="M9,5 L9,2.99895656 C9,2.44724809 9.45097518,2 9.99077797,2 L14.009222,2 C14.5564136,2 15,2.44266033 15,2.99895656 L15,5" id="Path-33" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"></path>
11 </g>
12 </g>
13 </g>
14</svg>
diff --git a/client/src/sass/_mixins.scss b/client/src/sass/_mixins.scss
index 7f1063414..6a18f7a76 100644
--- a/client/src/sass/_mixins.scss
+++ b/client/src/sass/_mixins.scss
@@ -33,15 +33,15 @@
33 cursor: pointer; 33 cursor: pointer;
34 34
35 &:hover { 35 &:hover {
36 background-color: #F97D46; 36 background-color: $orange-hoover-color;
37 } 37 }
38} 38}
39 39
40@mixin peertube-button-link { 40@mixin peertube-button-link {
41 display: inline-block; 41 display: inline-block;
42 42
43 @include peertube-button;
44 @include disable-default-a-behaviour; 43 @include disable-default-a-behaviour;
44 @include peertube-button;
45} 45}
46 46
47@mixin avatar ($size) { 47@mixin avatar ($size) {
diff --git a/client/src/sass/_variables.scss b/client/src/sass/_variables.scss
index 81dafdc19..cc1cee75b 100644
--- a/client/src/sass/_variables.scss
+++ b/client/src/sass/_variables.scss
@@ -4,6 +4,7 @@ $font-bold: 700;
4 4
5$grey-color: #555; 5$grey-color: #555;
6$orange-color: #F1680D; 6$orange-color: #F1680D;
7$orange-hoover-color: #F97D46;
7 8
8$black-background: #000; 9$black-background: #000;
9$grey-background: #f6f2f2; 10$grey-background: #f6f2f2;