Some fixes for admin videos list

pull/4481/head
Chocobozzz 2021-11-02 11:00:40 +01:00
parent fd5fa94bbc
commit 7e7d8e4853
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
12 changed files with 54 additions and 54 deletions

View File

@ -69,7 +69,7 @@
<span *ngIf="video.nsfw" class="badge badge-red" i18n>NSFW</span> <span *ngIf="video.nsfw" class="badge badge-red" i18n>NSFW</span>
<span *ngIf="isUnpublished(video.state.id)" class="badge badge-yellow" i18n>Not published yet</span> <span *ngIf="isUnpublished(video.state.id)" class="badge badge-yellow" i18n>{{ video.state.label }}</span>
<span *ngIf="isAccountBlocked(video)" class="badge badge-red" i18n>Account muted</span> <span *ngIf="isAccountBlocked(video)" class="badge badge-red" i18n>Account muted</span>
<span *ngIf="isServerBlocked(video)" class="badge badge-red" i18n>Server muted</span> <span *ngIf="isServerBlocked(video)" class="badge badge-red" i18n>Server muted</span>
@ -80,8 +80,9 @@
<td> <td>
<span *ngIf="isHLS(video)" class="badge badge-blue">HLS</span> <span *ngIf="isHLS(video)" class="badge badge-blue">HLS</span>
<span *ngIf="isWebTorrent(video)" class="badge badge-blue">WebTorrent</span> <span *ngIf="isWebTorrent(video)" class="badge badge-blue">WebTorrent</span>
<span *ngIf="video.isLive" class="badge badge-blue">Live</span>
<span *ngIf="!video.remote">{{ getFilesSize(video) | bytes: 1 }}</span> <span *ngIf="!video.isLive && video.isLocal">{{ getFilesSize(video) | bytes: 1 }}</span>
</td> </td>
<td> <td>

View File

