Group videos on chronological order
This commit is contained in:
		
							parent
							
								
									e6b04e0e79
								
							
						
					
					
						commit
						34c7f429e4
					
				
					 12 changed files with 155 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -29,6 +29,7 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit,
 | 
			
		|||
  private accountSub: Subscription
 | 
			
		||||
 | 
			
		||||
  constructor (
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    protected router: Router,
 | 
			
		||||
    protected serverService: ServerService,
 | 
			
		||||
    protected route: ActivatedRoute,
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +37,6 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit,
 | 
			
		|||
    protected notifier: Notifier,
 | 
			
		||||
    protected confirmService: ConfirmService,
 | 
			
		||||
    protected screenService: ScreenService,
 | 
			
		||||
    private i18n: I18n,
 | 
			
		||||
    private accountService: AccountService,
 | 
			
		||||
    private videoService: VideoService
 | 
			
		||||
  ) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ export class MyAccountHistoryComponent extends AbstractVideoList implements OnIn
 | 
			
		|||
  videosHistoryEnabled: boolean
 | 
			
		||||
 | 
			
		||||
  constructor (
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    protected router: Router,
 | 
			
		||||
    protected serverService: ServerService,
 | 
			
		||||
    protected route: ActivatedRoute,
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +35,6 @@ export class MyAccountHistoryComponent extends AbstractVideoList implements OnIn
 | 
			
		|||
    protected userService: UserService,
 | 
			
		||||
    protected notifier: Notifier,
 | 
			
		||||
    protected screenService: ScreenService,
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    private confirmService: ConfirmService,
 | 
			
		||||
    private videoService: VideoService,
 | 
			
		||||
    private userHistoryService: UserHistoryService
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@ export class VideoChannelVideosComponent extends AbstractVideoList implements On
 | 
			
		|||
  private videoChannelSub: Subscription
 | 
			
		||||
 | 
			
		||||
  constructor (
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    protected router: Router,
 | 
			
		||||
    protected serverService: ServerService,
 | 
			
		||||
    protected route: ActivatedRoute,
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +37,6 @@ export class VideoChannelVideosComponent extends AbstractVideoList implements On
 | 
			
		|||
    protected notifier: Notifier,
 | 
			
		||||
    protected confirmService: ConfirmService,
 | 
			
		||||
    protected screenService: ScreenService,
 | 
			
		||||
    private i18n: I18n,
 | 
			
		||||
    private videoChannelService: VideoChannelService,
 | 
			
		||||
    private videoService: VideoService
 | 
			
		||||
  ) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,11 +22,18 @@
 | 
			
		|||
    myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true"
 | 
			
		||||
    class="videos"
 | 
			
		||||
  >
 | 
			
		||||
    <my-video-miniature
 | 
			
		||||
      *ngFor="let video of videos; trackBy: videoById" [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType"
 | 
			
		||||
      [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
 | 
			
		||||
      (videoBlacklisted)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
 | 
			
		||||
    >
 | 
			
		||||
    </my-video-miniature>
 | 
			
		||||
    <ng-container *ngFor="let video of videos; trackBy: videoById;">
 | 
			
		||||
      <div class="date-title" *ngIf="getCurrentGroupedDateLabel(video)">
 | 
			
		||||
        {{ getCurrentGroupedDateLabel(video) }}
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      <my-video-miniature
 | 
			
		||||
        [video]="video" [user]="user" [ownerDisplayType]="ownerDisplayType"
 | 
			
		||||
        [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
 | 
			
		||||
        (videoBlacklisted)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
 | 
			
		||||
      >
 | 
			
		||||
      </my-video-miniature>
 | 
			
		||||
    </ng-container>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */ }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<any>
 | 
			
		||||
 | 
			
		||||
  constructor (
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    protected router: Router,
 | 
			
		||||
    protected route: ActivatedRoute,
 | 
			
		||||
    protected notifier: Notifier,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,13 +22,13 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit, On
 | 
			
		|||
  filter: VideoFilter = 'local'
 | 
			
		||||
 | 
			
		||||
  constructor (
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    protected router: Router,
 | 
			
		||||
    protected serverService: ServerService,
 | 
			
		||||
    protected route: ActivatedRoute,
 | 
			
		||||
    protected notifier: Notifier,
 | 
			
		||||
    protected authService: AuthService,
 | 
			
		||||
    protected screenService: ScreenService,
 | 
			
		||||
    private i18n: I18n,
 | 
			
		||||
    private videoService: VideoService
 | 
			
		||||
  ) {
 | 
			
		||||
    super()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,15 +17,16 @@ import { Notifier, ServerService } from '@app/core'
 | 
			
		|||
export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit, OnDestroy {
 | 
			
		||||
  titlePage: string
 | 
			
		||||
  sort: VideoSortField = '-publishedAt'
 | 
			
		||||
  groupByDate = true
 | 
			
		||||
 | 
			
		||||
  constructor (
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    protected route: ActivatedRoute,
 | 
			
		||||
    protected serverService: ServerService,
 | 
			
		||||
    protected router: Router,
 | 
			
		||||
    protected notifier: Notifier,
 | 
			
		||||
    protected authService: AuthService,
 | 
			
		||||
    protected screenService: ScreenService,
 | 
			
		||||
    private i18n: I18n,
 | 
			
		||||
    private videoService: VideoService
 | 
			
		||||
  ) {
 | 
			
		||||
    super()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,13 +19,13 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
 | 
			
		|||
  defaultSort: VideoSortField = '-trending'
 | 
			
		||||
 | 
			
		||||
  constructor (
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    protected router: Router,
 | 
			
		||||
    protected serverService: ServerService,
 | 
			
		||||
    protected route: ActivatedRoute,
 | 
			
		||||
    protected notifier: Notifier,
 | 
			
		||||
    protected authService: AuthService,
 | 
			
		||||
    protected screenService: ScreenService,
 | 
			
		||||
    private i18n: I18n,
 | 
			
		||||
    private videoService: VideoService
 | 
			
		||||
  ) {
 | 
			
		||||
    super()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,15 +19,16 @@ export class VideoUserSubscriptionsComponent extends AbstractVideoList implement
 | 
			
		|||
  titlePage: string
 | 
			
		||||
  sort = '-publishedAt' as VideoSortField
 | 
			
		||||
  ownerDisplayType: OwnerDisplayType = 'auto'
 | 
			
		||||
  groupByDate = true
 | 
			
		||||
 | 
			
		||||
  constructor (
 | 
			
		||||
    protected i18n: I18n,
 | 
			
		||||
    protected router: Router,
 | 
			
		||||
    protected serverService: ServerService,
 | 
			
		||||
    protected route: ActivatedRoute,
 | 
			
		||||
    protected notifier: Notifier,
 | 
			
		||||
    protected authService: AuthService,
 | 
			
		||||
    protected screenService: ScreenService,
 | 
			
		||||
    private i18n: I18n,
 | 
			
		||||
    private videoService: VideoService
 | 
			
		||||
  ) {
 | 
			
		||||
    super()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										49
									
								
								shared/core-utils/miscs/date.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								shared/core-utils/miscs/date.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
function isToday (d: Date) {
 | 
			
		||||
  const today = new Date()
 | 
			
		||||
 | 
			
		||||
  return areDatesEqual(d, today)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isYesterday (d: Date) {
 | 
			
		||||
  const yesterday = new Date()
 | 
			
		||||
  yesterday.setDate(yesterday.getDate() - 1)
 | 
			
		||||
 | 
			
		||||
  return areDatesEqual(d, yesterday)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isThisWeek (d: Date) {
 | 
			
		||||
  const minDateOfThisWeek = new Date()
 | 
			
		||||
  minDateOfThisWeek.setHours(0, 0, 0)
 | 
			
		||||
 | 
			
		||||
  // getDay() -> Sunday - Saturday : 0 - 6
 | 
			
		||||
  // We want to start our week on Monday
 | 
			
		||||
  let dayOfWeek = minDateOfThisWeek.getDay() - 1
 | 
			
		||||
  if (dayOfWeek < 0) dayOfWeek = 6 // Sunday
 | 
			
		||||
 | 
			
		||||
  minDateOfThisWeek.setDate(minDateOfThisWeek.getDate() - dayOfWeek)
 | 
			
		||||
 | 
			
		||||
  return d >= minDateOfThisWeek
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isThisMonth (d: Date) {
 | 
			
		||||
  const thisMonth = new Date().getMonth()
 | 
			
		||||
 | 
			
		||||
  return d.getMonth() === thisMonth
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
  isYesterday,
 | 
			
		||||
  isThisWeek,
 | 
			
		||||
  isThisMonth,
 | 
			
		||||
  isToday
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
function areDatesEqual (d1: Date, d2: Date) {
 | 
			
		||||
  return d1.getFullYear() === d2.getFullYear() &&
 | 
			
		||||
    d1.getMonth() === d2.getMonth() &&
 | 
			
		||||
    d1.getDate() === d2.getDate()
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue