</div>
</ng-container>
+
<div i18n class="inner-form-title">Signup</div>
<ng-container formGroupName="signup">
</div>
</ng-container>
+
<div i18n class="inner-form-title">Users</div>
<ng-container formGroupName="user">
</div>
</ng-container>
+
<div i18n class="inner-form-title">Import</div>
<ng-container formGroupName="import">
</ng-container>
</ng-container>
+
<div i18n class="inner-form-title">Auto-blacklist</div>
<ng-container formGroupName="autoBlacklist">
</ng-container>
</ng-container>
+
+ <div i18n class="inner-form-title">Instance followers</div>
+
+ <ng-container formGroupName="followers">
+ <ng-container formGroupName="instance">
+
+ <div class="form-group">
+ <my-peertube-checkbox
+ inputName="followersInstanceEnabled" formControlName="enabled"
+ i18n-labelText labelText="Other instances can follow your instance"
+ ></my-peertube-checkbox>
+ </div>
+
+ <div class="form-group">
+ <my-peertube-checkbox
+ inputName="followersInstanceManualApproval" formControlName="manualApproval"
+ i18n-labelText labelText="Manually approve new instance follower"
+ ></my-peertube-checkbox>
+ </div>
+ </ng-container>
+ </ng-container>
+
+
<div i18n class="inner-form-title">Administrator</div>
<div class="form-group" formGroupName="admin">
import { Notifier } from '@app/core'
import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model'
import { I18n } from '@ngx-translate/i18n-polyfill'
-import { BuildFormDefaultValues, FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
@Component({
selector: 'my-edit-custom-config',
enabled: null
}
}
+ },
+ followers: {
+ instance: {
+ enabled: null,
+ manualApproval: null
+ }
}
}
<ng-template pTemplate="header">
<tr>
<th i18n style="width: 60px">ID</th>
- <th i18n>Score</th>
- <th i18n>Name</th>
- <th i18n>Host</th>
+ <th i18n>Follower handle</th>
<th i18n>State</th>
+ <th i18n>Score</th>
<th i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
+ <th></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-follow>
<tr>
<td>{{ follow.id }}</td>
- <td>{{ follow.score }}</td>
- <td>{{ follow.follower.name }}</td>
- <td>{{ follow.follower.host }}</td>
+ <td>{{ follow.follower.name + '@' + follow.follower.host }}</td>
<td *ngIf="follow.state === 'accepted'" i18n>Accepted</td>
<td *ngIf="follow.state === 'pending'" i18n>Pending</td>
+ <td>{{ follow.score }}</td>
<td>{{ follow.createdAt }}</td>
+
+ <td class="action-cell">
+ <ng-container *ngIf="follow.state === 'pending'">
+ <my-button i18n-label label="Accept" icon="tick" (click)="acceptFollower(follow)"></my-button>
+ <my-button i18n-label label="Refuse" icon="cross" (click)="rejectFollower(follow)"></my-button>
+ </ng-container>
+
+ <my-delete-button *ngIf="follow.state === 'accepted'" (click)="deleteFollower(follow)"></my-delete-button>
+ </td>
</tr>
</ng-template>
</p-table>
input {
@include peertube-input-text(250px);
}
-}
\ No newline at end of file
+}
+
+.action-cell {
+ my-button:first-child {
+ margin-right: 10px;
+ }
+}
import { Component, OnInit } from '@angular/core'
-
-import { Notifier } from '@app/core'
+import { ConfirmService, Notifier } from '@app/core'
import { SortMeta } from 'primeng/primeng'
import { ActorFollow } from '../../../../../../shared/models/actors/follow.model'
import { RestPagination, RestTable } from '../../../shared'
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
constructor (
+ private confirmService: ConfirmService,
private notifier: Notifier,
- private followService: FollowService,
- private i18n: I18n
+ private i18n: I18n,
+ private followService: FollowService
) {
super()
}
this.initialize()
}
+ acceptFollower (follow: ActorFollow) {
+ follow.state = 'accepted'
+
+ this.followService.acceptFollower(follow)
+ .subscribe(
+ () => {
+ const handle = follow.follower.name + '@' + follow.follower.host
+ this.notifier.success(this.i18n('{{handle}} accepted in instance followers', { handle }))
+ },
+
+ err => {
+ follow.state = 'pending'
+ this.notifier.error(err.message)
+ }
+ )
+ }
+
+ async rejectFollower (follow: ActorFollow) {
+ const message = this.i18n('Do you really want to reject this follower?')
+ const res = await this.confirmService.confirm(message, this.i18n('Reject'))
+ if (res === false) return
+
+ this.followService.rejectFollower(follow)
+ .subscribe(
+ () => {
+ const handle = follow.follower.name + '@' + follow.follower.host
+ this.notifier.success(this.i18n('{{handle}} rejected from instance followers', { handle }))
+
+ this.loadData()
+ },
+
+ err => {
+ follow.state = 'pending'
+ this.notifier.error(err.message)
+ }
+ )
+ }
+
+ async deleteFollower (follow: ActorFollow) {
+ const message = this.i18n('Do you really want to delete this follower?')
+ const res = await this.confirmService.confirm(message, this.i18n('Delete'))
+ if (res === false) return
+
+ this.followService.removeFollower(follow)
+ .subscribe(
+ () => {
+ const handle = follow.follower.name + '@' + follow.follower.host
+ this.notifier.success(this.i18n('{{handle}} removed from instance followers', { handle }))
+
+ this.loadData()
+ },
+
+ err => this.notifier.error(err.message)
+ )
+ }
+
protected loadData () {
this.followService.getFollowers(this.pagination, this.sort, this.search)
.subscribe(
catchError(res => this.restExtractor.handleError(res))
)
}
+
+ acceptFollower (follow: ActorFollow) {
+ const handle = follow.follower.name + '@' + follow.follower.host
+
+ return this.authHttp.post(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}/accept`, {})
+ .pipe(
+ map(this.restExtractor.extractDataBool),
+ catchError(res => this.restExtractor.handleError(res))
+ )
+ }
+
+ rejectFollower (follow: ActorFollow) {
+ const handle = follow.follower.name + '@' + follow.follower.host
+
+ return this.authHttp.post(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}/reject`, {})
+ .pipe(
+ map(this.restExtractor.extractDataBool),
+ catchError(res => this.restExtractor.handleError(res))
+ )
+ }
+
+ removeFollower (follow: ActorFollow) {
+ const handle = follow.follower.name + '@' + follow.follower.host
+
+ return this.authHttp.delete(`${FollowService.BASE_APPLICATION_URL}/followers/${handle}`)
+ .pipe(
+ map(this.restExtractor.extractDataBool),
+ catchError(res => this.restExtractor.handleError(res))
+ )
+ }
}
</a>
</td>
<td>
- <a [href]="videoChangeOwnership.video.url" i18n-title title="Go to the video" target="_blank"
- rel="noopener noreferrer">
+ <a [href]="videoChangeOwnership.video.url" i18n-title title="Go to the video" target="_blank" rel="noopener noreferrer">
{{ videoChangeOwnership.video.name }}
</a>
</td>
<td i18n>{{ videoChangeOwnership.status }}</td>
<td class="action-cell">
<ng-container *ngIf="videoChangeOwnership.status === 'WAITING'">
- <my-button i18n label="Accept"
- icon="tick"
- (click)="openAcceptModal(videoChangeOwnership)"></my-button>
- <my-button i18n label="Refuse"
- icon="cross"
- (click)="refuse(videoChangeOwnership)">Refuse</my-button>
+ <my-button i18n-label label="Accept" icon="tick" (click)="openAcceptModal(videoChangeOwnership)"></my-button>
+ <my-button i18n-label label="Refuse" icon="cross" (click)="refuse(videoChangeOwnership)"></my-button>
</ng-container>
</td>
</tr>
</ng-template>
</p-table>
-<my-account-accept-ownership #myAccountAcceptOwnershipComponent (accepted)="accepted()"></my-account-accept-ownership>
\ No newline at end of file
+<my-account-accept-ownership #myAccountAcceptOwnershipComponent (accepted)="accepted()"></my-account-accept-ownership>