From 34c7f429e411fb911dfa56a816b638fd665717a4 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 31 May 2019 11:14:38 +0200 Subject: Group videos on chronological order --- .../src/app/shared/video/abstract-video-list.html | 19 ++++-- .../src/app/shared/video/abstract-video-list.scss | 12 ++++ client/src/app/shared/video/abstract-video-list.ts | 70 ++++++++++++++++++++++ .../app/shared/video/videos-selection.component.ts | 2 + 4 files changed, 97 insertions(+), 6 deletions(-) (limited to 'client/src/app/shared/video') 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 @@ myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" class="videos" > - - + +
+ {{ getCurrentGroupedDateLabel(video) }} +
+ + + + +
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 @@ } } +.date-title { + font-size: 16px; + font-weight: $font-semibold; + margin-bottom: 20px; + margin-top: -10px; + padding-top: 20px; + + &:not(:first-child) { + border-top: 1px solid $separator-border-color; + } +} + .margin-content { @include adapt-margin-content-width; } 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 import { Syndication } from '@app/shared/video/syndication.model' import { Notifier, ServerService } from '@app/core' import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' +import { I18n } from '@ngx-translate/i18n-polyfill' +import { isThisMonth, isThisWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' + +enum GroupDate { + UNKNOWN = 0, + TODAY = 1, + YESTERDAY = 2, + THIS_WEEK = 3, + THIS_MONTH = 4, + OLDER = 5 +} export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableForReuseHook { pagination: ComponentPagination = { @@ -31,6 +42,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor displayModerationBlock = false titleTooltip: string displayVideoActions = true + groupByDate = false disabled = false @@ -50,11 +62,15 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor protected abstract serverService: ServerService protected abstract screenService: ScreenService protected abstract router: Router + protected abstract i18n: I18n abstract titlePage: string private resizeSubscription: Subscription private angularState: number + private groupedDateLabels: { [id in GroupDate]: string } + private groupedDates: { [id: number]: GroupDate } = {} + abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number }> abstract generateSyndicationList (): void @@ -64,6 +80,15 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor } ngOnInit () { + this.groupedDateLabels = { + [GroupDate.UNKNOWN]: null, + [GroupDate.TODAY]: this.i18n('Today'), + [GroupDate.YESTERDAY]: this.i18n('Yesterday'), + [GroupDate.THIS_WEEK]: this.i18n('This week'), + [GroupDate.THIS_MONTH]: this.i18n('This month'), + [GroupDate.OLDER]: this.i18n('Older') + } + // Subscribe to route changes const routeParams = this.route.snapshot.queryParams this.loadRouteParams(routeParams) @@ -113,6 +138,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor this.pagination.totalItems = totalVideos this.videos = this.videos.concat(videos) + if (this.groupByDate) this.buildGroupedDateLabels() + this.onMoreVideos() }, @@ -134,6 +161,49 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor this.videos = this.videos.filter(v => v.id !== video.id) } + buildGroupedDateLabels () { + let currentGroupedDate: GroupDate = GroupDate.UNKNOWN + + for (const video of this.videos) { + const publishedDate = video.publishedAt + + if (currentGroupedDate < GroupDate.TODAY && isToday(publishedDate)) { + currentGroupedDate = GroupDate.TODAY + this.groupedDates[ video.id ] = currentGroupedDate + continue + } + + if (currentGroupedDate < GroupDate.YESTERDAY && isYesterday(publishedDate)) { + currentGroupedDate = GroupDate.YESTERDAY + this.groupedDates[ video.id ] = currentGroupedDate + continue + } + + if (currentGroupedDate < GroupDate.THIS_WEEK && isThisWeek(publishedDate)) { + currentGroupedDate = GroupDate.THIS_WEEK + this.groupedDates[ video.id ] = currentGroupedDate + continue + } + + if (currentGroupedDate < GroupDate.THIS_MONTH && isThisMonth(publishedDate)) { + currentGroupedDate = GroupDate.THIS_MONTH + this.groupedDates[ video.id ] = currentGroupedDate + continue + } + + if (currentGroupedDate < GroupDate.OLDER) { + currentGroupedDate = GroupDate.OLDER + this.groupedDates[ video.id ] = currentGroupedDate + } + } + } + + getCurrentGroupedDateLabel (video: Video) { + if (this.groupByDate === false) return undefined + + return this.groupedDateLabels[this.groupedDates[video.id]] + } + // On videos hook for children that want to do something protected onMoreVideos () { /* empty */ } 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' import { PeerTubeTemplateDirective } from '@app/shared/angular/peertube-template.directive' import { VideoSortField } from '@app/shared/video/sort-field.type' import { ComponentPagination } from '@app/shared/rest/component-pagination.model' +import { I18n } from '@ngx-translate/i18n-polyfill' export type SelectionType = { [ id: number ]: boolean } @@ -44,6 +45,7 @@ export class VideosSelectionComponent extends AbstractVideoList implements OnIni globalButtonsTemplate: TemplateRef constructor ( + protected i18n: I18n, protected router: Router, protected route: ActivatedRoute, protected notifier: Notifier, -- cgit v1.2.3