Add ability to unfollow a server
This commit is contained in:
parent
892211e849
commit
7e9334c34d
|
@ -7,9 +7,9 @@
|
|||
sortField="createdAt" (onLazyLoad)="loadLazy($event)"
|
||||
>
|
||||
<p-column field="id" header="ID"></p-column>
|
||||
<p-column field="host" header="Host"></p-column>
|
||||
<p-column field="follower.host" header="Host"></p-column>
|
||||
<p-column field="email" header="Email"></p-column>
|
||||
<p-column field="score" header="Score"></p-column>
|
||||
<p-column field="follower.score" header="Score"></p-column>
|
||||
<p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
|
||||
</p-dataTable>
|
||||
</div>
|
||||
|
|
|
@ -7,10 +7,15 @@
|
|||
sortField="createdAt" (onLazyLoad)="loadLazy($event)"
|
||||
>
|
||||
<p-column field="id" header="ID"></p-column>
|
||||
<p-column field="host" header="Host"></p-column>
|
||||
<p-column field="following.host" header="Host"></p-column>
|
||||
<p-column field="email" header="Email"></p-column>
|
||||
<p-column field="score" header="Score"></p-column>
|
||||
<p-column field="following.score" header="Score"></p-column>
|
||||
<p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
|
||||
<p-column header="Unfollow" styleClass="action-cell">
|
||||
<ng-template pTemplate="body" let-following="rowData">
|
||||
<span (click)="removeFollowing(following)" class="glyphicon glyphicon-remove glyphicon-black" title="Unfollow"></span>
|
||||
</ng-template>
|
||||
</p-column>
|
||||
</p-dataTable>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Component } from '@angular/core'
|
|||
import { NotificationsService } from 'angular2-notifications'
|
||||
import { SortMeta } from 'primeng/primeng'
|
||||
import { AccountFollow } from '../../../../../../shared/models/accounts/follow.model'
|
||||
import { ConfirmService } from '../../../core/confirm/confirm.service'
|
||||
import { RestPagination, RestTable } from '../../../shared'
|
||||
import { FollowService } from '../shared'
|
||||
|
||||
|
@ -18,11 +19,29 @@ export class FollowingListComponent extends RestTable {
|
|||
|
||||
constructor (
|
||||
private notificationsService: NotificationsService,
|
||||
private confirmService: ConfirmService,
|
||||
private followService: FollowService
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
removeFollowing (follow: AccountFollow) {
|
||||
this.confirmService.confirm(`Do you really want to unfollow ${follow.following.host}?`, 'Unfollow').subscribe(
|
||||
res => {
|
||||
if (res === false) return
|
||||
|
||||
this.followService.unfollow(follow).subscribe(
|
||||
() => {
|
||||
this.notificationsService.success('Success', `You are not following ${follow.following.host} anymore.`)
|
||||
this.loadData()
|
||||
},
|
||||
|
||||
err => this.notificationsService.error('Error', err.message)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
protected loadData () {
|
||||
this.followService.getFollowing(this.pagination, this.sort)
|
||||
.subscribe(
|
||||
|
|
|
@ -37,7 +37,7 @@ export class FollowService {
|
|||
.catch(res => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
follow (notEmptyHosts: String[]) {
|
||||
follow (notEmptyHosts: string[]) {
|
||||
const body = {
|
||||
hosts: notEmptyHosts
|
||||
}
|
||||
|
@ -46,4 +46,10 @@ export class FollowService {
|
|||
.map(this.restExtractor.extractDataBool)
|
||||
.catch(res => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
unfollow (follow: AccountFollow) {
|
||||
return this.authHttp.delete(FollowService.BASE_APPLICATION_URL + '/following/' + follow.following.id)
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch(res => this.restExtractor.handleError(res))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, OnInit } from '@angular/core'
|
||||
import { Component } from '@angular/core'
|
||||
import { SortMeta } from 'primeng/components/common/sortmeta'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
@ -12,7 +12,7 @@ import { UserService } from '../shared'
|
|||
templateUrl: './user-list.component.html',
|
||||
styleUrls: [ './user-list.component.scss' ]
|
||||
})
|
||||
export class UserListComponent extends RestTable implements OnInit {
|
||||
export class UserListComponent extends RestTable {
|
||||
users: User[] = []
|
||||
totalRecords = 0
|
||||
rowsPerPage = 10
|
||||
|
@ -27,10 +27,6 @@ export class UserListComponent extends RestTable implements OnInit {
|
|||
super()
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
this.loadData()
|
||||
}
|
||||
|
||||
removeUser (user: User) {
|
||||
if (user.username === 'root') {
|
||||
this.notificationsService.error('Error', 'You cannot delete root.')
|
||||
|
|
|
@ -134,7 +134,7 @@ const CONSTRAINTS_FIELDS = {
|
|||
VIEWS: { min: 0 },
|
||||
LIKES: { min: 0 },
|
||||
DISLIKES: { min: 0 },
|
||||
FILE_SIZE: { min: 10, max: 1024 * 1024 * 1024 * 3 /* 3Go */ },
|
||||
FILE_SIZE: { min: 10, max: 1024 * 1024 * 1024 * 10 /* 10Go */ },
|
||||
URL: { min: 3, max: 2000 } // Length
|
||||
},
|
||||
ACCOUNTS: {
|
||||
|
|
|
@ -10,7 +10,7 @@ async function processUndoActivity (activity: ActivityUndo) {
|
|||
const following = await db.Account.loadByUrl(activityToUndo.object)
|
||||
const accountFollow = await db.AccountFollow.loadByAccountAndTarget(follower.id, following.id)
|
||||
|
||||
if (!accountFollow) throw new Error(`'Unknown account follow (${follower.id} -> ${following.id}.`)
|
||||
if (!accountFollow) throw new Error(`'Unknown account follow ${follower.id} -> ${following.id}.`)
|
||||
|
||||
await accountFollow.destroy()
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import * as express from 'express'
|
||||
import { body } from 'express-validator/check'
|
||||
import { body, param } from 'express-validator/check'
|
||||
import { isTestInstance } from '../../helpers/core-utils'
|
||||
import { isAccountIdValid } from '../../helpers/custom-validators/activitypub/account'
|
||||
import { isEachUniqueHostValid } from '../../helpers/custom-validators/servers'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { CONFIG, database as db } from '../../initializers'
|
||||
import { checkErrors } from './utils'
|
||||
import { getServerAccount } from '../../helpers/utils'
|
||||
import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
|
||||
|
||||
const followValidator = [
|
||||
body('hosts').custom(isEachUniqueHostValid).withMessage('Should have an array of unique hosts'),
|
||||
|
@ -28,7 +28,7 @@ const followValidator = [
|
|||
]
|
||||
|
||||
const removeFollowingValidator = [
|
||||
body('accountId').custom(isAccountIdValid).withMessage('Should have a valid account id'),
|
||||
param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'),
|
||||
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.debug('Checking follow parameters', { parameters: req.body })
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
import * as Bluebird from 'bluebird'
|
||||
import { FollowState } from '../../../shared/models/accounts/follow.model'
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { AccountFollow, FollowState } from '../../../shared/models/accounts/follow.model'
|
||||
import { ResultList } from '../../../shared/models/result-list.model'
|
||||
import { AccountInstance } from './account-interface'
|
||||
|
||||
export namespace AccountFollowMethods {
|
||||
export type LoadByAccountAndTarget = (accountId: number, targetAccountId: number) => Bluebird<AccountFollowInstance>
|
||||
|
||||
export type ListFollowingForApi = (id: number, start: number, count: number, sort: string) => Bluebird< ResultList<AccountInstance> >
|
||||
export type ListFollowersForApi = (id: number, start: number, count: number, sort: string) => Bluebird< ResultList<AccountInstance> >
|
||||
export type ListFollowingForApi = (id: number, start: number, count: number, sort: string) => Bluebird< ResultList<AccountFollowInstance>>
|
||||
export type ListFollowersForApi = (id: number, start: number, count: number, sort: string) => Bluebird< ResultList<AccountFollowInstance>>
|
||||
|
||||
export type ListAcceptedFollowerUrlsForApi = (accountId: number[], start?: number, count?: number) => Promise< ResultList<string> >
|
||||
export type ListAcceptedFollowingUrlsForApi = (accountId: number[], start?: number, count?: number) => Promise< ResultList<string> >
|
||||
export type ListAcceptedFollowerSharedInboxUrls = (accountId: number[]) => Promise< ResultList<string> >
|
||||
export type ToFormattedJSON = (this: AccountFollowInstance) => AccountFollow
|
||||
}
|
||||
|
||||
export interface AccountFollowClass {
|
||||
|
@ -38,6 +39,8 @@ export interface AccountFollowInstance extends AccountFollowClass, AccountFollow
|
|||
|
||||
AccountFollower?: AccountInstance
|
||||
AccountFollowing?: AccountInstance
|
||||
|
||||
toFormattedJSON: AccountFollowMethods.ToFormattedJSON
|
||||
}
|
||||
|
||||
export interface AccountFollowModel extends AccountFollowClass, Sequelize.Model<AccountFollowInstance, AccountFollowAttributes> {}
|
||||
|
|
|
@ -12,6 +12,7 @@ let listFollowersForApi: AccountFollowMethods.ListFollowersForApi
|
|||
let listAcceptedFollowerUrlsForApi: AccountFollowMethods.ListAcceptedFollowerUrlsForApi
|
||||
let listAcceptedFollowingUrlsForApi: AccountFollowMethods.ListAcceptedFollowingUrlsForApi
|
||||
let listAcceptedFollowerSharedInboxUrls: AccountFollowMethods.ListAcceptedFollowerSharedInboxUrls
|
||||
let toFormattedJSON: AccountFollowMethods.ToFormattedJSON
|
||||
|
||||
export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
|
||||
AccountFollow = sequelize.define<AccountFollowInstance, AccountFollowAttributes>('AccountFollow',
|
||||
|
@ -46,7 +47,10 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
listAcceptedFollowingUrlsForApi,
|
||||
listAcceptedFollowerSharedInboxUrls
|
||||
]
|
||||
addMethodsToModel(AccountFollow, classMethods)
|
||||
const instanceMethods = [
|
||||
toFormattedJSON
|
||||
]
|
||||
addMethodsToModel(AccountFollow, classMethods, instanceMethods)
|
||||
|
||||
return AccountFollow
|
||||
}
|
||||
|
@ -73,6 +77,22 @@ function associate (models) {
|
|||
})
|
||||
}
|
||||
|
||||
toFormattedJSON = function (this: AccountFollowInstance) {
|
||||
const follower = this.AccountFollower.toFormattedJSON()
|
||||
const following = this.AccountFollowing.toFormattedJSON()
|
||||
|
||||
const json = {
|
||||
id: this.id,
|
||||
follower,
|
||||
following,
|
||||
state: this.state,
|
||||
createdAt: this.createdAt,
|
||||
updatedAt: this.updatedAt
|
||||
}
|
||||
|
||||
return json
|
||||
}
|
||||
|
||||
loadByAccountAndTarget = function (accountId: number, targetAccountId: number) {
|
||||
const query = {
|
||||
where: {
|
||||
|
@ -122,7 +142,7 @@ listFollowingForApi = function (id: number, start: number, count: number, sort:
|
|||
|
||||
return AccountFollow.findAndCountAll(query).then(({ rows, count }) => {
|
||||
return {
|
||||
data: rows.map(r => r.AccountFollowing),
|
||||
data: rows,
|
||||
total: count
|
||||
}
|
||||
})
|
||||
|
@ -154,7 +174,7 @@ listFollowersForApi = function (id: number, start: number, count: number, sort:
|
|||
|
||||
return AccountFollow.findAndCountAll(query).then(({ rows, count }) => {
|
||||
return {
|
||||
data: rows.map(r => r.AccountFollower),
|
||||
data: rows,
|
||||
total: count
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import { Account } from './account.model'
|
||||
|
||||
export type FollowState = 'pending' | 'accepted'
|
||||
|
||||
export interface AccountFollow {
|
||||
id: number
|
||||
name: string
|
||||
score?: number // Used for followers
|
||||
host: string
|
||||
follower: Account
|
||||
following: Account
|
||||
state: FollowState
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ server {
|
|||
|
||||
# For the video upload
|
||||
client_max_body_size 2G;
|
||||
proxy_connect_timeout 600;
|
||||
proxy_send_timeout 600;
|
||||
proxy_read_timeout 600;
|
||||
}
|
||||
|
||||
# Bypass PeerTube webseed route for better performances
|
||||
|
|
|
@ -23,6 +23,9 @@ server {
|
|||
|
||||
# For the video upload
|
||||
client_max_body_size 2G;
|
||||
proxy_connect_timeout 600;
|
||||
proxy_send_timeout 600;
|
||||
proxy_read_timeout 600;
|
||||
}
|
||||
|
||||
# Bypass PeerTube webseed route for better performances
|
||||
|
|
Loading…
Reference in New Issue