From 33f6dce136ca6e969fe374efa099bee3f2a3599d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 27 Oct 2021 11:42:05 +0200 Subject: Add videos list admin component --- client/src/app/+admin/admin.component.ts | 12 ++ client/src/app/+admin/admin.module.ts | 8 +- .../video-block-list.component.html | 29 ++--- .../video-block-list/video-block-list.component.ts | 13 +-- client/src/app/+admin/overview/index.ts | 1 + client/src/app/+admin/overview/overview.routes.ts | 4 +- client/src/app/+admin/overview/videos/index.ts | 2 + .../overview/videos/video-list.component.html | 86 ++++++++++++++ .../overview/videos/video-list.component.scss | 10 ++ .../+admin/overview/videos/video-list.component.ts | 123 +++++++++++++++++++++ .../src/app/+admin/overview/videos/video.routes.ts | 30 +++++ 11 files changed, 284 insertions(+), 34 deletions(-) create mode 100644 client/src/app/+admin/overview/videos/index.ts create mode 100644 client/src/app/+admin/overview/videos/video-list.component.html create mode 100644 client/src/app/+admin/overview/videos/video-list.component.scss create mode 100644 client/src/app/+admin/overview/videos/video-list.component.ts create mode 100644 client/src/app/+admin/overview/videos/video.routes.ts (limited to 'client/src/app/+admin') diff --git a/client/src/app/+admin/admin.component.ts b/client/src/app/+admin/admin.component.ts index 27d5e0a10..b8a957d1c 100644 --- a/client/src/app/+admin/admin.component.ts +++ b/client/src/app/+admin/admin.component.ts @@ -44,6 +44,14 @@ export class AdminComponent implements OnInit { }) } + if (this.hasVideosRight()) { + overviewItems.children.push({ + label: $localize`Videos`, + routerLink: '/admin/videos', + iconName: 'videos' + }) + } + if (overviewItems.children.length !== 0) { this.menuEntries.push(overviewItems) } @@ -217,4 +225,8 @@ export class AdminComponent implements OnInit { private hasVideoCommentsRight () { return this.auth.getUser().hasRight(UserRight.SEE_ALL_COMMENTS) } + + private hasVideosRight () { + return this.auth.getUser().hasRight(UserRight.SEE_ALL_VIDEOS) + } } diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts index a2bd88880..d04c11a20 100644 --- a/client/src/app/+admin/admin.module.ts +++ b/client/src/app/+admin/admin.module.ts @@ -10,7 +10,9 @@ import { SharedFormModule } from '@app/shared/shared-forms' import { SharedGlobalIconModule } from '@app/shared/shared-icons' import { SharedMainModule } from '@app/shared/shared-main' import { SharedModerationModule } from '@app/shared/shared-moderation' +import { SharedTablesModule } from '@app/shared/shared-tables' import { SharedVideoCommentModule } from '@app/shared/shared-video-comment' +import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature' import { AdminRoutingModule } from './admin-routing.module' import { AdminComponent } from './admin.component' import { @@ -33,7 +35,7 @@ import { AbuseListComponent, VideoBlockListComponent } from './moderation' import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from './moderation/instance-blocklist' import { ModerationComponent } from './moderation/moderation.component' import { VideoCommentListComponent } from './moderation/video-comment-list' -import { UserCreateComponent, UserListComponent, UserPasswordComponent, UserUpdateComponent } from './overview' +import { UserCreateComponent, UserListComponent, UserPasswordComponent, UserUpdateComponent, VideoListComponent } from './overview' import { PluginListInstalledComponent } from './plugins/plugin-list-installed/plugin-list-installed.component' import { PluginSearchComponent } from './plugins/plugin-search/plugin-search.component' import { PluginShowInstalledComponent } from './plugins/plugin-show-installed/plugin-show-installed.component' @@ -56,6 +58,8 @@ import { JobsComponent } from './system/jobs/jobs.component' SharedActorImageModule, SharedActorImageEditModule, SharedCustomMarkupModule, + SharedVideoMiniatureModule, + SharedTablesModule, TableModule, SelectButtonModule, @@ -65,6 +69,8 @@ import { JobsComponent } from './system/jobs/jobs.component' declarations: [ AdminComponent, + VideoListComponent, + FollowsComponent, FollowersListComponent, FollowingListComponent, diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html index 7efa87dd0..3cd69cfbc 100644 --- a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html +++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html @@ -34,9 +34,7 @@ - - - + @@ -47,22 +45,11 @@ - -
-
- -
- -
-
- - {{ videoBlock.video.name }} -
- -
by {{ videoBlock.video.channel?.displayName }} on {{ videoBlock.video.channel?.host }}
-
-
-
+ + + + + @@ -90,9 +77,7 @@
-
-
-
+
diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts index 7baf34ca2..1fe8d0f9d 100644 --- a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts +++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts @@ -3,11 +3,10 @@ import { switchMap } from 'rxjs/operators' import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils' import { environment } from 'src/environments/environment' import { Component, OnInit } from '@angular/core' -import { DomSanitizer } from '@angular/platform-browser' import { ActivatedRoute, Router } from '@angular/router' import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable, ServerService } from '@app/core' import { AdvancedInputFilter } from '@app/shared/shared-forms' -import { DropdownAction, Video, VideoService } from '@app/shared/shared-main' +import { DropdownAction, VideoService } from '@app/shared/shared-main' import { VideoBlockService } from '@app/shared/shared-moderation' import { buildVideoEmbedLink, decorateVideoLink } from '@shared/core-utils' import { VideoBlacklist, VideoBlacklistType } from '@shared/models' @@ -18,7 +17,7 @@ import { VideoBlacklist, VideoBlacklistType } from '@shared/models' styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-block-list.component.scss' ] }) export class VideoBlockListComponent extends RestTable implements OnInit { - blocklist: (VideoBlacklist & { reasonHtml?: string, embedHtml?: string })[] = [] + blocklist: (VideoBlacklist & { reasonHtml?: string })[] = [] totalRecords = 0 sort: SortMeta = { field: 'createdAt', order: -1 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 } @@ -50,7 +49,6 @@ export class VideoBlockListComponent extends RestTable implements OnInit { private confirmService: ConfirmService, private videoBlocklistService: VideoBlockService, private markdownRenderer: MarkdownService, - private sanitizer: DomSanitizer, private videoService: VideoService ) { super() @@ -125,10 +123,6 @@ export class VideoBlockListComponent extends RestTable implements OnInit { return 'VideoBlockListComponent' } - getVideoUrl (videoBlock: VideoBlacklist) { - return Video.buildWatchUrl(videoBlock.video) - } - toHtml (text: string) { return this.markdownRenderer.textMarkdownToHTML(text) } @@ -176,8 +170,7 @@ export class VideoBlockListComponent extends RestTable implements OnInit { for (const element of this.blocklist) { Object.assign(element, { - reasonHtml: await this.toHtml(element.reason), - embedHtml: this.sanitizer.bypassSecurityTrustHtml(this.getVideoEmbed(element)) + reasonHtml: await this.toHtml(element.reason) }) } }, diff --git a/client/src/app/+admin/overview/index.ts b/client/src/app/+admin/overview/index.ts index b71a6a45f..a9c46893f 100644 --- a/client/src/app/+admin/overview/index.ts +++ b/client/src/app/+admin/overview/index.ts @@ -1,2 +1,3 @@ export * from './users' +export * from './videos' export * from './overview.routes' diff --git a/client/src/app/+admin/overview/overview.routes.ts b/client/src/app/+admin/overview/overview.routes.ts index cb5986072..1e6686d16 100644 --- a/client/src/app/+admin/overview/overview.routes.ts +++ b/client/src/app/+admin/overview/overview.routes.ts @@ -1,6 +1,8 @@ import { Routes } from '@angular/router' import { UsersRoutes } from './users' +import { VideosRoutes } from './videos' export const OverviewRoutes: Routes = [ - ...UsersRoutes + ...UsersRoutes, + ...VideosRoutes ] diff --git a/client/src/app/+admin/overview/videos/index.ts b/client/src/app/+admin/overview/videos/index.ts new file mode 100644 index 000000000..40c2ffe72 --- /dev/null +++ b/client/src/app/+admin/overview/videos/index.ts @@ -0,0 +1,2 @@ +export * from './video-list.component' +export * from './video.routes' diff --git a/client/src/app/+admin/overview/videos/video-list.component.html b/client/src/app/+admin/overview/videos/video-list.component.html new file mode 100644 index 000000000..1f1e9cc6e --- /dev/null +++ b/client/src/app/+admin/overview/videos/video-list.component.html @@ -0,0 +1,86 @@ +

+ + Videos +

+ + + +
+
+ + +
+ +
+ +
+ +
+
+ + + + + + + + + Video + Info + Published + + + + + + + + + + + + + + + + + + + + + + + + {{ video.privacy.label }} + NSFW + NSFW + + + + {{ video.publishedAt | date: 'short' }} + + + + + + + + + + + + +
diff --git a/client/src/app/+admin/overview/videos/video-list.component.scss b/client/src/app/+admin/overview/videos/video-list.component.scss new file mode 100644 index 000000000..fcdb457f2 --- /dev/null +++ b/client/src/app/+admin/overview/videos/video-list.component.scss @@ -0,0 +1,10 @@ +@use '_variables' as *; +@use '_mixins' as *; +my-embed { + display: block; + max-width: 500px; +} + +.badge { + @include table-badge; +} diff --git a/client/src/app/+admin/overview/videos/video-list.component.ts b/client/src/app/+admin/overview/videos/video-list.component.ts new file mode 100644 index 000000000..a445bc209 --- /dev/null +++ b/client/src/app/+admin/overview/videos/video-list.component.ts @@ -0,0 +1,123 @@ +import { SortMeta } from 'primeng/api' +import { Component, OnInit } from '@angular/core' +import { ActivatedRoute, Router } from '@angular/router' +import { AuthService, ConfirmService, Notifier, RestPagination, RestTable } from '@app/core' +import { DropdownAction, Video, VideoService } from '@app/shared/shared-main' +import { UserRight } from '@shared/models' +import { AdvancedInputFilter } from '@app/shared/shared-forms' +import { VideoActionsDisplayType } from '@app/shared/shared-video-miniature' + +@Component({ + selector: 'my-video-list', + templateUrl: './video-list.component.html', + styleUrls: [ './video-list.component.scss' ] +}) +export class VideoListComponent extends RestTable implements OnInit { + videos: Video[] = [] + + totalRecords = 0 + sort: SortMeta = { field: 'publishedAt', order: 1 } + pagination: RestPagination = { count: this.rowsPerPage, start: 0 } + + bulkVideoActions: DropdownAction[][] = [] + + selectedVideos: Video[] = [] + + inputFilters: AdvancedInputFilter[] = [ + { + title: $localize`Advanced filters`, + children: [ + { + queryParams: { search: 'local:true' }, + label: $localize`Only local videos` + } + ] + } + ] + + videoActionsOptions: VideoActionsDisplayType = { + playlist: false, + download: false, + update: true, + blacklist: true, + delete: true, + report: false, + duplicate: true, + mute: true, + liveInfo: false + } + + constructor ( + protected route: ActivatedRoute, + protected router: Router, + private confirmService: ConfirmService, + private auth: AuthService, + private notifier: Notifier, + private videoService: VideoService + ) { + super() + } + + get authUser () { + return this.auth.getUser() + } + + ngOnInit () { + this.initialize() + + this.bulkVideoActions = [ + [ + { + label: $localize`Delete`, + handler: videos => this.removeVideos(videos), + isDisplayed: () => this.authUser.hasRight(UserRight.REMOVE_ANY_VIDEO) + } + ] + ] + } + + getIdentifier () { + return 'VideoListComponent' + } + + isInSelectionMode () { + return this.selectedVideos.length !== 0 + } + + onVideoRemoved () { + this.reloadData() + } + + protected reloadData () { + this.selectedVideos = [] + + this.videoService.getAdminVideos({ + pagination: this.pagination, + sort: this.sort, + search: this.search + }).subscribe({ + next: resultList => { + this.videos = resultList.data + this.totalRecords = resultList.total + }, + + error: err => this.notifier.error(err.message) + }) + } + + private async removeVideos (videos: Video[]) { + const message = $localize`Are you sure you want to delete these ${videos.length} videos?` + const res = await this.confirmService.confirm(message, $localize`Delete`) + if (res === false) return + + this.videoService.removeVideo(videos.map(v => v.id)) + .subscribe({ + next: () => { + this.notifier.success($localize`${videos.length} videos deleted.`) + this.reloadData() + }, + + error: err => this.notifier.error(err.message) + }) + } +} diff --git a/client/src/app/+admin/overview/videos/video.routes.ts b/client/src/app/+admin/overview/videos/video.routes.ts new file mode 100644 index 000000000..984df7b82 --- /dev/null +++ b/client/src/app/+admin/overview/videos/video.routes.ts @@ -0,0 +1,30 @@ +import { Routes } from '@angular/router' +import { UserRightGuard } from '@app/core' +import { UserRight } from '@shared/models' +import { VideoListComponent } from './video-list.component' + +export const VideosRoutes: Routes = [ + { + path: 'videos', + canActivate: [ UserRightGuard ], + data: { + userRight: UserRight.SEE_ALL_VIDEOS + }, + children: [ + { + path: '', + redirectTo: 'list', + pathMatch: 'full' + }, + { + path: 'list', + component: VideoListComponent, + data: { + meta: { + title: $localize`Videos list` + } + } + } + ] + } +] -- cgit v1.2.3