]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Refactor search filters
authorChocobozzz <me@florianbigard.com>
Mon, 3 May 2021 12:33:34 +0000 (14:33 +0200)
committerChocobozzz <me@florianbigard.com>
Mon, 3 May 2021 14:42:15 +0000 (16:42 +0200)
47 files changed:
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/following-list/following-list.component.html
client/src/app/+admin/follows/following-list/following-list.component.scss
client/src/app/+admin/follows/following-list/following-list.component.ts
client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.ts
client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
client/src/app/+admin/moderation/video-block-list/video-block-list.component.scss
client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss
client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts
client/src/app/+admin/system/jobs/jobs.component.ts
client/src/app/+admin/users/user-list/user-list.component.html
client/src/app/+admin/users/user-list/user-list.component.ts
client/src/app/+my-library/+my-video-channels/my-video-channels.component.html
client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts
client/src/app/+my-library/my-history/my-history.component.html
client/src/app/+my-library/my-history/my-history.component.ts
client/src/app/+my-library/my-ownership/my-ownership.component.ts
client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html
client/src/app/+my-library/my-subscriptions/my-subscriptions.component.scss
client/src/app/+my-library/my-subscriptions/my-subscriptions.component.ts
client/src/app/+my-library/my-video-imports/my-video-imports.component.ts
client/src/app/+my-library/my-video-playlists/my-video-playlists.component.html
client/src/app/+my-library/my-video-playlists/my-video-playlists.component.ts
client/src/app/+my-library/my-videos/my-videos.component.html
client/src/app/+my-library/my-videos/my-videos.component.ts
client/src/app/core/rest/rest-table.ts
client/src/app/core/routing/index.ts
client/src/app/core/routing/route-filter.ts [deleted file]
client/src/app/shared/shared-abuse-list/abuse-list-table.component.html
client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
client/src/app/shared/shared-forms/advanced-input-filter.component.html
client/src/app/shared/shared-forms/advanced-input-filter.component.ts
client/src/app/shared/shared-main/misc/top-menu-dropdown.component.scss
client/src/app/shared/shared-moderation/account-blocklist.component.html
client/src/app/shared/shared-moderation/account-blocklist.component.scss
client/src/app/shared/shared-moderation/account-blocklist.component.ts
client/src/app/shared/shared-moderation/moderation.scss
client/src/app/shared/shared-moderation/server-blocklist.component.html
client/src/app/shared/shared-moderation/server-blocklist.component.scss
client/src/app/shared/shared-moderation/server-blocklist.component.ts
client/src/app/shared/shared-video-miniature/videos-selection.component.html
client/src/app/shared/shared-video-miniature/videos-selection.component.ts

index 633de96775bb38815dbcca28c0df8497b6c8e0bc..c2e9a4df69fa61d6537697a2ccc17a8def72fd09 100644 (file)
@@ -4,20 +4,16 @@
 </h1>
 
 <p-table
-  [value]="followers" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
-  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
+  [value]="followers" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [sortField]="sort.field" [sortOrder]="sort.order" (onPage)="onPage($event)"
+  [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} followers"
 >
   <ng-template pTemplate="caption">
     <div class="caption">
-      <div class="ml-auto has-feedback has-clear">
-        <input
-          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
-          (keyup)="onSearch($event)"
-        >
-        <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-        <span class="sr-only" i18n>Clear filters</span>
+      <div class="ml-auto">
+        <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
     </div>
   </ng-template>
index 12c0cd03317bf68abc51f678041e409c975bcb77..35f38aae0664aa2f72c3a8da8568991cb2526d43 100644 (file)
@@ -1,14 +1,6 @@
 @import '_variables';
 @import '_mixins';
 
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-  }
-}
-
 a {
   @include disable-default-a-behaviour;
   display: inline-block;
index 904e3c338a90d06aab05a810c851daf8b0e525fd..4a312f6aa891bbdec94ed53bebc6236bf7871198 100644 (file)
@@ -59,7 +59,7 @@ export class FollowersListComponent extends RestTable implements OnInit {
             const handle = follow.follower.name + '@' + follow.follower.host
             this.notifier.success($localize`${handle} rejected from instance followers`)
 
-            this.loadData()
+            this.reloadData()
           },
 
           err => {
@@ -80,14 +80,14 @@ export class FollowersListComponent extends RestTable implements OnInit {
             const handle = follow.follower.name + '@' + follow.follower.host
             this.notifier.success($localize`${handle} removed from instance followers`)
 
-            this.loadData()
+            this.reloadData()
           },
 
           err => this.notifier.error(err.message)
         )
   }
 