@ -16,7 +16,7 @@ export class VideoListComponent extends RestTable implements OnInit {
videos: Video[] = [] videos: Video[] = []
totalRecords = 0 totalRecords = 0
sort: SortMeta = { field: 'publishedAt', order: 1 } sort: SortMeta = { field: 'publishedAt', order: -1 }
pagination: RestPagination = { count: this.rowsPerPage, start: 0 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
bulkVideoActions: DropdownAction<Video[]>[][] = [] bulkVideoActions: DropdownAction<Video[]>[][] = []
@ -99,7 +99,7 @@ export class VideoListComponent extends RestTable implements OnInit {
} }
isUnpublished (state: VideoState) { isUnpublished (state: VideoState) {
return state !== VideoState.PUBLISHED return state !== VideoState.LIVE_ENDED && state !== VideoState.PUBLISHED
} }
isAccountBlocked (video: Video) { isAccountBlocked (video: Video) {

View File

@ -48,7 +48,7 @@ export type CommonVideoParams = {
@Injectable() @Injectable()
export class VideoService { export class VideoService {
static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/' static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos'
static BASE_FEEDS_URL = environment.apiUrl + '/feeds/videos.' static BASE_FEEDS_URL = environment.apiUrl + '/feeds/videos.'
static BASE_SUBSCRIPTION_FEEDS_URL = environment.apiUrl + '/feeds/subscriptions.' static BASE_SUBSCRIPTION_FEEDS_URL = environment.apiUrl + '/feeds/subscriptions.'
@ -60,18 +60,18 @@ export class VideoService {
) {} ) {}
getVideoViewUrl (uuid: string) { getVideoViewUrl (uuid: string) {
return VideoService.BASE_VIDEO_URL + uuid + '/views' return VideoService.BASE_VIDEO_URL + '/' + uuid + '/views'
} }
getUserWatchingVideoUrl (uuid: string) { getUserWatchingVideoUrl (uuid: string) {
return VideoService.BASE_VIDEO_URL + uuid + '/watching' return VideoService.BASE_VIDEO_URL + '/' + uuid + '/watching'
} }
getVideo (options: { videoId: string }): Observable<VideoDetails> { getVideo (options: { videoId: string }): Observable<VideoDetails> {
return this.serverService.getServerLocale() return this.serverService.getServerLocale()
.pipe( .pipe(
switchMap(translations => { switchMap(translations => {
return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + options.videoId) return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + '/' + options.videoId)
.pipe(map(videoHash => ({ videoHash, translations }))) .pipe(map(videoHash => ({ videoHash, translations })))
}), }),
map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)), map(({ videoHash, translations }) => new VideoDetails(videoHash, translations)),
@ -111,7 +111,7 @@ export class VideoService {
const data = objectToFormData(body) const data = objectToFormData(body)
return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, data) return this.authHttp.put(VideoService.BASE_VIDEO_URL + '/' + video.id, data)
.pipe( .pipe(
map(this.restExtractor.extractDataBool), map(this.restExtractor.extractDataBool),
catchError(err => this.restExtractor.handleError(err)) catchError(err => this.restExtractor.handleError(err))
@ -119,7 +119,7 @@ export class VideoService {
} }
uploadVideo (video: FormData) { uploadVideo (video: FormData) {
const req = new HttpRequest('POST', VideoService.BASE_VIDEO_URL + 'upload', video, { reportProgress: true }) const req = new HttpRequest('POST', VideoService.BASE_VIDEO_URL + '/' + 'upload', video, { reportProgress: true })
return this.authHttp return this.authHttp
.request<{ video: { id: number, uuid: string } }>(req) .request<{ video: { id: number, uuid: string } }>(req)
@ -321,7 +321,7 @@ export class VideoService {
return from(ids) return from(ids)
.pipe( .pipe(
concatMap(id => this.authHttp.delete(VideoService.BASE_VIDEO_URL + id)), concatMap(id => this.authHttp.delete(VideoService.BASE_VIDEO_URL + '/' + id)),
toArray(), toArray(),
catchError(err => this.restExtractor.handleError(err)) catchError(err => this.restExtractor.handleError(err))
) )
@ -413,7 +413,7 @@ export class VideoService {
} }
private setVideoRate (id: number, rateType: UserVideoRateType) { private setVideoRate (id: number, rateType: UserVideoRateType) {
const url = VideoService.BASE_VIDEO_URL + id + '/rate' const url = VideoService.BASE_VIDEO_URL + '/' + id + '/rate'
const body: UserVideoRateUpdate = { const body: UserVideoRateUpdate = {
rating: rateType rating: rateType
} }

View File

@ -6,7 +6,7 @@ import { QueryTypes, Sequelize, Transaction } from 'sequelize'
* *
*/ */
export class AbstractVideosQueryBuilder { export class AbstractRunQuery {
protected sequelize: Sequelize protected sequelize: Sequelize
protected query: string protected query: string

View File

@ -1,8 +1,8 @@
import { createSafeIn } from '@server/models/utils' import { createSafeIn } from '@server/models/utils'
import { MUserAccountId } from '@server/types/models' import { MUserAccountId } from '@server/types/models'
import validator from 'validator' import validator from 'validator'
import { AbstractVideosQueryBuilder } from './abstract-videos-query-builder' import { AbstractRunQuery } from './abstract-run-query'
import { VideoTables } from './video-tables' import { VideoTableAttributes } from './video-table-attributes'
/** /**
* *
@ -10,18 +10,18 @@ import { VideoTables } from './video-tables'
* *
*/ */
export class AbstractVideosModelQueryBuilder extends AbstractVideosQueryBuilder { export class AbstractVideoQueryBuilder extends AbstractRunQuery {
protected attributes: { [key: string]: string } = {} protected attributes: { [key: string]: string } = {}
protected joins = '' protected joins = ''
protected where: string protected where: string
protected tables: VideoTables protected tables: VideoTableAttributes
constructor (protected readonly mode: 'list' | 'get') { constructor (protected readonly mode: 'list' | 'get') {
super() super()
this.tables = new VideoTables(this.mode) this.tables = new VideoTableAttributes(this.mode)
} }
protected buildSelect () { protected buildSelect () {

View File

@ -1,6 +1,6 @@
import { Sequelize } from 'sequelize' import { Sequelize } from 'sequelize'
import { BuildVideoGetQueryOptions } from '../video-model-get-query-builder' import { BuildVideoGetQueryOptions } from '../video-model-get-query-builder'
import { AbstractVideosModelQueryBuilder } from './abstract-videos-model-query-builder' import { AbstractVideoQueryBuilder } from './abstract-video-query-builder'
/** /**
* *
@ -8,7 +8,7 @@ import { AbstractVideosModelQueryBuilder } from './abstract-videos-model-query-b
* *
*/ */
export class VideoFileQueryBuilder extends AbstractVideosModelQueryBuilder { export class VideoFileQueryBuilder extends AbstractVideoQueryBuilder {
protected attributes: { [key: string]: string } protected attributes: { [key: string]: string }
constructor (protected readonly sequelize: Sequelize) { constructor (protected readonly sequelize: Sequelize) {

View File

@ -18,7 +18,7 @@ import { VideoChannelModel } from '../../video-channel'
import { VideoFileModel } from '../../video-file' import { VideoFileModel } from '../../video-file'
import { VideoLiveModel } from '../../video-live' import { VideoLiveModel } from '../../video-live'
import { VideoStreamingPlaylistModel } from '../../video-streaming-playlist' import { VideoStreamingPlaylistModel } from '../../video-streaming-playlist'
import { VideoTables } from './video-tables' import { VideoTableAttributes } from './video-table-attributes'
type SQLRow = { [id: string]: string | number } type SQLRow = { [id: string]: string | number }
@ -51,7 +51,7 @@ export class VideoModelBuilder {
constructor ( constructor (
readonly mode: 'get' | 'list', readonly mode: 'get' | 'list',
readonly tables: VideoTables readonly tables: VideoTableAttributes
) { ) {
} }

View File

@ -4,7 +4,7 @@
* Class to build video attributes/join names we want to fetch from the database * Class to build video attributes/join names we want to fetch from the database
* *
*/ */
export class VideoTables { export class VideoTableAttributes {
constructor (readonly mode: 'get' | 'list') { constructor (readonly mode: 'get' | 'list') {
@ -93,22 +93,20 @@ export class VideoTables {
} }
getStreamingPlaylistAttributes () { getStreamingPlaylistAttributes () {
let playlistKeys = [ 'id', 'playlistUrl', 'playlistFilename', 'type' ] return [
'id',
if (this.mode === 'get') { 'playlistUrl',
playlistKeys = playlistKeys.concat([ 'playlistFilename',
'p2pMediaLoaderInfohashes', 'type',
'p2pMediaLoaderPeerVersion', 'p2pMediaLoaderInfohashes',
'segmentsSha256Filename', 'p2pMediaLoaderPeerVersion',
'segmentsSha256Url', 'segmentsSha256Filename',
'videoId', 'segmentsSha256Url',
'createdAt', 'videoId',
'updatedAt', 'createdAt',
'storage' 'updatedAt',
]) 'storage'
} ]
return playlistKeys
} }
getUserHistoryAttributes () { getUserHistoryAttributes () {

View File

@ -1,8 +1,8 @@
import { Sequelize, Transaction } from 'sequelize' import { Sequelize, Transaction } from 'sequelize'
import { AbstractVideosModelQueryBuilder } from './shared/abstract-videos-model-query-builder' import { AbstractVideoQueryBuilder } from './shared/abstract-video-query-builder'
import { VideoFileQueryBuilder } from './shared/video-file-query-builder' import { VideoFileQueryBuilder } from './shared/video-file-query-builder'
import { VideoModelBuilder } from './shared/video-model-builder' import { VideoModelBuilder } from './shared/video-model-builder'
import { VideoTables } from './shared/video-tables' import { VideoTableAttributes } from './shared/video-table-attributes'
/** /**
* *
@ -46,7 +46,7 @@ export class VideoModelGetQueryBuilder {
this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
this.videoModelBuilder = new VideoModelBuilder('get', new VideoTables('get')) this.videoModelBuilder = new VideoModelBuilder('get', new VideoTableAttributes('get'))
} }
async queryVideo (options: BuildVideoGetQueryOptions) { async queryVideo (options: BuildVideoGetQueryOptions) {
@ -69,15 +69,16 @@ export class VideoModelGetQueryBuilder {
}) })
if (videos.length > 1) { if (videos.length > 1) {
throw new Error('Video results is more than ') throw new Error('Video results is more than 1')
} }
if (videos.length === 0) return null if (videos.length === 0) return null
return videos[0] return videos[0]
} }
} }
export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuilder { export class VideosModelGetQuerySubBuilder extends AbstractVideoQueryBuilder {
protected attributes: { [key: string]: string } protected attributes: { [key: string]: string }
protected webtorrentFilesQuery: string protected webtorrentFilesQuery: string

View File

@ -5,7 +5,7 @@ import { WEBSERVER } from '@server/initializers/constants'
import { buildDirectionAndField, createSafeIn } from '@server/models/utils' import { buildDirectionAndField, createSafeIn } from '@server/models/utils'
import { MUserAccountId, MUserId } from '@server/types/models' import { MUserAccountId, MUserId } from '@server/types/models'
import { VideoInclude, VideoPrivacy, VideoState } from '@shared/models' import { VideoInclude, VideoPrivacy, VideoState } from '@shared/models'
import { AbstractVideosQueryBuilder } from './shared/abstract-videos-query-builder' import { AbstractRunQuery } from './shared/abstract-run-query'
/** /**
* *
@ -72,7 +72,7 @@ export type BuildVideosListQueryOptions = {
having?: string having?: string
} }
export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder { export class VideosIdListQueryBuilder extends AbstractRunQuery {
protected replacements: any = {} protected replacements: any = {}
private attributes: string[] private attributes: string[]
@ -105,7 +105,7 @@ export class VideosIdListQueryBuilder extends AbstractVideosQueryBuilder {
return this.runQuery().then(rows => rows.length !== 0 ? rows[0].total : 0) return this.runQuery().then(rows => rows.length !== 0 ? rows[0].total : 0)
} }
getIdsListQueryAndSort (options: BuildVideosListQueryOptions) { getQuery (options: BuildVideosListQueryOptions) {
this.buildIdsListQuery(options) this.buildIdsListQuery(options)
return { query: this.query, sort: this.sort, replacements: this.replacements } return { query: this.query, sort: this.sort, replacements: this.replacements }

View File

@ -1,6 +1,6 @@
import { VideoInclude } from '@shared/models' import { VideoInclude } from '@shared/models'
import { Sequelize } from 'sequelize' import { Sequelize } from 'sequelize'
import { AbstractVideosModelQueryBuilder } from './shared/abstract-videos-model-query-builder' import { AbstractVideoQueryBuilder } from './shared/abstract-video-query-builder'
import { VideoModelBuilder } from './shared/video-model-builder' import { VideoModelBuilder } from './shared/video-model-builder'
import { BuildVideosListQueryOptions, VideosIdListQueryBuilder } from './videos-id-list-query-builder' import { BuildVideosListQueryOptions, VideosIdListQueryBuilder } from './videos-id-list-query-builder'
@ -10,7 +10,7 @@ import { BuildVideosListQueryOptions, VideosIdListQueryBuilder } from './videos-
* *
*/ */
export class VideosModelListQueryBuilder extends AbstractVideosModelQueryBuilder { export class VideosModelListQueryBuilder extends AbstractVideoQueryBuilder {
protected attributes: { [key: string]: string } protected attributes: { [key: string]: string }
private innerQuery: string private innerQuery: string
@ -26,7 +26,7 @@ export class VideosModelListQueryBuilder extends AbstractVideosModelQueryBuilder
queryVideos (options: BuildVideosListQueryOptions) { queryVideos (options: BuildVideosListQueryOptions) {
this.buildInnerQuery(options) this.buildInnerQuery(options)
this.buildListQueryFromIdsQuery(options) this.buildMainQuery(options)
return this.runQuery() return this.runQuery()
.then(rows => this.videoModelBuilder.buildVideosFromRows({ rows, include: options.include })) .then(rows => this.videoModelBuilder.buildVideosFromRows({ rows, include: options.include }))
@ -34,14 +34,14 @@ export class VideosModelListQueryBuilder extends AbstractVideosModelQueryBuilder
private buildInnerQuery (options: BuildVideosListQueryOptions) { private buildInnerQuery (options: BuildVideosListQueryOptions) {
const idsQueryBuilder = new VideosIdListQueryBuilder(this.sequelize) const idsQueryBuilder = new VideosIdListQueryBuilder(this.sequelize)
const { query, sort, replacements } = idsQueryBuilder.getIdsListQueryAndSort(options) const { query, sort, replacements } = idsQueryBuilder.getQuery(options)
this.replacements = replacements this.replacements = replacements
this.innerQuery = query this.innerQuery = query
this.innerSort = sort this.innerSort = sort
} }
private buildListQueryFromIdsQuery (options: BuildVideosListQueryOptions) { private buildMainQuery (options: BuildVideosListQueryOptions) {
this.attributes = { this.attributes = {
'"video".*': '' '"video".*': ''
} }

View File

@ -4805,7 +4805,7 @@ components:
required: false required: false
schema: schema:
type: boolean type: boolean
description: 'Display only local or remote videos' description: '**PeerTube >= 4.0** Display only local or remote videos'
include: include:
name: include name: include
in: query in: query
@ -4819,7 +4819,7 @@ components:
- 4 - 4
- 8 - 8
description: > description: >
Include additional videos in results (can be combined using bitwise or operator) **PeerTube >= 4.0** Include additional videos in results (can be combined using bitwise or operator)
- `0` NONE - `0` NONE