diff options
Diffstat (limited to 'client/src/app/shared/video')
4 files changed, 97 insertions, 6 deletions
diff --git a/client/src/app/shared/video/abstract-video-list.html b/client/src/app/shared/video/abstract-video-list.html index 14f48b54b..11cf1bd92 100644 --- a/client/src/app/shared/video/abstract-video-list.html +++ b/client/src/app/shared/video/abstract-video-list.html | |||
@@ -22,11 +22,18 @@ | |||
22 | myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" | 22 | myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" |
23 | class="videos" | 23 | class="videos" |
24 | > | 24 | > |
25 | <my-video-miniature | 25 | <ng-container *ngFor="let video of videos; trackBy: videoById;"> |
26 | *ngFor="let video of videos; trackBy: videoById" [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType" | 26 | <div class="date-title" *ngIf="getCurrentGroupedDateLabel(video)"> |
27 | [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions" | 27 | {{ getCurrentGroupedDateLabel(video) }} |
28 | (videoBlacklisted)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)" | 28 | </div> |
29 | > | 29 | |
30 | </my-video-miniature> | 30 | |
31 | <my-video-miniature | ||
32 | [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType" | ||
33 | [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions" | ||
34 | (videoBlacklisted)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)" | ||
35 | > | ||
36 | </my-video-miniature> | ||
37 | </ng-container> | ||
31 | </div> | 38 | </div> |
32 | </div> | 39 | </div> |
diff --git a/client/src/app/shared/video/abstract-video-list.scss b/client/src/app/shared/video/abstract-video-list.scss index d94596113..98b80fdfd 100644 --- a/client/src/app/shared/video/abstract-video-list.scss +++ b/client/src/app/shared/video/abstract-video-list.scss | |||
@@ -24,6 +24,18 @@ | |||
24 | } | 24 | } |
25 | } | 25 | } |
26 | 26 | ||
27 | .date-title { | ||
28 | font-size: 16px; | ||
29 | font-weight: $font-semibold; | ||
30 | margin-bottom: 20px; | ||
31 | margin-top: -10px; | ||
32 | padding-top: 20px; | ||
33 | |||
34 | &:not(:first-child) { | ||
35 | border-top: 1px solid $separator-border-color; | ||
36 | } | ||
37 | } | ||
38 | |||
27 | .margin-content { | 39 | .margin-content { |
28 | @include adapt-margin-content-width; | 40 | @include adapt-margin-content-width; |
29 | } | 41 | } |
diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts index fa9d38735..eba05c07d 100644 --- a/client/src/app/shared/video/abstract-video-list.ts +++ b/client/src/app/shared/video/abstract-video-list.ts | |||
@@ -11,6 +11,17 @@ import { MiniatureDisplayOptions, OwnerDisplayType } from '@app/shared/video/vid | |||
11 | import { Syndication } from '@app/shared/video/syndication.model' | 11 | import { Syndication } from '@app/shared/video/syndication.model' |
12 | import { Notifier, ServerService } from '@app/core' | 12 | import { Notifier, ServerService } from '@app/core' |
13 | import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' | 13 | import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' |
14 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
15 | import { isThisMonth, isThisWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' | ||
16 | |||
17 | enum GroupDate { | ||
18 | UNKNOWN = 0, | ||
19 | TODAY = 1, | ||
20 | YESTERDAY = 2, | ||
21 | THIS_WEEK = 3, | ||
22 | THIS_MONTH = 4, | ||
23 | OLDER = 5 | ||
24 | } | ||
14 | 25 | ||
15 | export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableForReuseHook { | 26 | export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableForReuseHook { |
16 | pagination: ComponentPagination = { | 27 | pagination: ComponentPagination = { |
@@ -31,6 +42,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
31 | displayModerationBlock = false | 42 | displayModerationBlock = false |
32 | titleTooltip: string | 43 | titleTooltip: string |
33 | displayVideoActions = true | 44 | displayVideoActions = true |
45 | groupByDate = false | ||
34 | 46 | ||
35 | disabled = false | 47 | disabled = false |
36 | 48 | ||
@@ -50,11 +62,15 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
50 | protected abstract serverService: ServerService | 62 | protected abstract serverService: ServerService |
51 | protected abstract screenService: ScreenService | 63 | protected abstract screenService: ScreenService |
52 | protected abstract router: Router | 64 | protected abstract router: Router |
65 | protected abstract i18n: I18n | ||
53 | abstract titlePage: string | 66 | abstract titlePage: string |
54 | 67 | ||
55 | private resizeSubscription: Subscription | 68 | private resizeSubscription: Subscription |
56 | private angularState: number | 69 | private angularState: number |
57 | 70 | ||
71 | private groupedDateLabels: { [id in GroupDate]: string } | ||
72 | private groupedDates: { [id: number]: GroupDate } = {} | ||
73 | |||
58 | abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number }> | 74 | abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number }> |
59 | 75 | ||
60 | abstract generateSyndicationList (): void | 76 | abstract generateSyndicationList (): void |
@@ -64,6 +80,15 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
64 | } | 80 | } |
65 | 81 | ||
66 | ngOnInit () { | 82 | ngOnInit () { |
83 | this.groupedDateLabels = { | ||
84 | [GroupDate.UNKNOWN]: null, | ||
85 | [GroupDate.TODAY]: this.i18n('Today'), | ||
86 | [GroupDate.YESTERDAY]: this.i18n('Yesterday'), | ||
87 | [GroupDate.THIS_WEEK]: this.i18n('This week'), | ||
88 | [GroupDate.THIS_MONTH]: this.i18n('This month'), | ||
89 | [GroupDate.OLDER]: this.i18n('Older') | ||
90 | } | ||
91 | |||
67 | // Subscribe to route changes | 92 | // Subscribe to route changes |
68 | const routeParams = this.route.snapshot.queryParams | 93 | const routeParams = this.route.snapshot.queryParams |
69 | this.loadRouteParams(routeParams) | 94 | this.loadRouteParams(routeParams) |
@@ -113,6 +138,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
113 | this.pagination.totalItems = totalVideos | 138 | this.pagination.totalItems = totalVideos |
114 | this.videos = this.videos.concat(videos) | 139 | this.videos = this.videos.concat(videos) |
115 | 140 | ||
141 | if (this.groupByDate) this.buildGroupedDateLabels() | ||
142 | |||
116 | this.onMoreVideos() | 143 | this.onMoreVideos() |
117 | }, | 144 | }, |
118 | 145 | ||
@@ -134,6 +161,49 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor | |||
134 | this.videos = this.videos.filter(v => v.id !== video.id) | 161 | this.videos = this.videos.filter(v => v.id !== video.id) |
135 | } | 162 | } |
136 | 163 | ||
164 | buildGroupedDateLabels () { | ||
165 | let currentGroupedDate: GroupDate = GroupDate.UNKNOWN | ||
166 | |||
167 | for (const video of this.videos) { | ||
168 | const publishedDate = video.publishedAt | ||
169 | |||
170 | if (currentGroupedDate < GroupDate.TODAY && isToday(publishedDate)) { | ||
171 | currentGroupedDate = GroupDate.TODAY | ||
172 | this.groupedDates[ video.id ] = currentGroupedDate | ||
173 | continue | ||
174 | } | ||
175 | |||
176 | if (currentGroupedDate < GroupDate.YESTERDAY && isYesterday(publishedDate)) { | ||
177 | currentGroupedDate = GroupDate.YESTERDAY | ||
178 | this.groupedDates[ video.id ] = currentGroupedDate | ||
179 | continue | ||
180 | } | ||
181 | |||
182 | if (currentGroupedDate < GroupDate.THIS_WEEK && isThisWeek(publishedDate)) { | ||
183 | currentGroupedDate = GroupDate.THIS_WEEK | ||
184 | this.groupedDates[ video.id ] = currentGroupedDate | ||
185 | continue | ||
186 | } | ||
187 | |||
188 | if (currentGroupedDate < GroupDate.THIS_MONTH && isThisMonth(publishedDate)) { | ||
189 | currentGroupedDate = GroupDate.THIS_MONTH | ||
190 | this.groupedDates[ video.id ] = currentGroupedDate | ||
191 | continue | ||
192 | } | ||
193 | |||
194 | if (currentGroupedDate < GroupDate.OLDER) { | ||
195 | currentGroupedDate = GroupDate.OLDER | ||
196 | this.groupedDates[ video.id ] = currentGroupedDate | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | getCurrentGroupedDateLabel (video: Video) { | ||
202 | if (this.groupByDate === false) return undefined | ||
203 | |||
204 | return this.groupedDateLabels[this.groupedDates[video.id]] | ||
205 | } | ||
206 | |||
137 | // On videos hook for children that want to do something | 207 | // On videos hook for children that want to do something |
138 | protected onMoreVideos () { /* empty */ } | 208 | protected onMoreVideos () { /* empty */ } |
139 | 209 | ||
diff --git a/client/src/app/shared/video/videos-selection.component.ts b/client/src/app/shared/video/videos-selection.component.ts index 955ebca9f..d69f7b70e 100644 --- a/client/src/app/shared/video/videos-selection.component.ts +++ b/client/src/app/shared/video/videos-selection.component.ts | |||
@@ -20,6 +20,7 @@ import { Video } from '@app/shared/video/video.model' | |||
20 | import { PeerTubeTemplateDirective } from '@app/shared/angular/peertube-template.directive' | 20 | import { PeerTubeTemplateDirective } from '@app/shared/angular/peertube-template.directive' |
21 | import { VideoSortField } from '@app/shared/video/sort-field.type' | 21 | import { VideoSortField } from '@app/shared/video/sort-field.type' |
22 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' | 22 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' |
23 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
23 | 24 | ||
24 | export type SelectionType = { [ id: number ]: boolean } | 25 | export type SelectionType = { [ id: number ]: boolean } |
25 | 26 | ||
@@ -44,6 +45,7 @@ export class VideosSelectionComponent extends AbstractVideoList implements OnIni | |||
44 | globalButtonsTemplate: TemplateRef<any> | 45 | globalButtonsTemplate: TemplateRef<any> |
45 | 46 | ||
46 | constructor ( | 47 | constructor ( |
48 | protected i18n: I18n, | ||
47 | protected router: Router, | 49 | protected router: Router, |
48 | protected route: ActivatedRoute, | 50 | protected route: ActivatedRoute, |
49 | protected notifier: Notifier, | 51 | protected notifier: Notifier, |