diff options
Diffstat (limited to 'client/src/app/shared')
9 files changed, 59 insertions, 21 deletions
diff --git a/client/src/app/shared/shared-icons/global-icon.component.ts b/client/src/app/shared/shared-icons/global-icon.component.ts index a4c62c234..ba23edde0 100644 --- a/client/src/app/shared/shared-icons/global-icon.component.ts +++ b/client/src/app/shared/shared-icons/global-icon.component.ts | |||
@@ -75,7 +75,8 @@ const icons = { | |||
75 | 'chevrons-up': require('!!raw-loader?!../../../assets/images/feather/chevrons-up.svg').default, | 75 | 'chevrons-up': require('!!raw-loader?!../../../assets/images/feather/chevrons-up.svg').default, |
76 | 'message-circle': require('!!raw-loader?!../../../assets/images/feather/message-circle.svg').default, | 76 | 'message-circle': require('!!raw-loader?!../../../assets/images/feather/message-circle.svg').default, |
77 | codesandbox: require('!!raw-loader?!../../../assets/images/feather/codesandbox.svg').default, | 77 | codesandbox: require('!!raw-loader?!../../../assets/images/feather/codesandbox.svg').default, |
78 | award: require('!!raw-loader?!../../../assets/images/feather/award.svg').default | 78 | award: require('!!raw-loader?!../../../assets/images/feather/award.svg').default, |
79 | stats: require('!!raw-loader?!../../../assets/images/feather/stats.svg').default | ||
79 | } | 80 | } |
80 | 81 | ||
81 | export type GlobalIconName = keyof typeof icons | 82 | export type GlobalIconName = keyof typeof icons |
diff --git a/client/src/app/shared/shared-main/angular/number-formatter.pipe.ts b/client/src/app/shared/shared-main/angular/number-formatter.pipe.ts index 8badb1573..7c18b7f67 100644 --- a/client/src/app/shared/shared-main/angular/number-formatter.pipe.ts +++ b/client/src/app/shared/shared-main/angular/number-formatter.pipe.ts | |||
@@ -22,6 +22,7 @@ export class NumberFormatterPipe implements PipeTransform { | |||
22 | { max: 1000000, type: 'K' }, | 22 | { max: 1000000, type: 'K' }, |
23 | { max: 1000000000, type: 'M' } | 23 | { max: 1000000000, type: 'M' } |
24 | ] | 24 | ] |
25 | |||
25 | constructor (@Inject(LOCALE_ID) private localeId: string) {} | 26 | constructor (@Inject(LOCALE_ID) private localeId: string) {} |
26 | 27 | ||
27 | transform (value: number) { | 28 | transform (value: number) { |
diff --git a/client/src/app/shared/shared-main/shared-main.module.ts b/client/src/app/shared/shared-main/shared-main.module.ts index d83af9a66..5629640bc 100644 --- a/client/src/app/shared/shared-main/shared-main.module.ts +++ b/client/src/app/shared/shared-main/shared-main.module.ts | |||
@@ -45,7 +45,7 @@ import { | |||
45 | import { PluginPlaceholderComponent, PluginSelectorDirective } from './plugins' | 45 | import { PluginPlaceholderComponent, PluginSelectorDirective } from './plugins' |
46 | import { ActorRedirectGuard } from './router' | 46 | import { ActorRedirectGuard } from './router' |
47 | import { UserHistoryService, UserNotificationsComponent, UserNotificationService, UserQuotaComponent } from './users' | 47 | import { UserHistoryService, UserNotificationsComponent, UserNotificationService, UserQuotaComponent } from './users' |
48 | import { EmbedComponent, RedundancyService, VideoImportService, VideoOwnershipService, VideoService } from './video' | 48 | import { EmbedComponent, RedundancyService, VideoImportService, VideoOwnershipService, VideoResolver, VideoService } from './video' |
49 | import { VideoCaptionService } from './video-caption' | 49 | import { VideoCaptionService } from './video-caption' |
50 | import { VideoChannelService } from './video-channel' | 50 | import { VideoChannelService } from './video-channel' |
51 | 51 | ||
@@ -190,6 +190,7 @@ import { VideoChannelService } from './video-channel' | |||
190 | VideoImportService, | 190 | VideoImportService, |
191 | VideoOwnershipService, | 191 | VideoOwnershipService, |
192 | VideoService, | 192 | VideoService, |
193 | VideoResolver, | ||
193 | 194 | ||
194 | VideoCaptionService, | 195 | VideoCaptionService, |
195 | 196 | ||
diff --git a/client/src/app/shared/shared-main/video/index.ts b/client/src/app/shared/shared-main/video/index.ts index e72c0c3d6..361601456 100644 --- a/client/src/app/shared/shared-main/video/index.ts +++ b/client/src/app/shared/shared-main/video/index.ts | |||
@@ -5,4 +5,5 @@ export * from './video-edit.model' | |||
5 | export * from './video-import.service' | 5 | export * from './video-import.service' |
6 | export * from './video-ownership.service' | 6 | export * from './video-ownership.service' |
7 | export * from './video.model' | 7 | export * from './video.model' |
8 | export * from './video.resolver' | ||
8 | export * from './video.service' | 9 | export * from './video.service' |
diff --git a/client/src/app/shared/shared-main/video/video.model.ts b/client/src/app/shared/shared-main/video/video.model.ts index 2d4db9a28..022bb95ad 100644 --- a/client/src/app/shared/shared-main/video/video.model.ts +++ b/client/src/app/shared/shared-main/video/video.model.ts | |||
@@ -58,8 +58,7 @@ export class Video implements VideoServerModel { | |||
58 | url: string | 58 | url: string |
59 | 59 | ||
60 | views: number | 60 | views: number |
61 | // If live | 61 | viewers: number |
62 | viewers?: number | ||
63 | 62 | ||
64 | likes: number | 63 | likes: number |
65 | dislikes: number | 64 | dislikes: number |
@@ -234,9 +233,13 @@ export class Video implements VideoServerModel { | |||
234 | this.isUpdatableBy(user) | 233 | this.isUpdatableBy(user) |
235 | } | 234 | } |
236 | 235 | ||
236 | canSeeStats (user: AuthUser) { | ||
237 | return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.SEE_ALL_VIDEOS)) | ||
238 | } | ||
239 | |||
237 | canRemoveFiles (user: AuthUser) { | 240 | canRemoveFiles (user: AuthUser) { |
238 | return this.isLocal && | 241 | return this.isLocal && |
239 | user.hasRight(UserRight.MANAGE_VIDEO_FILES) && | 242 | user && user.hasRight(UserRight.MANAGE_VIDEO_FILES) && |
240 | this.state.id !== VideoState.TO_TRANSCODE && | 243 | this.state.id !== VideoState.TO_TRANSCODE && |
241 | this.hasHLS() && | 244 | this.hasHLS() && |
242 | this.hasWebTorrent() | 245 | this.hasWebTorrent() |
@@ -244,7 +247,7 @@ export class Video implements VideoServerModel { | |||
244 | 247 | ||
245 | canRunTranscoding (user: AuthUser) { | 248 | canRunTranscoding (user: AuthUser) { |
246 | return this.isLocal && | 249 | return this.isLocal && |
247 | user.hasRight(UserRight.RUN_VIDEO_TRANSCODING) && | 250 | user && user.hasRight(UserRight.RUN_VIDEO_TRANSCODING) && |
248 | this.state.id !== VideoState.TO_TRANSCODE | 251 | this.state.id !== VideoState.TO_TRANSCODE |
249 | } | 252 | } |
250 | 253 | ||
diff --git a/client/src/app/shared/shared-main/video/video.resolver.ts b/client/src/app/shared/shared-main/video/video.resolver.ts new file mode 100644 index 000000000..65b7230ce --- /dev/null +++ b/client/src/app/shared/shared-main/video/video.resolver.ts | |||
@@ -0,0 +1,17 @@ | |||
1 | import { Injectable } from '@angular/core' | ||
2 | import { ActivatedRouteSnapshot, Resolve } from '@angular/router' | ||
3 | import { VideoService } from './video.service' | ||
4 | |||
5 | @Injectable() | ||
6 | export class VideoResolver implements Resolve<any> { | ||
7 | constructor ( | ||
8 | private videoService: VideoService | ||
9 | ) { | ||
10 | } | ||
11 | |||
12 | resolve (route: ActivatedRouteSnapshot) { | ||
13 | const videoId: string = route.params['videoId'] | ||
14 | |||
15 | return this.videoService.getVideo({ videoId }) | ||
16 | } | ||
17 | } | ||
diff --git a/client/src/app/shared/shared-main/video/video.service.ts b/client/src/app/shared/shared-main/video/video.service.ts index 94af9cd38..bc15c326f 100644 --- a/client/src/app/shared/shared-main/video/video.service.ts +++ b/client/src/app/shared/shared-main/video/video.service.ts | |||
@@ -65,10 +65,6 @@ export class VideoService { | |||
65 | return `${VideoService.BASE_VIDEO_URL}/${uuid}/views` | 65 | return `${VideoService.BASE_VIDEO_URL}/${uuid}/views` |
66 | } | 66 | } |
67 | 67 | ||
68 | getUserWatchingVideoUrl (uuid: string) { | ||
69 | return `${VideoService.BASE_VIDEO_URL}/${uuid}/watching` | ||
70 | } | ||
71 | |||
72 | getVideo (options: { videoId: string }): Observable<VideoDetails> { | 68 | getVideo (options: { videoId: string }): Observable<VideoDetails> { |
73 | return this.serverService.getServerLocale() | 69 | return this.serverService.getServerLocale() |
74 | .pipe( | 70 | .pipe( |
diff --git a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts index 5eef96145..ed6a4afc0 100644 --- a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts +++ b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts | |||
@@ -30,6 +30,7 @@ export type VideoActionsDisplayType = { | |||
30 | removeFiles?: boolean | 30 | removeFiles?: boolean |
31 | transcoding?: boolean | 31 | transcoding?: boolean |
32 | studio?: boolean | 32 | studio?: boolean |
33 | stats?: boolean | ||
33 | } | 34 | } |
34 | 35 | ||
35 | @Component({ | 36 | @Component({ |
@@ -61,9 +62,11 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
61 | liveInfo: false, | 62 | liveInfo: false, |
62 | removeFiles: false, | 63 | removeFiles: false, |
63 | transcoding: false, | 64 | transcoding: false, |
64 | studio: true | 65 | studio: true, |
66 | stats: true | ||
65 | } | 67 | } |
66 | @Input() placement = 'left' | 68 | @Input() placement = 'left' |
69 | @Input() moreActions: DropdownAction<{ video: Video }>[][] = [] | ||
67 | 70 | ||
68 | @Input() label: string | 71 | @Input() label: string |
69 | 72 | ||
@@ -156,6 +159,10 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
156 | return this.video.isEditableBy(this.user, this.serverService.getHTMLConfig().videoStudio.enabled) | 159 | return this.video.isEditableBy(this.user, this.serverService.getHTMLConfig().videoStudio.enabled) |
157 | } | 160 | } |
158 | 161 | ||
162 | isVideoStatsAvailable () { | ||
163 | return this.video.canSeeStats(this.user) | ||
164 | } | ||
165 | |||
159 | isVideoRemovable () { | 166 | isVideoRemovable () { |
160 | return this.video.isRemovableBy(this.user) | 167 | return this.video.isRemovableBy(this.user) |
161 | } | 168 | } |
@@ -343,6 +350,12 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
343 | isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.studio && this.isVideoEditable() | 350 | isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.studio && this.isVideoEditable() |
344 | }, | 351 | }, |
345 | { | 352 | { |
353 | label: $localize`Stats`, | ||
354 | linkBuilder: ({ video }) => [ '/stats/videos', video.uuid ], | ||
355 | iconName: 'stats', | ||
356 | isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.stats && this.isVideoStatsAvailable() | ||
357 | }, | ||
358 | { | ||
346 | label: $localize`Block`, | 359 | label: $localize`Block`, |
347 | handler: () => this.showBlockModal(), | 360 | handler: () => this.showBlockModal(), |
348 | iconName: 'no', | 361 | iconName: 'no', |
@@ -408,5 +421,7 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
408 | } | 421 | } |
409 | ] | 422 | ] |
410 | ] | 423 | ] |
424 | |||
425 | this.videoActions = this.videoActions.concat(this.moreActions) | ||
411 | } | 426 | } |
412 | } | 427 | } |
diff --git a/client/src/app/shared/shared-video-miniature/video-miniature.component.ts b/client/src/app/shared/shared-video-miniature/video-miniature.component.ts index 7de9fc8e2..42c472579 100644 --- a/client/src/app/shared/shared-video-miniature/video-miniature.component.ts +++ b/client/src/app/shared/shared-video-miniature/video-miniature.component.ts | |||
@@ -49,7 +49,20 @@ export class VideoMiniatureComponent implements OnInit { | |||
49 | state: false, | 49 | state: false, |
50 | blacklistInfo: false | 50 | blacklistInfo: false |
51 | } | 51 | } |
52 | |||
52 | @Input() displayVideoActions = true | 53 | @Input() displayVideoActions = true |
54 | @Input() videoActionsDisplayOptions: VideoActionsDisplayType = { | ||
55 | playlist: true, | ||
56 | download: false, | ||
57 | update: true, | ||
58 | blacklist: true, | ||
59 | delete: true, | ||
60 | report: true, | ||
61 | duplicate: true, | ||
62 | mute: true, | ||
63 | studio: false, | ||
64 | stats: false | ||
65 | } | ||
53 | 66 | ||
54 | @Input() actorImageSize: ActorAvatarSize = '40' | 67 | @Input() actorImageSize: ActorAvatarSize = '40' |
55 | 68 | ||
@@ -62,16 +75,6 @@ export class VideoMiniatureComponent implements OnInit { | |||
62 | @Output() videoRemoved = new EventEmitter() | 75 | @Output() videoRemoved = new EventEmitter() |
63 | @Output() videoAccountMuted = new EventEmitter() | 76 | @Output() videoAccountMuted = new EventEmitter() |
64 | 77 | ||
65 | videoActionsDisplayOptions: VideoActionsDisplayType = { | ||
66 | playlist: true, | ||
67 | download: false, | ||
68 | update: true, | ||
69 | blacklist: true, | ||
70 | delete: true, | ||
71 | report: true, | ||
72 | duplicate: true, | ||
73 | mute: true | ||
74 | } | ||
75 | showActions = false | 78 | showActions = false |
76 | serverConfig: HTMLServerConfig | 79 | serverConfig: HTMLServerConfig |
77 | 80 | ||