Add delete/manual approval instance followers in client
authorChocobozzz <me@florianbigard.com>
Mon, 8 Apr 2019 13:47:44 +0000 (15:47 +0200)
committerChocobozzz <me@florianbigard.com>
Mon, 8 Apr 2019 13:47:44 +0000 (15:47 +0200)
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
client/src/app/+admin/follows/followers-list/followers-list.component.html
client/src/app/+admin/follows/followers-list/followers-list.component.scss
client/src/app/+admin/follows/followers-list/followers-list.component.ts
client/src/app/+admin/follows/shared/follow.service.ts
client/src/app/+my-account/my-account-ownership/my-account-ownership.component.html

index 00a0d98f8e63d6c4582a1f502dfc7256ef05e7f1..637484622ca64dcf9bcd3f7a6199f57f23eb5cfa 100644 (file)
@@ -84,6 +84,7 @@
           </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">
index d8eb55da7f613d5f5b53046481460e7e6c48ce38..e64750713a26efe9fdc93503fc257a1b559da237 100644 (file)
@@ -5,7 +5,7 @@ import { CustomConfigValidatorsService, FormReactive, UserValidatorsService } fr
 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',
@@ -124,6 +124,12 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
             enabled: null
           }
         }
+      },
+      followers: {
+        instance: {
+          enabled: null,
+          manualApproval: null
+        }
       }
     }
 
index fc022bdb47227c995cb15cbfe5d841665ad3cc58..da0ba95e3f5a0f2d01e4a7f0a490349d4266b597 100644 (file)
   <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>
index a6f0656b8b79d2f15cb6fe47be74c352f8488238..964b3f99b2bb8505bedfb20998e602e3a667ecc0 100644 (file)
@@ -7,4 +7,10 @@
   input {
     @include peertube-input-text(250px);
   }
-}
\ No newline at end of file
+}
+
+.action-cell {
+  my-button:first-child {
+    margin-right: 10px;
+  }
+}
index 9a8848bfb2eb48aff92f445d5f6d34d84e6b61ca..b78cdf656edfd76b3f2c94d341dd87c72553ced0 100644 (file)
@@ -1,6 +1,5 @@
 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'
@@ -20,9 +19,10 @@ export class FollowersListComponent extends RestTable implements OnInit {
   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()
   }
@@ -31,6 +31,62 @@ export class FollowersListComponent extends RestTable implements OnInit {
     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(
index a2904179ead2ade1dac1818f976cbce914430b11..c2b8ef006de53ea33dfaeacf4b260bbf81b42cf7 100644 (file)
@@ -63,4 +63,34 @@ export class FollowService {
                  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))
+               )
+  }
 }
index 5709e9f543c44f219f5f28c26bfbd0b708940955..c5fd3ccb9e3818c46272bcc345315931ca65cf79 100644 (file)
@@ -30,8 +30,7 @@
         </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>