-  protected loadData () {
+  protected reloadData () {
     this.followService.getFollowers({ pagination: this.pagination, sort: this.sort, search: this.search })
                       .subscribe(
                         resultList => {
index f4e6a60fe134044d99778a63eedb95f3b0248569..e7c0c908823bc1ec4d6f9531a31ae7bf2e36d358 100644 (file)
@@ -4,8 +4,9 @@
 </h1>
 
 <p-table
-  [value]="following" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [value]="following" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
   [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
+  [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} hosts"
 >
         </a>
       </div>
 
-      <div class="ml-auto has-feedback has-clear">
-        <input
-          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
-          (keyup)="onSearch($event)"
-        >
-        <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-        <span class="sr-only" i18n>Clear filters</span>
+      <div class="ml-auto">
+        <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
     </div>
   </ng-template>
index 797882d9a497b16bcbf6d4b2af5623099c4dc569..9474b0a234f9b26c7bce2e31739c40be57b0222e 100644 (file)
@@ -16,14 +16,6 @@ a {
   }
 }
 
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-  }
-}
-
 .follow-button {
   @include create-button;
 }
index f34490cc87c9888e7afc326e1f6b43ddea310729..b63fe08c0b4b36f0854f9da306836f02338f8492 100644 (file)
@@ -45,7 +45,7 @@ export class FollowingListComponent extends RestTable implements OnInit {
     this.followService.follow(hosts).subscribe(
       () => {
         this.notifier.success($localize`Follow request(s) sent!`)
-        this.loadData()
+        this.reloadData()
       },
 
       err => this.notifier.error(err.message)
@@ -62,14 +62,14 @@ export class FollowingListComponent extends RestTable implements OnInit {
     this.followService.unfollow(follow).subscribe(
       () => {
         this.notifier.success($localize`You are not following ${follow.following.host} anymore.`)
-        this.loadData()
+        this.reloadData()
       },
 
       err => this.notifier.error(err.message)
     )
   }
 
-  protected loadData () {
+  protected reloadData () {
     this.followService.getFollowing({ pagination: this.pagination, sort: this.sort, search: this.search })
                       .subscribe(
                         resultList => {
index d6fd1a1ab62e020237832ccc18848e6a5a65a67f..3cd65dd6e3ed144798dd4c751ec5bc7f2d626d82 100644 (file)
@@ -78,7 +78,7 @@ export class VideoRedundanciesListComponent extends RestTable implements OnInit
     this.pagination.start = 0
     this.saveSelectLocalStorage()
 
-    this.loadData()
+    this.reloadData()
   }
 
   getRedundancyStrategy (redundancy: VideoRedundancy) {
@@ -145,7 +145,7 @@ export class VideoRedundanciesListComponent extends RestTable implements OnInit
       .subscribe(
         () => {
           this.notifier.success($localize`Video redundancies removed!`)
-          this.loadData()
+          this.reloadData()
         },
 
         err => this.notifier.error(err.message)
@@ -153,7 +153,7 @@ export class VideoRedundanciesListComponent extends RestTable implements OnInit
 
   }
 
-  protected loadData () {
+  protected reloadData () {
     const options = {
       pagination: this.pagination,
       sort: this.sort,
index 84ce381cc17e7a95ad00d3d71a36669f6da0e8f4..e3a3a83207b49744cb10860630794f8de2278e79 100644 (file)
@@ -1,18 +1,14 @@
 <p-table
-  [value]="blockedAccounts" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
-  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
+  [value]="blockedAccounts" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [sortField]="sort.field" [sortOrder]="sort.order" (onPage)="onPage($event)"
+  [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted accounts"
 >
   <ng-template pTemplate="caption">
     <div class="caption">
-      <div class="ml-auto has-feedback has-clear">
-        <input
-          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
-          (keyup)="onSearch($event)"
-        >
-        <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-        <span class="sr-only" i18n>Clear filters</span>
+      <div class="ml-auto">
+        <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
     </div>
   </ng-template>
index cf2466bdbe33bae10d5ee7118b25ab7a72429def..d89c8f24445c2754eb36617e90584b57c16bc715 100644 (file)
@@ -4,8 +4,9 @@
 </h1>
 
 <p-table
-  [value]="blocklist" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
-  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
+  [value]="blocklist" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [sortField]="sort.field" [sortOrder]="sort.order" dataKey="id"
+  [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} blocked videos"
   (onPage)="onPage($event)" [expandedRowKeys]="expandedRows"
@@ -13,7 +14,7 @@
   <ng-template pTemplate="caption">
     <div class="caption">
       <div class="ml-auto">
-        <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)" (resetTableFilter)="resetTableFilter()"></my-advanced-input-filter>
+        <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
     </div>
   </ng-template>
index b67e33cc1a0ec68b863390d15796f09594f3cb4d..068aa2aee76bd8df041c572b1f2066440d773a1d 100644 (file)
@@ -5,23 +5,6 @@ my-global-icon {
   height: 24px;
 }
 
-.input-group {
-  @include peertube-input-group(300px);
-
-  .dropdown-toggle::after {
-    margin-left: 0;
-  }
-}
-
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-    flex-grow: 1;
-  }
-}
-
 .badge {
   @include table-badge;
 }
index dfd8dc745e3a76351d975fce90748cc1bde518ec..498d8321aff7b1f538584117df97d152b8ce3741 100644 (file)
@@ -2,9 +2,9 @@ import { SortMeta } from 'primeng/api'
 import { switchMap } from 'rxjs/operators'
 import { buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
 import { environment } from 'src/environments/environment'
-import { AfterViewInit, Component, OnInit } from '@angular/core'
+import { Component, OnInit } from '@angular/core'
 import { DomSanitizer } from '@angular/platform-browser'
-import { ActivatedRoute, Params, Router } from '@angular/router'
+import { ActivatedRoute, Router } from '@angular/router'
 import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
 import { AdvancedInputFilter } from '@app/shared/shared-forms'
 import { DropdownAction, Video, VideoService } from '@app/shared/shared-main'
@@ -16,7 +16,7 @@ import { VideoBlacklist, VideoBlacklistType } from '@shared/models'
   templateUrl: './video-block-list.component.html',
   styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-block-list.component.scss' ]
 })
-export class VideoBlockListComponent extends RestTable implements OnInit, AfterViewInit {
+export class VideoBlockListComponent extends RestTable implements OnInit {
   blocklist: (VideoBlacklist & { reasonHtml?: string, embedHtml?: string })[] = []
   totalRecords = 0
   sort: SortMeta = { field: 'createdAt', order: -1 }
@@ -64,7 +64,7 @@ export class VideoBlockListComponent extends RestTable implements OnInit, AfterV
             ).subscribe(
               () => {
                 this.notifier.success($localize`Video ${videoBlock.video.name} switched to manual block.`)
-                this.loadData()
+                this.reloadData()
               },
 
               err => this.notifier.error(err.message)
@@ -116,11 +116,6 @@ export class VideoBlockListComponent extends RestTable implements OnInit, AfterV
         })
 
     this.initialize()
-    this.listenToSearchChange()
-  }
-
-  ngAfterViewInit () {
-    if (this.search) this.setTableFilter(this.search, false)
   }
 
   getIdentifier () {
@@ -144,7 +139,7 @@ export class VideoBlockListComponent extends RestTable implements OnInit, AfterV
     this.videoBlocklistService.unblockVideo(entry.video.id).subscribe(
       () => {
         this.notifier.success($localize`Video ${entry.video.name} unblocked.`)
-        this.loadData()
+        this.reloadData()
       },
 
       err => this.notifier.error(err.message)
@@ -162,7 +157,7 @@ export class VideoBlockListComponent extends RestTable implements OnInit, AfterV
     )
   }
 
-  protected loadData () {
+  protected reloadData () {
     this.videoBlocklistService.listBlocks({
       pagination: this.pagination,
       sort: this.sort,
index 5cc0ff1379c9c49d7ffadf73472da37a48eb1a53..9d9283536dccdfdc5c94191c674dd0abca8371d9 100644 (file)
@@ -8,8 +8,9 @@
 <em i18n>This view also shows comments from muted accounts.</em>
 
 <p-table
-  [value]="comments" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
-  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id"
+  [value]="comments" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [sortField]="sort.field" [sortOrder]="sort.order" dataKey="id"
+  [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} comments"
   (onPage)="onPage($event)" [expandedRowKeys]="expandedRows"
@@ -26,7 +27,7 @@
       </div>
 
       <div class="ml-auto">
-        <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)" (resetTableFilter)="resetTableFilter()"></my-advanced-input-filter>
+        <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
     </div>
   </ng-template>
index 5d97d9bdb513e9fabb335b76e510aa9702f1bd78..a6f931e3b5bce9dd0c151e506fd94812d16b529f 100644 (file)
@@ -11,23 +11,6 @@ my-global-icon {
   height: 24px;
 }
 
-.input-group {
-  @include peertube-input-group(300px);
-
-  .dropdown-toggle::after {
-    margin-left: 0;
-  }
-}
-
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-    flex-grow: 1;
-  }
-}
-
 .video {
   display: flex;
   flex-direction: column;
index ebbbddb43652d0219c4b12ec1f9f728b12e989b9..e2ae993b0598fa02e8c7a804acf811b5a9d8a0d4 100644 (file)
@@ -13,9 +13,7 @@ import { FeedFormat, UserRight } from '@shared/models'
   templateUrl: './video-comment-list.component.html',
   styleUrls: [ '../../../shared/shared-moderation/moderation.scss', './video-comment-list.component.scss' ]
 })
-export class VideoCommentListComponent extends RestTable implements OnInit, AfterViewInit {
-  baseRoute = '/admin/moderation/video-comments/list'
-
+export class VideoCommentListComponent extends RestTable implements OnInit {
   comments: VideoCommentAdmin[]
   totalRecords = 0
   sort: SortMeta = { field: 'createdAt', order: -1 }
@@ -91,7 +89,6 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
 
   ngOnInit () {
     this.initialize()
-    this.listenToSearchChange()
 
     this.bulkCommentActions = [
       {
@@ -103,10 +100,6 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
     ]
   }
 
-  ngAfterViewInit () {
-    if (this.search) this.setTableFilter(this.search, false)
-  }
-
   getIdentifier () {
     return 'VideoCommentListComponent'
   }
@@ -119,7 +112,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
     return this.selectedComments.length !== 0
   }
 
-  protected loadData () {
+  protected reloadData () {
     this.videoCommentService.getAdminVideoComments({
       pagination: this.pagination,
       sort: this.sort,
@@ -147,7 +140,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
     this.videoCommentService.deleteVideoComments(commentArgs).subscribe(
       () => {
         this.notifier.success($localize`${commentArgs.length} comments deleted.`)
-        this.loadData()
+        this.reloadData()
       },
 
       err => this.notifier.error(err.message),
@@ -159,7 +152,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit, Afte
   private deleteComment (comment: VideoCommentAdmin) {
     this.videoCommentService.deleteVideoComment(comment.video.id, comment.id)
       .subscribe(
-        () => this.loadData(),
+        () => this.reloadData(),
 
         err => this.notifier.error(err.message)
       )
index 43578eedd434a4f9c92cd50754b7c21ec73e5a27..29ba95c5c2ad9c4f428294194e6ff86b725f5f66 100644 (file)
@@ -86,7 +86,7 @@ export class JobsComponent extends RestTable implements OnInit {
   onJobStateOrTypeChanged () {
     this.pagination.start = 0
 
-    this.loadData()
+    this.reloadData()
     this.saveJobStateAndType()
   }
 
@@ -104,10 +104,10 @@ export class JobsComponent extends RestTable implements OnInit {
     this.jobs = []
     this.totalRecords = 0
 
-    this.loadData()
+    this.reloadData()
   }
 
-  protected loadData () {
+  protected reloadData () {
     let jobState = this.jobState as JobState
     if (this.jobState === 'all') jobState = null
 
index 7170d70198fca51fc5ed051bbb01d66459d55896..44d8a7e87c7f16f618967578d543c512da9a819a 100644 (file)
@@ -1,7 +1,7 @@
 <p-table
-  [value]="users" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
-  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" [resizableColumns]="true"
-  [(selection)]="selectedUsers"
+  [value]="users" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [sortField]="sort.field" [sortOrder]="sort.order"  dataKey="id" [resizableColumns]="true" [(selection)]="selectedUsers"
+  [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} users"
   (onPage)="onPage($event)" [expandedRowKeys]="expandedRows"
@@ -22,7 +22,7 @@
       </div>
 
       <div class="ml-auto">
-        <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)" (resetTableFilter)="resetTableFilter()"></my-advanced-input-filter>
+        <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
 
     </div>
index 435bc17d7336c23a9a09991803b0bf6ca8f6c0d4..1c60adf89dc26ec3e4fe3cdf1c002b12aa951243 100644 (file)
@@ -1,5 +1,5 @@
 import { SortMeta } from 'primeng/api'
-import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'
+import { Component, OnInit, ViewChild } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
 import { AuthService, ConfirmService, Notifier, RestPagination, RestTable, ServerService, UserService } from '@app/core'
 import { AdvancedInputFilter } from '@app/shared/shared-forms'
@@ -19,7 +19,7 @@ type UserForList = User & {
   templateUrl: './user-list.component.html',
   styleUrls: [ './user-list.component.scss' ]
 })
-export class UserListComponent extends RestTable implements OnInit, AfterViewInit {
+export class UserListComponent extends RestTable implements OnInit {
   @ViewChild('userBanModal', { static: true }) userBanModal: UserBanModalComponent
 
   users: User[] = []
@@ -78,7 +78,6 @@ export class UserListComponent extends RestTable implements OnInit, AfterViewIni
         .subscribe(config => this.serverConfig = config)
 
     this.initialize()
-    this.listenToSearchChange()
 
     this.bulkUserActions = [
       [
@@ -127,10 +126,6 @@ export class UserListComponent extends RestTable implements OnInit, AfterViewIni
     this.columns.push({ id: 'lastLoginDate', label: 'Last login' })
   }
 
-  ngAfterViewInit () {
-    if (this.search) this.setTableFilter(this.search, false)
-  }
-
   getIdentifier () {
     return 'UserListComponent'
   }
@@ -174,7 +169,7 @@ export class UserListComponent extends RestTable implements OnInit, AfterViewIni
   }
 
   onUserChanged () {
-    this.loadData()
+    this.reloadData()
   }
 
   async unbanUsers (users: User[]) {
@@ -185,7 +180,7 @@ export class UserListComponent extends RestTable implements OnInit, AfterViewIni
         .subscribe(
           () => {
             this.notifier.success($localize`${users.length} users unbanned.`)
-            this.loadData()
+            this.reloadData()
           },
 
           err => this.notifier.error(err.message)
@@ -207,7 +202,7 @@ export class UserListComponent extends RestTable implements OnInit, AfterViewIni
     this.userService.removeUser(users).subscribe(
       () => {
         this.notifier.success($localize`${users.length} users deleted.`)
-        this.loadData()
+        this.reloadData()
       },
 
       err => this.notifier.error(err.message)
@@ -218,7 +213,7 @@ export class UserListComponent extends RestTable implements OnInit, AfterViewIni
     this.userService.updateUsers(users, { emailVerified: true }).subscribe(
       () => {
         this.notifier.success($localize`${users.length} users email set as verified.`)
-        this.loadData()
+        this.reloadData()
       },
 
       err => this.notifier.error(err.message)
@@ -229,7 +224,7 @@ export class UserListComponent extends RestTable implements OnInit, AfterViewIni
     return this.selectedUsers.length !== 0
   }
 
-  protected loadData () {
+  protected reloadData () {
     this.selectedUsers = []
 
     this.userService.getUsers({
index 2ed0c93d68ae5a50fe8d58548af0fc0f9139457d..8d5eb04e271f8cdd8587a193aa24b24326ec0489 100644 (file)
@@ -5,12 +5,7 @@
 </h1>
 
 <div class="video-channels-header d-flex justify-content-between">
-  <div class="has-feedback has-clear">
-    <input type="text" placeholder="Search your channels" i18n-placeholder [(ngModel)]="channelsSearch"
-      (ngModelChange)="onChannelsSearchChanged()" />
-    <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-    <span class="sr-only" i18n>Clear filters</span>
-  </div>
+  <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
 
   <a class="create-button" routerLink="create">
     <my-global-icon iconName="add" aria-hidden="true"></my-global-icon>
index f6ba50a4883f546f5348096c725ed700d255f863..9e3bf35b4e3ba611e12464af3eebf06c83006006 100644 (file)
@@ -1,29 +1,26 @@
 import { ChartData } from 'chart.js'
 import { max, maxBy, min, minBy } from 'lodash-es'
-import { Subject } from 'rxjs'
-import { debounceTime, mergeMap } from 'rxjs/operators'
-import { Component, OnInit } from '@angular/core'
-import { AuthService, ConfirmService, Notifier, ScreenService, User } from '@app/core'
+import { mergeMap } from 'rxjs/operators'
+import { Component } from '@angular/core'
+import { AuthService, ConfirmService, Notifier, ScreenService } from '@app/core'
 import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
 
 @Component({
   templateUrl: './my-video-channels.component.html',
   styleUrls: [ './my-video-channels.component.scss' ]
 })
-export class MyVideoChannelsComponent implements OnInit {
+export class MyVideoChannelsComponent {
   totalItems: number
 
   videoChannels: VideoChannel[] = []
+
   videoChannelsChartData: ChartData[]
   videoChannelsMinimumDailyViews = 0
   videoChannelsMaximumDailyViews: number
 
-  channelsSearch: string
-  channelsSearchChanged = new Subject<string>()
-
   chartOptions: any
 
-  private user: User
+  search: string
 
   constructor (
     private authService: AuthService,
@@ -31,31 +28,15 @@ export class MyVideoChannelsComponent implements OnInit {
     private confirmService: ConfirmService,
     private videoChannelService: VideoChannelService,
     private screenService: ScreenService
-    ) {}
-
-  ngOnInit () {
-    this.user = this.authService.getUser()
-
-    this.loadVideoChannels()
-
-    this.channelsSearchChanged
-      .pipe(debounceTime(500))
-      .subscribe(() => {
-        this.loadVideoChannels()
-      })
-  }
+  ) {}
 
   get isInSmallView () {
     return this.screenService.isInSmallView()
   }
 
-  resetSearch () {
-    this.channelsSearch = ''
-    this.onChannelsSearchChanged()
-  }
-
-  onChannelsSearchChanged () {
-    this.channelsSearchChanged.next()
+  onSearch (search: string) {
+    this.search = search
+    this.loadVideoChannels()
   }
 
   async deleteVideoChannel (videoChannel: VideoChannel) {
@@ -85,8 +66,11 @@ channel with the same name (${videoChannel.name})!`,
 
   private loadVideoChannels () {
     this.authService.userInformationLoaded
-        .pipe(mergeMap(() => this.videoChannelService.listAccountVideoChannels(this.user.account, null, true, this.channelsSearch)))
-        .subscribe(res => {
+        .pipe(mergeMap(() => {
+          const user = this.authService.getUser()
+
+          return this.videoChannelService.listAccountVideoChannels(user.account, null, true, this.search)
+        })).subscribe(res => {
           this.videoChannels = res.data
           this.totalItems = res.total
 
index 9dec64645622067bf79cd69dd7ebd5340dc0793d..45ca37e0db6c400c12481a3d6002b895e0fc1fab 100644 (file)
@@ -5,14 +5,7 @@
 
 <div class="top-buttons">
   <div class="search-wrapper">
-    <div class="input-group has-feedback has-clear">
-      <input
-        type="text" name="history-search" id="history-search" i18n-placeholder placeholder="Search your history"
-        (keyup)="onSearch($event)"
-      >
-      <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-      <span class="sr-only" i18n>Clear filters</span>
-    </div>
+    <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
   </div>
 
   <div class="history-switch">
   </button>
 </div>
 
-
-<div class="no-history" i18n *ngIf="hasDoneFirstQuery && videos.length === 0">You don't have any video in your watch history yet.</div>
-
-<div myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()" class="videos">
-  <div class="video" *ngFor="let video of videos">
-    <my-video-miniature
-      [video]="video" [displayAsRow]="true"
-      (videoRemoved)="removeVideoFromArray(video)" (videoBlocked)="removeVideoFromArray(video)"
-    ></my-video-miniature>
-  </div>
-</div>
+<my-videos-selection
+  [pagination]="pagination"
+  [(videosModel)]="videos"
+  [miniatureDisplayOptions]="miniatureDisplayOptions"
+  [titlePage]="titlePage"
+  [getVideosObservableFunction]="getVideosObservableFunction"
+  [user]="user"
+  [loadOnInit]="false"
+  i18n-noResultMessage noResultMessage="You don't have any video in your watch history yet."
+  [enableSelection]="false"
+  #videosSelection
+></my-videos-selection>
index 1695bd7ad8aaf7a145ea05f6f538f8e76ecda86b..ad83db7abc41bfbd6e267b0f10f5615fdcee9636 100644 (file)
@@ -1,36 +1,55 @@
-import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
+import { Subject } from 'rxjs'
+import { tap } from 'rxjs/operators'
+import { Component, ComponentFactoryResolver, OnInit, ViewChild } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
 import {
   AuthService,
   ComponentPagination,
   ConfirmService,
+  DisableForReuseHook,
   LocalStorageService,
   Notifier,
   ScreenService,
   ServerService,
+  User,
   UserService
 } from '@app/core'
 import { immutableAssign } from '@app/helpers'
-import { UserHistoryService } from '@app/shared/shared-main'
-import { AbstractVideoList } from '@app/shared/shared-video-miniature'
-import { Subject } from 'rxjs'
-import { debounceTime, tap, distinctUntilChanged } from 'rxjs/operators'
+import { UserHistoryService, Video } from '@app/shared/shared-main'
+import { MiniatureDisplayOptions, VideosSelectionComponent } from '@app/shared/shared-video-miniature'
 
 @Component({
   templateUrl: './my-history.component.html',
   styleUrls: [ './my-history.component.scss' ]
 })
-export class MyHistoryComponent extends AbstractVideoList implements OnInit, OnDestroy {
+export class MyHistoryComponent implements OnInit, DisableForReuseHook {
+  @ViewChild('videosSelection', { static: true }) videosSelection: VideosSelectionComponent
+
   titlePage: string
   pagination: ComponentPagination = {
     currentPage: 1,
     itemsPerPage: 5,
     totalItems: null
   }
+
   videosHistoryEnabled: boolean
-  search: string
 
-  protected searchStream: Subject<string>
+  miniatureDisplayOptions: MiniatureDisplayOptions = {
+    date: true,
+    views: true,
+    by: true,
+    privacyLabel: false,
+    privacyText: true,
+    state: true,
+    blacklistInfo: true
+  }
+
+  getVideosObservableFunction = this.getVideosObservable.bind(this)
+
+  user: User
+
+  videos: Video[] = []
+  search: string
 
   constructor (
     protected router: Router,
@@ -45,45 +64,31 @@ export class MyHistoryComponent extends AbstractVideoList implements OnInit, OnD
     private userHistoryService: UserHistoryService,
     protected cfr: ComponentFactoryResolver
   ) {
-    super()
-
     this.titlePage = $localize`My watch history`
   }
 
   ngOnInit () {
-    super.ngOnInit()
+    this.user = this.authService.getUser()
 
     this.authService.userInformationLoaded
-      .subscribe(() => {
-        this.videosHistoryEnabled = this.authService.getUser().videosHistoryEnabled
-      })
-
-    this.searchStream = new Subject()
+      .subscribe(() => this.videosHistoryEnabled = this.user.videosHistoryEnabled)
+  }
 
-    this.searchStream
-      .pipe(
-        debounceTime(400),
-        distinctUntilChanged()
-      )
-      .subscribe(search => {
-        this.search = search
-        this.reloadVideos()
-      })
+  disableForReuse () {
+    this.videosSelection.disableForReuse()
   }
 
-  onSearch (event: Event) {
-    const target = event.target as HTMLInputElement
-    this.searchStream.next(target.value)
+  enabledForReuse () {
+    this.videosSelection.enabledForReuse()
   }
 
-  resetSearch () {
-    const searchInput = document.getElementById('history-search') as HTMLInputElement
-    searchInput.value = ''
-    this.searchStream.next('')
+  reloadData () {
+    this.videosSelection.reloadVideos()
   }
 
-  ngOnDestroy () {
-    super.ngOnDestroy()
+  onSearch (search: string) {
+    this.search = search
+    this.reloadData()
   }
 
   getVideosObservable (page: number) {
@@ -129,7 +134,7 @@ export class MyHistoryComponent extends AbstractVideoList implements OnInit, OnD
           () => {
             this.notifier.success($localize`Videos history deleted`)
 
-            this.reloadVideos()
+            this.reloadData()
           },
 
           err => this.notifier.error(err.message)
index a938023b4e4ecf0cdeb9d81416d4eaee347f6a78..aaf028474c586f617670c037b0c14d2d7c5e2fbd 100644 (file)
@@ -48,18 +48,18 @@ export class MyOwnershipComponent extends RestTable implements OnInit {
   }
 
   accepted () {
-    this.loadData()
+    this.reloadData()
   }
 
   refuse (videoChangeOwnership: VideoChangeOwnership) {
     this.videoOwnershipService.refuseOwnership(videoChangeOwnership.id)
       .subscribe(
-        () => this.loadData(),
+        () => this.reloadData(),
         err => this.notifier.error(err.message)
       )
   }
 
-  protected loadData () {
+  protected reloadData () {
     return this.videoOwnershipService.getOwnershipChanges(this.pagination, this.sort)
       .subscribe(
         resultList => {
index 853d47fe6fb6d0869cce21cbd77410a668413479..f91cebacfbbf1a3e5904526f85837d1aebbdacdf 100644 (file)
@@ -7,12 +7,7 @@
 </h1>
 
 <div class="video-subscriptions-header">
-  <div class="has-feedback has-clear">
-    <input type="text" placeholder="Search your subscriptions" i18n-placeholder [(ngModel)]="subscriptionsSearch"
-      (ngModelChange)="onSubscriptionsSearchChanged()" />
-    <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-    <span class="sr-only" i18n>Clear filters</span>
-  </div>
+  <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
 </div>
 
 <div class="no-results" i18n *ngIf="pagination.totalItems === 0">You don't have any subscription yet.</div>
index 53ceaa250f5cac0ba2b3eda55fa1be93efedbc67..6c1ddf7167a19b2714d71cad9ad47cdb0591027e 100644 (file)
@@ -58,6 +58,7 @@ input[type=text] {
 
 .video-subscriptions-header {
   margin-bottom: 30px;
+  display: flex;
 }
 
 @media screen and (max-width: $small-view) {
index 3b748eccf30b0d5dc8589649173bfdcdc3063714..1f4a931a01a1a6a6745fbccb193ffea121375dc4 100644 (file)
@@ -1,6 +1,5 @@
 import { Subject } from 'rxjs'
-import { debounceTime } from 'rxjs/operators'
-import { Component, OnInit } from '@angular/core'
+import { Component } from '@angular/core'
 import { ComponentPagination, Notifier } from '@app/core'
 import { VideoChannel } from '@app/shared/shared-main'
 import { UserSubscriptionService } from '@app/shared/shared-user-subscription'
@@ -9,7 +8,7 @@ import { UserSubscriptionService } from '@app/shared/shared-user-subscription'
   templateUrl: './my-subscriptions.component.html',
   styleUrls: [ './my-subscriptions.component.scss' ]
 })
-export class MySubscriptionsComponent implements OnInit {
+export class MySubscriptionsComponent {
   videoChannels: VideoChannel[] = []
 
   pagination: ComponentPagination = {
@@ -20,34 +19,13 @@ export class MySubscriptionsComponent implements OnInit {
 
   onDataSubject = new Subject<any[]>()
 
-  subscriptionsSearch: string
-  subscriptionsSearchChanged = new Subject<string>()
+  search: string
 
   constructor (
     private userSubscriptionService: UserSubscriptionService,
     private notifier: Notifier
   ) {}
 
-  ngOnInit () {
-    this.loadSubscriptions()
-
-    this.subscriptionsSearchChanged
-      .pipe(debounceTime(500))
-      .subscribe(() => {
-        this.pagination.currentPage = 1
-        this.loadSubscriptions(false)
-      })
-  }
-
-  resetSearch () {
-    this.subscriptionsSearch = ''
-    this.onSubscriptionsSearchChanged()
-  }
-
-  onSubscriptionsSearchChanged () {
-    this.subscriptionsSearchChanged.next()
-  }
-
   onNearOfBottom () {
     // Last page
     if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return
@@ -56,8 +34,13 @@ export class MySubscriptionsComponent implements OnInit {
     this.loadSubscriptions()
   }
 
+  onSearch (search: string) {
+    this.search = search
+    this.loadSubscriptions(false)
+  }
+
   private loadSubscriptions (more = true) {
-    this.userSubscriptionService.listSubscriptions({ pagination: this.pagination, search: this.subscriptionsSearch })
+    this.userSubscriptionService.listSubscriptions({ pagination: this.pagination, search: this.search })
         .subscribe(
           res => {
             this.videoChannels = more
index d6d7d7a1b8c9ca1489f0924220c2447b275aa904..359535526658682e2c3d89b196df7df65539e262 100644 (file)
@@ -62,7 +62,7 @@ export class MyVideoImportsComponent extends RestTable implements OnInit {
     return '/videos/update/' + video.uuid
   }
 
-  protected loadData () {
+  protected reloadData () {
     this.videoImportService.getMyVideoImports(this.pagination, this.sort)
         .subscribe(
           resultList => {
index b88ea3db7361687e8f7ab27d6920ccd7efc14cd7..309afcf137f8f2ca1f835722ec165a9427c2e894 100644 (file)
@@ -4,12 +4,7 @@
 </h1>
 
 <div class="video-playlists-header d-flex justify-content-between">
-  <div class="has-feedback has-clear">
-    <input type="text" placeholder="Search your playlists" i18n-placeholder [(ngModel)]="videoPlaylistsSearch"
-      (ngModelChange)="onVideoPlaylistSearchChanged()" />
-    <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-    <span class="sr-only" i18n>Clear filters</span>
-  </div>
+  <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
 
   <a class="create-button" routerLink="create">
     <my-global-icon iconName="add" aria-hidden="true"></my-global-icon>
index f6d39492320b57d5a7d15ab9967463c2812bef3e..d90102693acab006a4dd542ef65a6124e1a45f14 100644 (file)
@@ -1,7 +1,7 @@
 import { Subject } from 'rxjs'
-import { debounceTime, mergeMap } from 'rxjs/operators'
-import { Component, OnInit } from '@angular/core'
-import { AuthService, ComponentPagination, ConfirmService, Notifier, User } from '@app/core'
+import { mergeMap } from 'rxjs/operators'
+import { Component } from '@angular/core'
+import { AuthService, ComponentPagination, ConfirmService, Notifier } from '@app/core'
 import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist'
 import { VideoPlaylistType } from '@shared/models'
 
@@ -9,10 +9,8 @@ import { VideoPlaylistType } from '@shared/models'
   templateUrl: './my-video-playlists.component.html',
   styleUrls: [ './my-video-playlists.component.scss' ]
 })
-export class MyVideoPlaylistsComponent implements OnInit {
-  videoPlaylistsSearch: string
+export class MyVideoPlaylistsComponent {
   videoPlaylists: VideoPlaylist[] = []
-  videoPlaylistSearchChanged = new Subject<string>()
 
   pagination: ComponentPagination = {
     currentPage: 1,
@@ -22,27 +20,14 @@ export class MyVideoPlaylistsComponent implements OnInit {
 
   onDataSubject = new Subject<any[]>()
 
-  private user: User
+  search: string
 
   constructor (
     private authService: AuthService,
     private notifier: Notifier,
     private confirmService: ConfirmService,
     private videoPlaylistService: VideoPlaylistService
-    ) {}
-
-  ngOnInit () {
-    this.user = this.authService.getUser()
-
-    this.loadVideoPlaylists()
-
-    this.videoPlaylistSearchChanged
-      .pipe(
-        debounceTime(500))
-      .subscribe(() => {
-        this.loadVideoPlaylists(true)
-      })
-  }
+  ) {}
 
   async deleteVideoPlaylist (videoPlaylist: VideoPlaylist) {
     const res = await this.confirmService.confirm(
@@ -76,22 +61,20 @@ export class MyVideoPlaylistsComponent implements OnInit {
     this.loadVideoPlaylists()
   }
 
-  resetSearch () {
-    this.videoPlaylistsSearch = ''
-    this.onVideoPlaylistSearchChanged()
-  }
-
-  onVideoPlaylistSearchChanged () {
-    this.videoPlaylistSearchChanged.next()
+  onSearch (search: string) {
+    this.search = search
+    this.loadVideoPlaylists(true)
   }
 
   private loadVideoPlaylists (reset = false) {
     this.authService.userInformationLoaded
         .pipe(mergeMap(() => {
-          return this.videoPlaylistService.listAccountPlaylists(this.user.account, this.pagination, '-updatedAt', this.videoPlaylistsSearch)
-        }))
-        .subscribe(res => {
+          const user = this.authService.getUser()
+
+          return this.videoPlaylistService.listAccountPlaylists(user.account, this.pagination, '-updatedAt', this.search)
+        })).subscribe(res => {
           if (reset) this.videoPlaylists = []
+
           this.videoPlaylists = this.videoPlaylists.concat(res.data)
           this.pagination.totalItems = res.total
 
index 7c1cdb511e678cdb18dbecb3bdc376a2faf52f96..8d8b482add3756970736a71397b23fe0efb7b581 100644 (file)
@@ -19,7 +19,7 @@
 </h1>
 
 <div class="videos-header d-flex justify-content-between">
-  <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)" (resetTableFilter)="resetTableFilter()"></my-advanced-input-filter>
+  <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter>
 
   <div class="peertube-select-container peertube-select-button">
     <select [(ngModel)]="sort" (ngModelChange)="onChangeSortColumn()" class="form-control">
@@ -41,6 +41,7 @@
   [titlePage]="titlePage"
   [getVideosObservableFunction]="getVideosObservableFunction"
   [user]="user"
+  [loadOnInit]="false"
   #videosSelection
 >
   <ng-template ptTemplate="globalButtons">
@@ -59,6 +60,5 @@
   </ng-template>
 </my-videos-selection>
 
-
 <my-video-change-ownership #videoChangeOwnershipModal></my-video-change-ownership>
 <my-live-stream-information #liveStreamInformationModal></my-live-stream-information>
index f9c1b32b036b53e9c90ddb3d5225c201033e3649..1e4a4406d6369d0538cdd0cc022264b8321990a3 100644 (file)
@@ -1,8 +1,8 @@
 import { concat, Observable } from 'rxjs'
 import { tap, toArray } from 'rxjs/operators'
-import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'
+import { Component, OnInit, ViewChild } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
-import { AuthService, ComponentPagination, ConfirmService, Notifier, RouteFilter, ScreenService, ServerService, User } from '@app/core'
+import { AuthService, ComponentPagination, ConfirmService, Notifier, ScreenService, ServerService, User } from '@app/core'
 import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
 import { immutableAssign } from '@app/helpers'
 import { AdvancedInputFilter } from '@app/shared/shared-forms'
@@ -16,7 +16,7 @@ import { VideoChangeOwnershipComponent } from './modals/video-change-ownership.c
   templateUrl: './my-videos.component.html',
   styleUrls: [ './my-videos.component.scss' ]
 })
-export class MyVideosComponent extends RouteFilter implements OnInit, AfterViewInit, DisableForReuseHook {
+export class MyVideosComponent implements OnInit, DisableForReuseHook {
   @ViewChild('videosSelection', { static: true }) videosSelection: VideosSelectionComponent
   @ViewChild('videoChangeOwnershipModal', { static: true }) videoChangeOwnershipModal: VideoChangeOwnershipComponent
   @ViewChild('liveStreamInformationModal', { static: true }) liveStreamInformationModal: LiveStreamInformationComponent
@@ -42,6 +42,7 @@ export class MyVideosComponent extends RouteFilter implements OnInit, AfterViewI
 
   videos: Video[] = []
   getVideosObservableFunction = this.getVideosObservable.bind(this)
+
   sort: VideoSortField = '-publishedAt'
 
   user: User
@@ -53,6 +54,8 @@ export class MyVideosComponent extends RouteFilter implements OnInit, AfterViewI
     }
   ]
 
+  private search: string
+
   constructor (
     protected router: Router,
     protected serverService: ServerService,
@@ -63,8 +66,6 @@ export class MyVideosComponent extends RouteFilter implements OnInit, AfterViewI
     private confirmService: ConfirmService,
     private videoService: VideoService
   ) {
-    super()
-
     this.titlePage = $localize`My videos`
   }
 
@@ -72,16 +73,14 @@ export class MyVideosComponent extends RouteFilter implements OnInit, AfterViewI
     this.buildActions()
 
     this.user = this.authService.getUser()
-
-    this.initSearch()
-    this.listenToSearchChange()
   }
 
-  ngAfterViewInit () {
-    if (this.search) this.setTableFilter(this.search, false)
+  onSearch (search: string) {
+    this.search = search
+    this.reloadData()
   }
 
-  loadData () {
+  reloadData () {
     this.videosSelection.reloadVideos()
   }
 
index 9baab8a3905591c0512742e1e8f325ee55f89aef..a5b48f10c6f17dc85108ce7e049003c1ee0a378a 100644 (file)
@@ -1,25 +1,22 @@
 import * as debug from 'debug'
 import { LazyLoadEvent, SortMeta } from 'primeng/api'
-import { Subject } from 'rxjs'
 import { ActivatedRoute, Router } from '@angular/router'
 import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
-import { RouteFilter } from '../routing'
 import { RestPagination } from './rest-pagination'
 
 const logger = debug('peertube:tables:RestTable')
 
-export abstract class RestTable extends RouteFilter {
+export abstract class RestTable {
 
   abstract totalRecords: number
   abstract sort: SortMeta
   abstract pagination: RestPagination
 
-  search: string
   rowsPerPageOptions = [ 10, 20, 50, 100 ]
   rowsPerPage = this.rowsPerPageOptions[0]
   expandedRows = {}
 
-  protected searchStream: Subject<string>
+  search: string
 
   protected route: ActivatedRoute
   protected router: Router
@@ -28,7 +25,6 @@ export abstract class RestTable extends RouteFilter {
 
   initialize () {
     this.loadSort()
-    this.initSearch()
   }
 
   loadSort () {
@@ -56,7 +52,7 @@ export abstract class RestTable extends RouteFilter {
       count: this.rowsPerPage
     }
 
-    this.loadData()
+    this.reloadData()
     this.saveSort()
   }
 
@@ -74,13 +70,18 @@ export abstract class RestTable extends RouteFilter {
         count: this.rowsPerPage
       }
 
-      this.loadData()
+      this.reloadData()
     }
 
     this.expandedRows = {}
   }
 
-  protected abstract loadData (): void
+  onSearch (search: string) {
+    this.search = search
+    this.reloadData()
+  }
+
+  protected abstract reloadData (): void
 
   private getSortLocalStorageKey () {
     return 'rest-table-sort-' + this.getIdentifier()
index d53a4ae2c8b8390dbe740e58cb2a8906b34d6e07..239c27caf9bd67dbc9d0f96f7b74c3d5b9efb729 100644 (file)
@@ -5,7 +5,6 @@ export * from './login-guard.service'
 export * from './menu-guard.service'
 export * from './preload-selected-modules-list'
 export * from './redirect.service'
-export * from './route-filter'
 export * from './server-config-resolver.service'
 export * from './unlogged-guard.service'
 export * from './user-right-guard.service'
diff --git a/client/src/app/core/routing/route-filter.ts b/client/src/app/core/routing/route-filter.ts
deleted file mode 100644 (file)
index d2eed7c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-import * as debug from 'debug'
-import { Subject } from 'rxjs'
-import { debounceTime, distinctUntilChanged } from 'rxjs/operators'
-import { ActivatedRoute, Params, Router } from '@angular/router'
-
-const logger = debug('peertube:tables:RouteFilter')
-
-export abstract class RouteFilter {
-  search: string
-
-  protected searchStream: Subject<string>
-
-  protected route: ActivatedRoute
-  protected router: Router
-
-  initSearch () {
-    this.searchStream = new Subject()
-
-    this.searchStream
-      .pipe(
-        debounceTime(200),
-        distinctUntilChanged()
-      )
-      .subscribe(search => {
-        this.search = search
-
-        logger('On search %s.', this.search)
-
-        this.loadData()
-      })
-  }
-
-  onSearch (event: Event) {
-    const target = event.target as HTMLInputElement
-    this.searchStream.next(target.value)
-
-    this.setQueryParams(target.value)
-  }
-
-  resetTableFilter () {
-    this.setTableFilter('')
-    this.setQueryParams('')
-    this.resetSearch()
-  }
-
-  resetSearch () {
-    this.searchStream.next('')
-    this.setTableFilter('')
-  }
-
-  listenToSearchChange () {
-    this.route.queryParams
-      .subscribe(params => {
-        this.search = params.search || ''
-
-        // Primeng table will run an event to load data
-        this.setTableFilter(this.search)
-      })
-  }
-
-  setTableFilter (filter: string, triggerEvent = true) {
-    // FIXME: cannot use ViewChild, so create a component for the filter input
-    const filterInput = document.getElementById('table-filter') as HTMLInputElement
-    if (!filterInput) return
-
-    filterInput.value = filter
-
-    if (triggerEvent) filterInput.dispatchEvent(new Event('keyup'))
-  }
-
-  protected abstract loadData (): void
-
-  private setQueryParams (search: string) {
-    const queryParams: Params = {}
-
-    if (search) Object.assign(queryParams, { search })
-    this.router.navigate([ ], { queryParams })
-  }
-}
index 22f84a96e5d3ed8fb3a135254e1636cc3db30e4a..b1c065c7a58edb467b28d6e0a1a51e5e705453cc 100644 (file)
@@ -1,6 +1,7 @@
 <p-table
-  [value]="abuses" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
-  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" dataKey="id" [resizableColumns]="true"
+  [value]="abuses" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [sortField]="sort.field" [sortOrder]="sort.order" dataKey="id" [resizableColumns]="true"
+  [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} reports"
   (onPage)="onPage($event)" [expandedRowKeys]="expandedRows"
@@ -8,7 +9,7 @@
   <ng-template pTemplate="caption">
     <div class="caption">
       <div class="ml-auto">
-        <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)" (resetTableFilter)="resetTableFilter()"></my-advanced-input-filter>
+        <my-advanced-input-filter [filters]="inputFilters" (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
     </div>
   </ng-template>
index f393c0d1e86ff0f550c1e6fbb83b6613fda1d179..4dc2b4f10b65c3a0ce0afc9dfc05396537896e26 100644 (file)
@@ -3,7 +3,7 @@ import truncate from 'lodash-es/truncate'
 import { SortMeta } from 'primeng/api'
 import { buildVideoLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils'
 import { environment } from 'src/environments/environment'
-import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core'
+import { Component, Input, OnInit, ViewChild } from '@angular/core'
 import { DomSanitizer } from '@angular/platform-browser'
 import { ActivatedRoute, Router } from '@angular/router'
 import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } from '@app/core'
@@ -11,10 +11,10 @@ import { Account, Actor, DropdownAction, Video, VideoService } from '@app/shared
 import { AbuseService, BlocklistService, VideoBlockService } from '@app/shared/shared-moderation'
 import { VideoCommentService } from '@app/shared/shared-video-comment'
 import { AbuseState, AdminAbuse } from '@shared/models'
+import { AdvancedInputFilter } from '../shared-forms'
 import { AbuseMessageModalComponent } from './abuse-message-modal.component'
 import { ModerationCommentModalComponent } from './moderation-comment-modal.component'
 import { ProcessedAbuse } from './processed-abuse.model'
-import { AdvancedInputFilter } from '../shared-forms'
 
 const logger = debug('peertube:moderation:AbuseListTableComponent')
 
@@ -23,7 +23,7 @@ const logger = debug('peertube:moderation:AbuseListTableComponent')
   templateUrl: './abuse-list-table.component.html',
   styleUrls: [ '../shared-moderation/moderation.scss', './abuse-list-table.component.scss' ]
 })
-export class AbuseListTableComponent extends RestTable implements OnInit, AfterViewInit {
+export class AbuseListTableComponent extends RestTable implements OnInit {
   @Input() viewType: 'admin' | 'user'
 
   @ViewChild('abuseMessagesModal', { static: true }) abuseMessagesModal: AbuseMessageModalComponent
@@ -89,11 +89,6 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
     ]
 
     this.initialize()
-    this.listenToSearchChange()
-  }
-
-  ngAfterViewInit () {
-    if (this.search) this.setTableFilter(this.search, false)
   }
 
   isAdminView () {
@@ -109,7 +104,7 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
   }
 
   onModerationCommentUpdated () {
-    this.loadData()
+    this.reloadData()
   }
 
   isAbuseAccepted (abuse: AdminAbuse) {
@@ -152,7 +147,7 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
     this.abuseService.removeAbuse(abuse).subscribe(
       () => {
         this.notifier.success($localize`Abuse deleted.`)
-        this.loadData()
+        this.reloadData()
       },
 
       err => this.notifier.error(err.message)
@@ -162,7 +157,7 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
   updateAbuseState (abuse: AdminAbuse, state: AbuseState) {
     this.abuseService.updateAbuse(abuse, { state })
       .subscribe(
-        () => this.loadData(),
+        () => this.reloadData(),
 
         err => this.notifier.error(err.message)
       )
@@ -189,7 +184,7 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV
     return Actor.IS_LOCAL(abuse.reporterAccount.host)
   }
 
-  protected loadData () {
+  protected reloadData () {
     logger('Loading data.')
 
     const options = {
index 03c4f127bc859512dbd82c7684592b9d2f9117dd..10d1296cf140cb492c319aaa0ca1c1ca9750725a 100644 (file)
@@ -1,5 +1,5 @@
 <div class="input-group has-feedback has-clear">
-  <div class="input-group-prepend c-hand" ngbDropdown placement="bottom-left auto" container="body">
+  <div *ngIf="hasFilters()" class="input-group-prepend c-hand" ngbDropdown placement="bottom-left auto" container="body">
     <div class="input-group-text" ngbDropdownToggle>
       <span class="caret" aria-haspopup="menu" role="button"></span>
     </div>
       <a *ngFor="let filter of filters" [routerLink]="[ '.' ]" [queryParams]="filter.queryParams" class="dropdown-item">
         {{ filter.label }}
       </a>
-
     </div>
   </div>
+
   <input
     type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
-    (keyup)="onSearch($event)"
+    [(ngModel)]="searchValue"
+    (keyup)="onInputSearch($event)"
   >
+
   <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="onResetTableFilter()"></a>
   <span class="sr-only" i18n>Clear filters</span>
 </div>
index 3940907518c4765e577910f0b95970460b3b8f50..1b0eed34b3e8cb52eb89d1fa5d712801d093f363 100644 (file)
@@ -1,27 +1,88 @@
-import { Component, EventEmitter, Input, Output } from '@angular/core'
-import { Params } from '@angular/router'
+import * as debug from 'debug'
+import { Subject } from 'rxjs'
+import { debounceTime, distinctUntilChanged } from 'rxjs/operators'
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
+import { ActivatedRoute, Params, Router } from '@angular/router'
 
 export type AdvancedInputFilter = {
   label: string
   queryParams: Params
 }
 
+const logger = debug('peertube:AdvancedInputFilterComponent')
+
 @Component({
   selector: 'my-advanced-input-filter',
   templateUrl: './advanced-input-filter.component.html',
   styleUrls: [ './advanced-input-filter.component.scss' ]
 })
-export class AdvancedInputFilterComponent {
+export class AdvancedInputFilterComponent implements OnInit {
   @Input() filters: AdvancedInputFilter[] = []
 
-  @Output() resetTableFilter = new EventEmitter<void>()
-  @Output() search = new EventEmitter<Event>()
+  @Output() search = new EventEmitter<string>()
+
+  searchValue: string
+
+  private searchStream: Subject<string>
+
+  constructor (
+    private route: ActivatedRoute,
+    private router: Router
+  ) { }
+
+  ngOnInit () {
+    this.initSearchStream()
+    this.listenToRouteSearchChange()
+  }
 
-  onSearch (event: Event) {
-    this.search.emit(event)
+  onInputSearch (event: Event) {
+    this.updateSearch((event.target as HTMLInputElement).value)
   }
 
   onResetTableFilter () {
-    this.resetTableFilter.emit()
+    this.updateSearch('')
+  }
+
+  hasFilters () {
+    return this.filters.length !== 0
+  }
+
+  private updateSearch (value: string) {
+    this.searchValue = value
+    this.searchStream.next(this.searchValue)
+  }
+
+  private listenToRouteSearchChange () {
+    this.route.queryParams
+      .subscribe(params => {
+        const search = params.search || ''
+
+        logger('On route search change "%s".', search)
+
+        this.updateSearch(search)
+      })
+  }
+
+  private initSearchStream () {
+    this.searchStream = new Subject()
+
+    this.searchStream
+      .pipe(
+        debounceTime(200),
+        distinctUntilChanged()
+      )
+      .subscribe(() => {
+        logger('On search "%s".', this.searchValue)
+
+        this.setQueryParams(this.searchValue)
+        this.search.emit(this.searchValue)
+      })
+  }
+
+  private setQueryParams (search: string) {
+    const queryParams: Params = {}
+
+    if (search) Object.assign(queryParams, { search })
+    this.router.navigate([ ], { queryParams })
   }
 }
index 84dd7dce3375ae96db321147a8d2ff80c350c64a..ffabb364651db629fe247cbf0cf48146511a6ee2 100644 (file)
   }
 }
 
-::ng-deep .dropdown-toggle::after {
+.sub-menu ::ng-deep .dropdown-toggle::after {
   position: relative;
   top: 2px;
 }
 
-::ng-deep .dropdown-menu {
+.sub-menu ::ng-deep .dropdown-menu {
   margin-top: 0 !important;
 }
 
index e914a7c3caf2dafe8bc5b54bcdd922dfa3fd01a2..a9fac08102aa6ed1faa80c2308f538748cc5150f 100644 (file)
 >
   <ng-template pTemplate="caption">
     <div class="caption">
-      <div class="ml-auto has-feedback has-clear">
-        <input
-          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
-          (keyup)="onSearch($event)"
-        >
-        <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-        <span class="sr-only" i18n>Clear filters</span>
+      <div class="ml-auto">
+        <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
     </div>
   </ng-template>
index 63a9df82365bd424d14165ee35aae9d38260378c..bc441811e3a25e11273106f0f8042aab27d7b44a 100644 (file)
@@ -1,16 +1,6 @@
 @import '_variables';
 @import '_mixins';
 
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-
-    flex-grow: 1;
-  }
-}
-
 .chip {
   @include chip;
 }
index 1bce65bf02722b46acd97908d78ef90f7de93161..1146aeec0b77326e3ae217089d3781b11076e527 100644 (file)
@@ -44,12 +44,12 @@ export class GenericAccountBlocklistComponent extends RestTable implements OnIni
             : $localize`Account ${blockedAccount.nameWithHost} unmuted by your instance.`
         )
 
-        this.loadData()
+        this.reloadData()
       }
     )
   }
 
-  protected loadData () {
+  protected reloadData () {
     const operation = this.mode === BlocklistComponentType.Account
       ? this.blocklistService.getUserAccountBlocklist({
         pagination: this.pagination,
index ab43d845761dbae6d748e3ac572778ba33526024..b13d06f03d50790ec55b5eb451617fcc436d910d 100644 (file)
   }
 }
 
-.input-group {
-  @include peertube-input-group(300px);
-
-  .dropdown-toggle::after {
-    margin-left: 0;
-  }
-}
-
 .chip {
   @include chip;
 }
 
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-    flex-grow: 1;
-  }
-}
-
 my-action-dropdown.show {
   ::ng-deep .dropdown-root {
     display: block !important;
index 537186f05d92de5bef7ae484bfbdd34b0d9872b1..c6d29bb21946dfbc2066ab108855554019fc3e62 100644 (file)
@@ -4,8 +4,9 @@
 </h1>
 
 <p-table
-  [value]="blockedServers" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
-  [sortField]="sort.field" [sortOrder]="sort.order" (onLazyLoad)="loadLazy($event)" (onPage)="onPage($event)"
+  [value]="blockedServers" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
+  [sortField]="sort.field" [sortOrder]="sort.order" (onPage)="onPage($event)"
+  [lazy]="true" (onLazyLoad)="loadLazy($event)" [lazyLoadOnInit]="false"
   [showCurrentPageReport]="true" i18n-currentPageReportTemplate
   currentPageReportTemplate="Showing {{'{first}'}} to {{'{last}'}} of {{'{totalRecords}'}} muted instances"
 >
         </a>
       </div>
 
-      <div class="ml-auto has-feedback has-clear">
-        <input
-          type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
-          (keyup)="onSearch($event)"
-        >
-        <a class="glyphicon glyphicon-remove-sign form-control-feedback form-control-clear" (click)="resetSearch()"></a>
-        <span class="sr-only" i18n>Clear filters</span>
+      <div class="ml-auto">
+        <my-advanced-input-filter (search)="onSearch($event)"></my-advanced-input-filter>
       </div>
     </div>
   </ng-template>
index af21c0c2019fc7c1bcd0e956ab46e9f530fe1a1e..a22972c5f46c750f16ee59aa5bdd38418649a733 100644 (file)
@@ -16,15 +16,6 @@ a {
   }
 }
 
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-    flex-grow: 1;
-  }
-}
-
 .unblock-button {
   @include peertube-button;
   @include grey-button;
@@ -34,15 +25,6 @@ a {
   @include create-button;
 }
 
-.caption {
-  justify-content: flex-end;
-
-  input {
-    @include peertube-input-text(250px);
-    flex-grow: 1;
-  }
-}
-
 .chip {
   @include chip;
 }
index 546fd53c395eebf6ee913d2eb9e1491357fc5931..274d8f6e9cf4eb2cd1632ffd912aa24ba45a6f8a 100644 (file)
@@ -46,7 +46,7 @@ export class GenericServerBlocklistComponent extends RestTable implements OnInit
             : $localize`Instance ${host} unmuted by your instance.`
         )
 
-        this.loadData()
+        this.reloadData()
       }
     )
   }
@@ -69,13 +69,13 @@ export class GenericServerBlocklistComponent extends RestTable implements OnInit
               : $localize`Instance ${domain} muted by your instance.`
           )
 
-          this.loadData()
+          this.reloadData()
         }
       )
     })
   }
 
-  protected loadData () {
+  protected reloadData () {
     const operation = this.mode === BlocklistComponentType.Account
       ? this.blocklistService.getUserServerBlocklist({
         pagination: this.pagination,
index dec9e99f335e5ea79250c612dfda89c31e3626ba..4ee90ce7fc456c4e7c9e5d01a3ee87496d28cfc8 100644 (file)
@@ -1,9 +1,9 @@
-<div class="no-results" i18n *ngIf="hasDoneFirstQuery && videos.length === 0">No results.</div>
+<div class="no-results" i18n *ngIf="hasDoneFirstQuery && videos.length === 0">{{ noResultMessage }}</div>
 
 <div myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()" class="videos">
   <div class="video" *ngFor="let video of videos; let i = index; trackBy: videoById">
 
-    <div class="checkbox-container">
+    <div class="checkbox-container" *ngIf="enableSelection">
       <my-peertube-checkbox [inputName]="'video-check-' + video.id" [(ngModel)]="_selection[video.id]"></my-peertube-checkbox>
     </div>
 
index f8c3800d7fa1e96a77da3a5b2083e26172b79b4e..d64ee9b981ecc3c94f84c5b935466614b403c8da 100644 (file)
@@ -31,6 +31,9 @@ export class VideosSelectionComponent extends AbstractVideoList implements OnIni
   @Input() pagination: ComponentPagination
   @Input() titlePage: string
   @Input() miniatureDisplayOptions: MiniatureDisplayOptions
+  @Input() noResultMessage = $localize`No results.`
+  @Input() enableSelection = true
+  @Input() loadOnInit = true
 
   @Input() getVideosObservableFunction: (page: number, sort?: VideoSortField) => Observable<ResultList<Video>>