diff options
Diffstat (limited to 'client/src/app/shared')
3 files changed, 147 insertions, 12 deletions
diff --git a/client/src/app/shared/video/video-miniature.component.html b/client/src/app/shared/video/video-miniature.component.html index 2c635fa2f..f4ae0b0dd 100644 --- a/client/src/app/shared/video/video-miniature.component.html +++ b/client/src/app/shared/video/video-miniature.component.html | |||
@@ -1,4 +1,4 @@ | |||
1 | <div class="video-miniature"> | 1 | <div class="video-miniature" [ngClass]="{ 'display-as-row': displayAsRow }"> |
2 | <my-video-thumbnail [video]="video" [nsfw]="isVideoBlur"></my-video-thumbnail> | 2 | <my-video-thumbnail [video]="video" [nsfw]="isVideoBlur"></my-video-thumbnail> |
3 | 3 | ||
4 | <div class="video-miniature-information"> | 4 | <div class="video-miniature-information"> |
@@ -7,19 +7,41 @@ | |||
7 | class="video-miniature-name" | 7 | class="video-miniature-name" |
8 | [routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }" | 8 | [routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }" |
9 | > | 9 | > |
10 | <span *ngIf="isUnlistedVideo()" class="badge badge-warning" i18n>Unlisted</span> | 10 | <ng-container *ngIf="displayOptions.privacyLabel"> |
11 | <span *ngIf="isPrivateVideo()" class="badge badge-danger" i18n>Private</span> | 11 | <span *ngIf="isUnlistedVideo()" class="badge badge-warning" i18n>Unlisted</span> |
12 | <span *ngIf="isPrivateVideo()" class="badge badge-danger" i18n>Private</span> | ||
13 | </ng-container> | ||
12 | 14 | ||
13 | {{ video.name }} | 15 | {{ video.name }} |
14 | </a> | 16 | </a> |
15 | 17 | ||
16 | <span i18n class="video-miniature-created-at-views">{{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span> | 18 | <span class="video-miniature-created-at-views"> |
19 | <ng-container *ngIf="displayOptions.date">{{ video.publishedAt | myFromNow }}</ng-container> | ||
20 | <ng-container *ngIf="displayOptions.date && displayOptions.views"> - </ng-container> | ||
21 | <ng-container i18n *ngIf="displayOptions.views">{{ video.views | myNumberFormatter }} views</ng-container> | ||
22 | </span> | ||
17 | 23 | ||
18 | <a tabindex="-1" *ngIf="displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]"> | 24 | <a tabindex="-1" *ngIf="displayOptions.by && displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]"> |
19 | {{ video.byAccount }} | 25 | {{ video.byAccount }} |
20 | </a> | 26 | </a> |
21 | <a tabindex="-1" *ngIf="displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]"> | 27 | <a tabindex="-1" *ngIf="displayOptions.by && displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]"> |
22 | {{ video.byVideoChannel }} | 28 | {{ video.byVideoChannel }} |
23 | </a> | 29 | </a> |
30 | |||
31 | <div class="video-info-privacy"> | ||
32 | <ng-container *ngIf="displayOptions.privacyText">{{ video.privacy.label }}</ng-container> | ||
33 | <ng-container *ngIf="displayOptions.privacyText && displayOptions.state"> - </ng-container> | ||
34 | <ng-container *ngIf="displayOptions.state">{{ getStateLabel(video) }}</ng-container> | ||
35 | </div> | ||
36 | |||
37 | <div *ngIf="displayOptions.blacklistInfo && video.blacklisted" class="video-info-blacklisted"> | ||
38 | <span class="blacklisted-label" i18n>Blacklisted</span> | ||
39 | <span class="blacklisted-reason" *ngIf="video.blacklistedReason">{{ video.blacklistedReason }}</span> | ||
40 | </div> | ||
41 | |||
42 | <div i18n *ngIf="displayOptions.nsfw && video.nsfw" class="video-info-nsfw"> | ||
43 | Sensitive | ||
44 | </div> | ||
45 | |||
24 | </div> | 46 | </div> |
25 | </div> | 47 | </div> |
diff --git a/client/src/app/shared/video/video-miniature.component.scss b/client/src/app/shared/video/video-miniature.component.scss index 4799e00c2..fdc3dc033 100644 --- a/client/src/app/shared/video/video-miniature.component.scss +++ b/client/src/app/shared/video/video-miniature.component.scss | |||
@@ -4,15 +4,14 @@ | |||
4 | 4 | ||
5 | .video-miniature { | 5 | .video-miniature { |
6 | width: $video-miniature-width; | 6 | width: $video-miniature-width; |
7 | 7 | display: inline-flex; | |
8 | display: inline-block; | 8 | flex-direction: column; |
9 | margin-bottom: 30px; | 9 | margin-bottom: 30px; |
10 | height: 195px; | 10 | height: 195px; |
11 | vertical-align: top; | 11 | vertical-align: top; |
12 | 12 | ||
13 | .video-miniature-information { | 13 | .video-miniature-information { |
14 | width: 200px; | 14 | width: 200px; |
15 | margin-top: 2px; | ||
16 | line-height: normal; | 15 | line-height: normal; |
17 | 16 | ||
18 | .video-miniature-name { | 17 | .video-miniature-name { |
@@ -37,5 +36,68 @@ | |||
37 | color: $grey-foreground-hover-color; | 36 | color: $grey-foreground-hover-color; |
38 | } | 37 | } |
39 | } | 38 | } |
39 | |||
40 | .video-info-privacy, | ||
41 | .video-info-blacklisted .blacklisted-label, | ||
42 | .video-info-nsfw { | ||
43 | font-weight: $font-semibold; | ||
44 | } | ||
45 | |||
46 | .video-info-blacklisted { | ||
47 | color: red; | ||
48 | |||
49 | .blacklisted-reason::before { | ||
50 | content: ' - '; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | .video-info-nsfw { | ||
55 | color: red; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | &.display-as-row { | ||
60 | flex-direction: row; | ||
61 | margin-bottom: 0; | ||
62 | height: auto; | ||
63 | width: 100%; | ||
64 | |||
65 | my-video-thumbnail { | ||
66 | margin-right: 10px; | ||
67 | } | ||
68 | |||
69 | .video-miniature-information { | ||
70 | width: auto; | ||
71 | |||
72 | .video-miniature-name { | ||
73 | @include ellipsis-multiline(1.3em, 2); | ||
74 | |||
75 | margin-top: 2px; | ||
76 | margin-bottom: 5px; | ||
77 | } | ||
78 | |||
79 | .video-miniature-created-at-views, | ||
80 | .video-miniature-account, | ||
81 | .video-miniature-channel { | ||
82 | font-size: 14px; | ||
83 | } | ||
84 | |||
85 | .video-info-privacy { | ||
86 | margin-top: 5px; | ||
87 | } | ||
88 | |||
89 | .video-info-blacklisted { | ||
90 | margin-top: 3px; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | @media screen and (max-width: $small-view) { | ||
95 | flex-direction: column; | ||
96 | height: auto; | ||
97 | |||
98 | my-video-thumbnail { | ||
99 | margin-right: 0; | ||
100 | } | ||
101 | } | ||
40 | } | 102 | } |
41 | } | 103 | } |
diff --git a/client/src/app/shared/video/video-miniature.component.ts b/client/src/app/shared/video/video-miniature.component.ts index 2f951a1f1..800417a79 100644 --- a/client/src/app/shared/video/video-miniature.component.ts +++ b/client/src/app/shared/video/video-miniature.component.ts | |||
@@ -1,10 +1,21 @@ | |||
1 | import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core' | 1 | import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core' |
2 | import { User } from '../users' | 2 | import { User } from '../users' |
3 | import { Video } from './video.model' | 3 | import { Video } from './video.model' |
4 | import { ServerService } from '@app/core' | 4 | import { ServerService } from '@app/core' |
5 | import { VideoPrivacy } from '../../../../../shared' | 5 | import { VideoPrivacy, VideoState } from '../../../../../shared' |
6 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
6 | 7 | ||
7 | export type OwnerDisplayType = 'account' | 'videoChannel' | 'auto' | 8 | export type OwnerDisplayType = 'account' | 'videoChannel' | 'auto' |
9 | export type MiniatureDisplayOptions = { | ||
10 | date?: boolean | ||
11 | views?: boolean | ||
12 | by?: boolean | ||
13 | privacyLabel?: boolean | ||
14 | privacyText?: boolean | ||
15 | state?: boolean | ||
16 | blacklistInfo?: boolean | ||
17 | nsfw?: boolean | ||
18 | } | ||
8 | 19 | ||
9 | @Component({ | 20 | @Component({ |
10 | selector: 'my-video-miniature', | 21 | selector: 'my-video-miniature', |
@@ -15,11 +26,26 @@ export type OwnerDisplayType = 'account' | 'videoChannel' | 'auto' | |||
15 | export class VideoMiniatureComponent implements OnInit { | 26 | export class VideoMiniatureComponent implements OnInit { |
16 | @Input() user: User | 27 | @Input() user: User |
17 | @Input() video: Video | 28 | @Input() video: Video |
29 | |||
18 | @Input() ownerDisplayType: OwnerDisplayType = 'account' | 30 | @Input() ownerDisplayType: OwnerDisplayType = 'account' |
31 | @Input() displayOptions: MiniatureDisplayOptions = { | ||
32 | date: true, | ||
33 | views: true, | ||
34 | by: true, | ||
35 | privacyLabel: false, | ||
36 | privacyText: false, | ||
37 | state: false, | ||
38 | blacklistInfo: false | ||
39 | } | ||
40 | @Input() displayAsRow = false | ||
19 | 41 | ||
20 | private ownerDisplayTypeChosen: 'account' | 'videoChannel' | 42 | private ownerDisplayTypeChosen: 'account' | 'videoChannel' |
21 | 43 | ||
22 | constructor (private serverService: ServerService) { } | 44 | constructor ( |
45 | private serverService: ServerService, | ||
46 | private i18n: I18n, | ||
47 | @Inject(LOCALE_ID) private localeId: string | ||
48 | ) { } | ||
23 | 49 | ||
24 | get isVideoBlur () { | 50 | get isVideoBlur () { |
25 | return this.video.isVideoNSFWForUser(this.user, this.serverService.getConfig()) | 51 | return this.video.isVideoNSFWForUser(this.user, this.serverService.getConfig()) |
@@ -58,4 +84,29 @@ export class VideoMiniatureComponent implements OnInit { | |||
58 | isPrivateVideo () { | 84 | isPrivateVideo () { |
59 | return this.video.privacy.id === VideoPrivacy.PRIVATE | 85 | return this.video.privacy.id === VideoPrivacy.PRIVATE |
60 | } | 86 | } |
87 | |||
88 | getStateLabel (video: Video) { | ||
89 | if (video.privacy.id !== VideoPrivacy.PRIVATE && video.state.id === VideoState.PUBLISHED) { | ||
90 | return this.i18n('Published') | ||
91 | } | ||
92 | |||
93 | if (video.scheduledUpdate) { | ||
94 | const updateAt = new Date(video.scheduledUpdate.updateAt.toString()).toLocaleString(this.localeId) | ||
95 | return this.i18n('Publication scheduled on ') + updateAt | ||
96 | } | ||
97 | |||
98 | if (video.state.id === VideoState.TO_TRANSCODE && video.waitTranscoding === true) { | ||
99 | return this.i18n('Waiting transcoding') | ||
100 | } | ||
101 | |||
102 | if (video.state.id === VideoState.TO_TRANSCODE) { | ||
103 | return this.i18n('To transcode') | ||
104 | } | ||
105 | |||
106 | if (video.state.id === VideoState.TO_IMPORT) { | ||
107 | return this.i18n('To import') | ||
108 | } | ||
109 | |||
110 | return '' | ||
111 | } | ||
61 | } | 112 | } |