aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared/video
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared/video')
-rw-r--r--client/src/app/shared/video/abstract-video-list.ts5
-rw-r--r--client/src/app/shared/video/videos-selection.component.html26
-rw-r--r--client/src/app/shared/video/videos-selection.component.scss57
-rw-r--r--client/src/app/shared/video/videos-selection.component.ts112
4 files changed, 200 insertions, 0 deletions
diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts
index 467f629ea..099650129 100644
--- a/client/src/app/shared/video/abstract-video-list.ts
+++ b/client/src/app/shared/video/abstract-video-list.ts
@@ -102,6 +102,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
102 ({ videos, totalVideos }) => { 102 ({ videos, totalVideos }) => {
103 this.pagination.totalItems = totalVideos 103 this.pagination.totalItems = totalVideos
104 this.videos = this.videos.concat(videos) 104 this.videos = this.videos.concat(videos)
105
106 this.onMoreVideos()
105 }, 107 },
106 108
107 error => this.notifier.error(error.message) 109 error => this.notifier.error(error.message)
@@ -118,6 +120,9 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
118 throw new Error('toggleModerationDisplay is not implemented') 120 throw new Error('toggleModerationDisplay is not implemented')
119 } 121 }
120 122
123 // On videos hook for children that want to do something
124 protected onMoreVideos () { /* empty */ }
125
121 protected loadRouteParams (routeParams: { [ key: string ]: any }) { 126 protected loadRouteParams (routeParams: { [ key: string ]: any }) {
122 this.sort = routeParams[ 'sort' ] as VideoSortField || this.defaultSort 127 this.sort = routeParams[ 'sort' ] as VideoSortField || this.defaultSort
123 this.categoryOneOf = routeParams[ 'categoryOneOf' ] 128 this.categoryOneOf = routeParams[ 'categoryOneOf' ]
diff --git a/client/src/app/shared/video/videos-selection.component.html b/client/src/app/shared/video/videos-selection.component.html
new file mode 100644
index 000000000..6f3401b4b
--- /dev/null
+++ b/client/src/app/shared/video/videos-selection.component.html
@@ -0,0 +1,26 @@
1<div class="no-results" i18n *ngIf="pagination.totalItems === 0">No results.</div>
2
3<div myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" class="videos">
4 <div class="video" *ngFor="let video of videos; let i = index">
5 <div class="checkbox-container">
6 <my-peertube-checkbox [inputName]="'video-check-' + video.id" [(ngModel)]="_selection[video.id]"></my-peertube-checkbox>
7 </div>
8
9 <my-video-miniature [video]="video" [displayAsRow]="true" [displayOptions]="miniatureDisplayOptions"></my-video-miniature>
10
11 <!-- Display only once -->
12 <div class="action-selection-mode" *ngIf="isInSelectionMode() === true && i === 0">
13 <div class="action-selection-mode-child">
14 <span i18n class="action-button action-button-cancel-selection" (click)="abortSelectionMode()">
15 Cancel
16 </span>
17
18 <ng-container *ngTemplateOutlet="globalButtonsTemplate"></ng-container>
19 </div>
20 </div>
21
22 <ng-container *ngIf="isInSelectionMode() === false">
23 <ng-container *ngTemplateOutlet="rowButtonsTemplate; context: {$implicit: video}"></ng-container>
24 </ng-container>
25 </div>
26</div>
diff --git a/client/src/app/shared/video/videos-selection.component.scss b/client/src/app/shared/video/videos-selection.component.scss
new file mode 100644
index 000000000..d3cbabf23
--- /dev/null
+++ b/client/src/app/shared/video/videos-selection.component.scss
@@ -0,0 +1,57 @@
1@import '_variables';
2@import '_mixins';
3
4.action-selection-mode {
5 display: flex;
6 justify-content: flex-end;
7 flex-grow: 1;
8
9 .action-selection-mode-child {
10 position: fixed;
11
12 .action-button {
13 display: inline-block;
14 }
15
16 .action-button-cancel-selection {
17 @include peertube-button;
18 @include grey-button;
19
20 margin-right: 10px;
21 }
22 }
23}
24
25.video {
26 @include row-blocks;
27
28 &:first-child {
29 margin-top: 47px;
30 }
31
32 .checkbox-container {
33 display: flex;
34 align-items: center;
35 margin-right: 20px;
36 margin-left: 12px;
37 }
38
39 my-video-miniature {
40 flex-grow: 1;
41 }
42}
43
44@media screen and (max-width: $small-view) {
45 .video {
46 flex-direction: column;
47 height: auto;
48
49 .checkbox-container {
50 display: none;
51 }
52
53 my-button {
54 margin-top: 10px;
55 }
56 }
57}
diff --git a/client/src/app/shared/video/videos-selection.component.ts b/client/src/app/shared/video/videos-selection.component.ts
new file mode 100644
index 000000000..b6bedafd8
--- /dev/null
+++ b/client/src/app/shared/video/videos-selection.component.ts
@@ -0,0 +1,112 @@
1import {
2 AfterContentInit,
3 Component,
4 ContentChildren,
5 EventEmitter,
6 Input,
7 OnDestroy,
8 OnInit,
9 Output,
10 QueryList,
11 TemplateRef
12} from '@angular/core'
13import { ActivatedRoute, Router } from '@angular/router'
14import { AbstractVideoList } from '@app/shared/video/abstract-video-list'
15import { AuthService, Notifier, ServerService } from '@app/core'
16import { ScreenService } from '@app/shared/misc/screen.service'
17import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.component'
18import { Observable } from 'rxjs'
19import { Video } from '@app/shared/video/video.model'
20import { PeerTubeTemplateDirective } from '@app/shared/angular/peertube-template.directive'
21import { VideoSortField } from '@app/shared/video/sort-field.type'
22
23export type SelectionType = { [ id: number ]: boolean }
24
25@Component({
26 selector: 'my-videos-selection',
27 templateUrl: './videos-selection.component.html',
28 styleUrls: [ './videos-selection.component.scss' ]
29})
30export class VideosSelectionComponent extends AbstractVideoList implements OnInit, OnDestroy, AfterContentInit {
31 @Input() titlePage: string
32 @Input() miniatureDisplayOptions: MiniatureDisplayOptions
33 @Input() getVideosObservableFunction: (page: number, sort?: VideoSortField) => Observable<{ videos: Video[], totalVideos: number }>
34 @ContentChildren(PeerTubeTemplateDirective) templates: QueryList<PeerTubeTemplateDirective>
35
36 @Output() selectionChange = new EventEmitter<SelectionType>()
37 @Output() videosModelChange = new EventEmitter<Video[]>()
38
39 _selection: SelectionType = {}
40
41 rowButtonsTemplate: TemplateRef<any>
42 globalButtonsTemplate: TemplateRef<any>
43
44 constructor (
45 protected router: Router,
46 protected route: ActivatedRoute,
47 protected notifier: Notifier,
48 protected authService: AuthService,
49 protected screenService: ScreenService,
50 protected serverService: ServerService
51 ) {
52 super()
53 }
54
55 ngAfterContentInit () {
56 {
57 const t = this.templates.find(t => t.name === 'rowButtons')
58 if (t) this.rowButtonsTemplate = t.template
59 }
60
61 {
62 const t = this.templates.find(t => t.name === 'globalButtons')
63 if (t) this.globalButtonsTemplate = t.template
64 }
65 }
66
67 @Input() get selection () {
68 return this._selection
69 }
70
71 set selection (selection: SelectionType) {
72 this._selection = selection
73 this.selectionChange.emit(this._selection)
74 }
75
76 @Input() get videosModel () {
77 return this.videos
78 }
79
80 set videosModel (videos: Video[]) {
81 this.videos = videos
82 this.videosModelChange.emit(this.videos)
83 }
84
85 ngOnInit () {
86 super.ngOnInit()
87 }
88
89 ngOnDestroy () {
90 super.ngOnDestroy()
91 }
92
93 getVideosObservable (page: number) {
94 return this.getVideosObservableFunction(page, this.sort)
95 }
96
97 abortSelectionMode () {
98 this._selection = {}
99 }
100
101 isInSelectionMode () {
102 return Object.keys(this._selection).some(k => this._selection[ k ] === true)
103 }
104
105 generateSyndicationList () {
106 throw new Error('Method not implemented.')
107 }
108
109 protected onMoreVideos () {
110 this.videosModel = this.videos
111 }
112}