Add filter inputs for blacklisted videos and muted accounts/servers

pull/2711/head
Rigel Kent 2020-04-19 14:11:40 +02:00 committed by Rigel Kent
parent aeb1bed983
commit e0a929179a
19 changed files with 202 additions and 61 deletions

View File

@ -1,9 +1,19 @@
<p-table <p-table
[value]="blockedAccounts" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [value]="blockedAccounts" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
[showCurrentPageReport]="true" i18n-currentPageReportTemplate [showCurrentPageReport]="true" i18n-currentPageReportTemplate
currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted accounts" currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted accounts"
> >
<ng-template pTemplate="caption">
<div class="caption">
<div class="ml-auto">
<input
type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
(keyup)="onSearch($event)"
>
</div>
</div>
</ng-template>
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>

View File

@ -7,13 +7,14 @@ import { AccountBlock, BlocklistService } from '@app/shared/blocklist'
@Component({ @Component({
selector: 'my-instance-account-blocklist', selector: 'my-instance-account-blocklist',
styleUrls: [ './instance-account-blocklist.component.scss' ], styleUrls: [ '../moderation.component.scss', './instance-account-blocklist.component.scss' ],
templateUrl: './instance-account-blocklist.component.html' templateUrl: './instance-account-blocklist.component.html'
}) })
export class InstanceAccountBlocklistComponent extends RestTable implements OnInit { export class InstanceAccountBlocklistComponent extends RestTable implements OnInit {
blockedAccounts: AccountBlock[] = [] blockedAccounts: AccountBlock[] = []
totalRecords = 0 totalRecords = 0
rowsPerPage = 10 rowsPerPageOptions = [ 20, 50, 100 ]
rowsPerPage = this.rowsPerPageOptions[0]
sort: SortMeta = { field: 'createdAt', order: -1 } sort: SortMeta = { field: 'createdAt', order: -1 }
pagination: RestPagination = { count: this.rowsPerPage, start: 0 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
@ -49,7 +50,11 @@ export class InstanceAccountBlocklistComponent extends RestTable implements OnIn
} }
protected loadData () { protected loadData () {
return this.blocklistService.getInstanceAccountBlocklist(this.pagination, this.sort) return this.blocklistService.getInstanceAccountBlocklist({
pagination: this.pagination,
sort: this.sort,
search: this.search
})
.subscribe( .subscribe(
resultList => { resultList => {
this.blockedAccounts = resultList.data this.blockedAccounts = resultList.data

View File

@ -1,12 +1,18 @@
<p-table <p-table
[value]="blockedServers" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [value]="blockedServers" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)"
[showCurrentPageReport]="true" i18n-currentPageReportTemplate [showCurrentPageReport]="true" i18n-currentPageReportTemplate
currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted instances" currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted instances"
> >
<ng-template pTemplate="caption"> <ng-template pTemplate="caption">
<div class="caption"> <div class="caption">
<a class="ml-auto block-button" (click)="addServersToBlock()" (key.enter)="addServersToBlock()"> <div class="ml-auto">
<input
type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
(keyup)="onSearch($event)"
>
</div>
<a class="ml-2 block-button" (click)="addServersToBlock()" (key.enter)="addServersToBlock()">
<my-global-icon iconName="add"></my-global-icon> <my-global-icon iconName="add"></my-global-icon>
<ng-container i18n>Mute domain</ng-container> <ng-container i18n>Mute domain</ng-container>
</a> </a>

View File

@ -9,7 +9,7 @@ import { BatchDomainsModalComponent } from '@app/+admin/config/shared/batch-doma
@Component({ @Component({
selector: 'my-instance-server-blocklist', selector: 'my-instance-server-blocklist',
styleUrls: [ './instance-server-blocklist.component.scss' ], styleUrls: [ '../moderation.component.scss', './instance-server-blocklist.component.scss' ],
templateUrl: './instance-server-blocklist.component.html' templateUrl: './instance-server-blocklist.component.html'
}) })
export class InstanceServerBlocklistComponent extends RestTable implements OnInit { export class InstanceServerBlocklistComponent extends RestTable implements OnInit {
@ -17,7 +17,8 @@ export class InstanceServerBlocklistComponent extends RestTable implements OnIni
blockedServers: ServerBlock[] = [] blockedServers: ServerBlock[] = []
totalRecords = 0 totalRecords = 0
rowsPerPage = 10 rowsPerPageOptions = [ 20, 50, 100 ]
rowsPerPage = this.rowsPerPageOptions[0]
sort: SortMeta = { field: 'createdAt', order: -1 } sort: SortMeta = { field: 'createdAt', order: -1 }
pagination: RestPagination = { count: this.rowsPerPage, start: 0 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
@ -72,7 +73,11 @@ export class InstanceServerBlocklistComponent extends RestTable implements OnIni
} }
protected loadData () { protected loadData () {
return this.blocklistService.getInstanceServerBlocklist(this.pagination, this.sort) return this.blocklistService.getInstanceServerBlocklist({
pagination: this.pagination,
sort: this.sort,
search: this.search
})
.subscribe( .subscribe(
resultList => { resultList => {
this.blockedServers = resultList.data this.blockedServers = resultList.data

View File

@ -7,6 +7,14 @@
margin-right: 30px; margin-right: 30px;
} }
.caption {
justify-content: flex-end;
input {
@include peertube-input-text(250px);
}
}
.moderation-expanded { .moderation-expanded {
font-size: 90%; font-size: 90%;

View File

@ -1,14 +1,6 @@
@import 'mixins'; @import 'mixins';
@import 'miniature'; @import 'miniature';
.caption {
justify-content: flex-end;
input {
@include peertube-input-text(250px);
}
}
.video-details-date-updated { .video-details-date-updated {
font-size: 90%; font-size: 90%;
margin-top: .1rem; margin-top: .1rem;

View File

@ -1,9 +1,20 @@
<p-table <p-table
[value]="blacklist" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [value]="blacklist" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
[sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
[showCurrentPageReport]="true" i18n-currentPageReportTemplate [showCurrentPageReport]="true" i18n-currentPageReportTemplate
currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} blacklisted videos" currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} blacklisted videos"
> >
<ng-template pTemplate="caption">
<div class="caption">
<div class="ml-auto">
<input
type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
(keyup)="onSearch($event)"
>
</div>
</div>
</ng-template>
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th style="width: 40px"></th> <th style="width: 40px"></th>
@ -33,7 +44,7 @@
<div class="video-table-video-text"> <div class="video-table-video-text">
<div> <div>
{{ videoBlacklist.video.name }} {{ videoBlacklist.video.name }}
<span class="glyphicon glyphicon-new-window"></span> <span i18n-title title="Video was blacklisted" class="glyphicon glyphicon-ban-circle"></span>
</div> </div>
<div class="text-muted">by {{ videoBlacklist.video.channel?.displayName }} on {{ videoBlacklist.video.channel?.host }} </div> <div class="text-muted">by {{ videoBlacklist.video.channel?.displayName }} on {{ videoBlacklist.video.channel?.host }} </div>
</div> </div>
@ -53,7 +64,10 @@
</ng-container> </ng-container>
<td class="action-cell"> <td class="action-cell">
<my-action-dropdown i18n-label placement="bottom-right" label="Actions" [actions]="videoBlacklistActions" [entry]="videoBlacklist"></my-action-dropdown> <my-action-dropdown
[ngClass]="{ 'show': expanded }" placement="bottom-right" container="body"
i18n-label label="Actions" [actions]="videoBlacklistActions" [entry]="videoBlacklist"
></my-action-dropdown>
</td> </td>
</tr> </tr>
</ng-template> </ng-template>
@ -61,8 +75,10 @@
<ng-template pTemplate="rowexpansion" let-videoBlacklist> <ng-template pTemplate="rowexpansion" let-videoBlacklist>
<tr> <tr>
<td class="expand-cell" colspan="6"> <td class="expand-cell" colspan="6">
<span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span> <div class="d-flex moderation-expanded">
<span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span> <span class="col-2 moderation-expanded-label" i18n>Blacklist reason:</span>
<span class="col-9 moderation-expanded-text" [innerHTML]="videoBlacklist.reasonHtml"></span>
</div>
</td> </td>
</tr> </tr>
</ng-template> </ng-template>

View File

@ -17,7 +17,8 @@ import { MarkdownService } from '@app/shared/renderer'
export class VideoBlacklistListComponent extends RestTable implements OnInit { export class VideoBlacklistListComponent extends RestTable implements OnInit {
blacklist: (VideoBlacklist & { reasonHtml?: string })[] = [] blacklist: (VideoBlacklist & { reasonHtml?: string })[] = []
totalRecords = 0 totalRecords = 0
rowsPerPage = 10 rowsPerPageOptions = [ 20, 50, 100 ]
rowsPerPage = this.rowsPerPageOptions[0]
sort: SortMeta = { field: 'createdAt', order: -1 } sort: SortMeta = { field: 'createdAt', order: -1 }
pagination: RestPagination = { count: this.rowsPerPage, start: 0 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
listBlacklistTypeFilter: VideoBlacklistType = undefined listBlacklistTypeFilter: VideoBlacklistType = undefined
@ -38,7 +39,7 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
ngOnInit () { ngOnInit () {
this.serverService.getConfig() this.serverService.getConfig()
.subscribe(config => { .subscribe(config => {
// don't filter if auto-blacklist not enabled as this will be the only list // don't filter if auto-blacklist is not enabled as this will be the only list
if (config.autoBlacklist.videos.ofUsers.enabled) { if (config.autoBlacklist.videos.ofUsers.enabled) {
this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL this.listBlacklistTypeFilter = VideoBlacklistType.MANUAL
} }
@ -91,7 +92,12 @@ export class VideoBlacklistListComponent extends RestTable implements OnInit {
} }
protected loadData () { protected loadData () {
this.videoBlacklistService.listBlacklist(this.pagination, this.sort, this.listBlacklistTypeFilter) this.videoBlacklistService.listBlacklist({
pagination: this.pagination,
sort: this.sort,
search: this.search,
type: this.listBlacklistTypeFilter
})
.subscribe( .subscribe(
async resultList => { async resultList => {
this.totalRecords = resultList.total this.totalRecords = resultList.total

View File

@ -76,10 +76,14 @@ export class BlocklistService {
/*********************** Instance -> Account blocklist ***********************/ /*********************** Instance -> Account blocklist ***********************/
getInstanceAccountBlocklist (pagination: RestPagination, sort: SortMeta) { getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) {
const { pagination, sort, search } = options
let params = new HttpParams() let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination, sort) params = this.restService.addRestGetParams(params, pagination, sort)
if (search) params = params.append('search', search)
return this.authHttp.get<ResultList<AccountBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/accounts', { params }) return this.authHttp.get<ResultList<AccountBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/accounts', { params })
.pipe( .pipe(
map(res => this.restExtractor.convertResultListDateToHuman(res)), map(res => this.restExtractor.convertResultListDateToHuman(res)),
@ -104,10 +108,14 @@ export class BlocklistService {
/*********************** Instance -> Server blocklist ***********************/ /*********************** Instance -> Server blocklist ***********************/
getInstanceServerBlocklist (pagination: RestPagination, sort: SortMeta) { getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search: string }) {
const { pagination, sort, search } = options
let params = new HttpParams() let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination, sort) params = this.restService.addRestGetParams(params, pagination, sort)
if (search) params = params.append('search', search)
return this.authHttp.get<ResultList<ServerBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/servers', { params }) return this.authHttp.get<ResultList<ServerBlock>>(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/servers', { params })
.pipe( .pipe(
map(res => this.restExtractor.convertResultListDateToHuman(res)), map(res => this.restExtractor.convertResultListDateToHuman(res)),

View File

@ -19,13 +19,19 @@ export class VideoBlacklistService {
private restExtractor: RestExtractor private restExtractor: RestExtractor
) {} ) {}
listBlacklist (pagination: RestPagination, sort: SortMeta, type?: VideoBlacklistType): Observable<ResultList<VideoBlacklist>> { listBlacklist (options: {
pagination: RestPagination,
sort: SortMeta,
search?: string
type?: VideoBlacklistType
}): Observable<ResultList<VideoBlacklist>> {
const { pagination, sort, search, type } = options
let params = new HttpParams() let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination, sort) params = this.restService.addRestGetParams(params, pagination, sort)
if (type) { if (search) params = params.append('search', search)
params = params.set('type', type.toString()) if (type) params = params.append('type', type.toString())
}
return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params }) return this.authHttp.get<ResultList<VideoBlacklist>>(VideoBlacklistService.BASE_VIDEOS_URL + 'blacklist', { params })
.pipe( .pipe(

View File

@ -82,7 +82,13 @@ export {
async function listBlockedAccounts (req: express.Request, res: express.Response) { async function listBlockedAccounts (req: express.Request, res: express.Response) {
const serverActor = await getServerActor() const serverActor = await getServerActor()
const resultList = await AccountBlocklistModel.listForApi(serverActor.Account.id, req.query.start, req.query.count, req.query.sort) const resultList = await AccountBlocklistModel.listForApi({
start: req.query.start,
count: req.query.count,
sort: req.query.sort,
search: req.query.search,
accountId: serverActor.Account.id
})
return res.json(getFormattedObjects(resultList.data, resultList.total)) return res.json(getFormattedObjects(resultList.data, resultList.total))
} }
@ -107,7 +113,13 @@ async function unblockAccount (req: express.Request, res: express.Response) {
async function listBlockedServers (req: express.Request, res: express.Response) { async function listBlockedServers (req: express.Request, res: express.Response) {
const serverActor = await getServerActor() const serverActor = await getServerActor()
const resultList = await ServerBlocklistModel.listForApi(serverActor.Account.id, req.query.start, req.query.count, req.query.sort) const resultList = await ServerBlocklistModel.listForApi({
start: req.query.start,
count: req.query.count,
sort: req.query.sort,
search: req.query.search,
accountId: serverActor.Account.id
})
return res.json(getFormattedObjects(resultList.data, resultList.total)) return res.json(getFormattedObjects(resultList.data, resultList.total))
} }

View File

@ -74,7 +74,13 @@ export {
async function listBlockedAccounts (req: express.Request, res: express.Response) { async function listBlockedAccounts (req: express.Request, res: express.Response) {
const user = res.locals.oauth.token.User const user = res.locals.oauth.token.User
const resultList = await AccountBlocklistModel.listForApi(user.Account.id, req.query.start, req.query.count, req.query.sort) const resultList = await AccountBlocklistModel.listForApi({
start: req.query.start,
count: req.query.count,
sort: req.query.sort,
search: req.query.search,
accountId: user.Account.id
})
return res.json(getFormattedObjects(resultList.data, resultList.total)) return res.json(getFormattedObjects(resultList.data, resultList.total))
} }
@ -99,7 +105,13 @@ async function unblockAccount (req: express.Request, res: express.Response) {
async function listBlockedServers (req: express.Request, res: express.Response) { async function listBlockedServers (req: express.Request, res: express.Response) {
const user = res.locals.oauth.token.User const user = res.locals.oauth.token.User
const resultList = await ServerBlocklistModel.listForApi(user.Account.id, req.query.start, req.query.count, req.query.sort) const resultList = await ServerBlocklistModel.listForApi({
start: req.query.start,
count: req.query.count,
sort: req.query.sort,
search: req.query.search,
accountId: user.Account.id
})
return res.json(getFormattedObjects(resultList.data, resultList.total)) return res.json(getFormattedObjects(resultList.data, resultList.total))
} }

View File

@ -102,7 +102,13 @@ async function updateVideoBlacklistController (req: express.Request, res: expres
} }
async function listBlacklist (req: express.Request, res: express.Response) { async function listBlacklist (req: express.Request, res: express.Response) {
const resultList = await VideoBlacklistModel.listForApi(req.query.start, req.query.count, req.query.sort, req.query.type) const resultList = await VideoBlacklistModel.listForApi({
start: req.query.start,
count: req.query.count,
sort: req.query.sort,
search: req.query.search,
type: req.query.type
})
return res.json(getFormattedObjects(resultList.data, resultList.total)) return res.json(getFormattedObjects(resultList.data, resultList.total))
} }

View File

@ -69,6 +69,10 @@ const videosBlacklistFiltersValidator = [
query('type') query('type')
.optional() .optional()
.custom(isVideoBlacklistTypeValid).withMessage('Should have a valid video blacklist type attribute'), .custom(isVideoBlacklistTypeValid).withMessage('Should have a valid video blacklist type attribute'),
query('search')
.optional()
.not()
.isEmpty().withMessage('Should have a valid search'),
(req: express.Request, res: express.Response, next: express.NextFunction) => { (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking videos blacklist filters query', { parameters: req.query }) logger.debug('Checking videos blacklist filters query', { parameters: req.query })

View File

@ -1,6 +1,6 @@
import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { AccountModel } from './account' import { AccountModel } from './account'
import { getSort } from '../utils' import { getSort, searchAttribute } from '../utils'
import { AccountBlock } from '../../../shared/models/blocklist' import { AccountBlock } from '../../../shared/models/blocklist'
import { Op } from 'sequelize' import { Op } from 'sequelize'
import * as Bluebird from 'bluebird' import * as Bluebird from 'bluebird'
@ -111,16 +111,36 @@ export class AccountBlocklistModel extends Model<AccountBlocklistModel> {
return AccountBlocklistModel.findOne(query) return AccountBlocklistModel.findOne(query)
} }
static listForApi (accountId: number, start: number, count: number, sort: string) { static listForApi (parameters: {
start: number
count: number
sort: string
search?: string
accountId: number
}) {
const { start, count, sort, search, accountId } = parameters
const query = { const query = {
offset: start, offset: start,
limit: count, limit: count,
order: getSort(sort), order: getSort(sort)
where: {
accountId
}
} }
const where = {
accountId
}
if (search) {
Object.assign(where, {
[Op.or]: [
{ ...searchAttribute(search, '$BlockedAccount.name$') },
{ ...searchAttribute(search, '$BlockedAccount.Actor.url$') }
]
})
}
Object.assign(query, { where })
return AccountBlocklistModel return AccountBlocklistModel
.scope([ ScopeNames.WITH_ACCOUNTS ]) .scope([ ScopeNames.WITH_ACCOUNTS ])
.findAndCountAll<MAccountBlocklistAccounts>(query) .findAndCountAll<MAccountBlocklistAccounts>(query)

View File

@ -2,7 +2,7 @@ import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, Updated
import { AccountModel } from '../account/account' import { AccountModel } from '../account/account'
import { ServerModel } from './server' import { ServerModel } from './server'
import { ServerBlock } from '../../../shared/models/blocklist' import { ServerBlock } from '../../../shared/models/blocklist'
import { getSort } from '../utils' import { getSort, searchAttribute } from '../utils'
import * as Bluebird from 'bluebird' import * as Bluebird from 'bluebird'
import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/typings/models' import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/typings/models'
import { Op } from 'sequelize' import { Op } from 'sequelize'
@ -120,16 +120,27 @@ export class ServerBlocklistModel extends Model<ServerBlocklistModel> {
return ServerBlocklistModel.findOne(query) return ServerBlocklistModel.findOne(query)
} }
static listForApi (accountId: number, start: number, count: number, sort: string) { static listForApi (parameters: {
start: number
count: number
sort: string
search?: string
accountId: number
}) {
const { start, count, sort, search, accountId } = parameters
const query = { const query = {
offset: start, offset: start,
limit: count, limit: count,
order: getSort(sort), order: getSort(sort),
where: { where: {
accountId accountId,
...searchAttribute(search, '$BlockedServer.host$')
} }
} }
console.log(search)
return ServerBlocklistModel return ServerBlocklistModel
.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_SERVER ]) .scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_SERVER ])
.findAndCountAll<MServerBlocklistAccountServer>(query) .findAndCountAll<MServerBlocklistAccountServer>(query)

View File

@ -1,7 +1,7 @@
import { Model, Sequelize } from 'sequelize-typescript' import { Model, Sequelize } from 'sequelize-typescript'
import validator from 'validator' import validator from 'validator'
import { Col } from 'sequelize/types/lib/utils' import { Col } from 'sequelize/types/lib/utils'
import { literal, OrderItem } from 'sequelize' import { literal, OrderItem, Op } from 'sequelize'
type Primitive = string | Function | number | boolean | Symbol | undefined | null type Primitive = string | Function | number | boolean | Symbol | undefined | null
type DeepOmitHelper<T, K extends keyof T> = { type DeepOmitHelper<T, K extends keyof T> = {
@ -207,6 +207,16 @@ function buildDirectionAndField (value: string) {
return { direction, field } return { direction, field }
} }
function searchAttribute (sourceField, targetField) {
return sourceField
? {
[targetField]: {
[Op.iLike]: `%${sourceField}%`
}
}
: {}
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
export { export {
@ -228,7 +238,8 @@ export {
parseAggregateResult, parseAggregateResult,
getFollowsSort, getFollowsSort,
buildDirectionAndField, buildDirectionAndField,
createSafeIn createSafeIn,
searchAttribute
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -9,7 +9,7 @@ import {
isVideoAbuseStateValid isVideoAbuseStateValid
} from '../../helpers/custom-validators/video-abuses' } from '../../helpers/custom-validators/video-abuses'
import { AccountModel } from '../account/account' import { AccountModel } from '../account/account'
import { buildBlockedAccountSQL, getSort, throwIfNotValid } from '../utils' import { buildBlockedAccountSQL, getSort, throwIfNotValid, searchAttribute } from '../utils'
import { VideoModel } from './video' import { VideoModel } from './video'
import { VideoAbuseState, VideoDetails } from '../../../shared' import { VideoAbuseState, VideoDetails } from '../../../shared'
import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants' import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants'
@ -17,8 +17,8 @@ import { MUserAccountId, MVideoAbuse, MVideoAbuseFormattable, MVideoAbuseVideo }
import * as Bluebird from 'bluebird' import * as Bluebird from 'bluebird'
import { literal, Op } from 'sequelize' import { literal, Op } from 'sequelize'
import { ThumbnailModel } from './thumbnail' import { ThumbnailModel } from './thumbnail'
import { VideoChannelModel } from './video-channel'
import { VideoBlacklistModel } from './video-blacklist' import { VideoBlacklistModel } from './video-blacklist'
import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
export enum ScopeNames { export enum ScopeNames {
FOR_API = 'FOR_API' FOR_API = 'FOR_API'
@ -33,12 +33,6 @@ export enum ScopeNames {
serverAccountId: number serverAccountId: number
userAccountId: any userAccountId: any
}) => { }) => {
const search = (sourceField, targetField) => sourceField ? ({
[targetField]: {
[Op.iLike]: `%${sourceField}%`
}
}) : {}
let where = { let where = {
reporterAccountId: { reporterAccountId: {
[Op.notIn]: literal('(' + buildBlockedAccountSQL(options.serverAccountId, options.userAccountId) + ')') [Op.notIn]: literal('(' + buildBlockedAccountSQL(options.serverAccountId, options.userAccountId) + ')')
@ -148,19 +142,19 @@ export enum ScopeNames {
{ {
model: AccountModel, model: AccountModel,
required: true, required: true,
where: { ...search(options.searchReporter, 'name') } where: { ...searchAttribute(options.searchReporter, 'name') }
}, },
{ {
model: VideoModel, model: VideoModel,
required: false, required: false,
where: { ...search(options.searchVideo, 'name') }, where: { ...searchAttribute(options.searchVideo, 'name') },
include: [ include: [
{ {
model: ThumbnailModel model: ThumbnailModel
}, },
{ {
model: VideoChannelModel.scope([ 'WITH_ACTOR', 'WITH_ACCOUNT' ]), model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }),
where: { ...search(options.searchVideoChannel, 'name') } where: { ...searchAttribute(options.searchVideoChannel, 'name') }
}, },
{ {
attributes: [ 'id', 'reason', 'unfederated' ], attributes: [ 'id', 'reason', 'unfederated' ],

View File

@ -1,5 +1,5 @@
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { getBlacklistSort, SortType, throwIfNotValid } from '../utils' import { getBlacklistSort, SortType, throwIfNotValid, searchAttribute } from '../utils'
import { VideoModel } from './video' import { VideoModel } from './video'
import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel' import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
@ -54,7 +54,15 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
}) })
Video: VideoModel Video: VideoModel
static listForApi (start: number, count: number, sort: SortType, type?: VideoBlacklistType) { static listForApi (parameters: {
start: number
count: number
sort: SortType
search?: string
type?: VideoBlacklistType
}) {
const { start, count, sort, search, type } = parameters
function buildBaseQuery (): FindOptions { function buildBaseQuery (): FindOptions {
return { return {
offset: start, offset: start,
@ -70,6 +78,7 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> {
{ {
model: VideoModel, model: VideoModel,
required: true, required: true,
where: { ...searchAttribute(search, 'name') },
include: [ include: [
{ {
model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }), model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: true } as SummaryOptions ] }),