aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+admin
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/+admin')
-rw-r--r--client/src/app/+admin/admin.module.ts4
-rw-r--r--client/src/app/+admin/follows/followers-list/followers-list.component.html2
-rw-r--r--client/src/app/+admin/follows/following-list/following-list.component.html2
-rw-r--r--client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html2
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html7
-rw-r--r--client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts3
-rw-r--r--client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html10
-rw-r--r--client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss16
-rw-r--r--client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.html2
-rw-r--r--client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts25
-rw-r--r--client/src/app/+admin/plugins/plugin-search/plugin-search.component.html8
-rw-r--r--client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts11
-rw-r--r--client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.html2
-rw-r--r--client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts54
-rw-r--r--client/src/app/+admin/plugins/shared/plugin-api.service.ts16
-rw-r--r--client/src/app/+admin/plugins/shared/plugin-list.component.scss2
-rw-r--r--client/src/app/+admin/system/debug/debug.component.html18
-rw-r--r--client/src/app/+admin/users/user-edit/user-edit.component.html2
-rw-r--r--client/src/app/+admin/users/user-edit/user-edit.component.scss8
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.html9
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.ts4
21 files changed, 114 insertions, 93 deletions
diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts
index fd648a425..8d1c3eadb 100644
--- a/client/src/app/+admin/admin.module.ts
+++ b/client/src/app/+admin/admin.module.ts
@@ -3,6 +3,7 @@ import { SelectButtonModule } from 'primeng/selectbutton'
3import { TableModule } from 'primeng/table' 3import { TableModule } from 'primeng/table'
4import { NgModule } from '@angular/core' 4import { NgModule } from '@angular/core'
5import { SharedAbuseListModule } from '@app/shared/shared-abuse-list' 5import { SharedAbuseListModule } from '@app/shared/shared-abuse-list'
6import { SharedActorImageModule } from '@app/shared/shared-actor-image'
6import { SharedFormModule } from '@app/shared/shared-forms' 7import { SharedFormModule } from '@app/shared/shared-forms'
7import { SharedGlobalIconModule } from '@app/shared/shared-icons' 8import { SharedGlobalIconModule } from '@app/shared/shared-icons'
8import { SharedMainModule } from '@app/shared/shared-main' 9import { SharedMainModule } from '@app/shared/shared-main'
@@ -38,6 +39,7 @@ import { JobService, LogsComponent, LogsService, SystemComponent } from './syste
38import { DebugComponent, DebugService } from './system/debug' 39import { DebugComponent, DebugService } from './system/debug'
39import { JobsComponent } from './system/jobs/jobs.component' 40import { JobsComponent } from './system/jobs/jobs.component'
40import { UserCreateComponent, UserListComponent, UserPasswordComponent, UsersComponent, UserUpdateComponent } from './users' 41import { UserCreateComponent, UserListComponent, UserPasswordComponent, UsersComponent, UserUpdateComponent } from './users'
42import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/shared-account-avatar.module'
41 43
42@NgModule({ 44@NgModule({
43 imports: [ 45 imports: [
@@ -49,6 +51,8 @@ import { UserCreateComponent, UserListComponent, UserPasswordComponent, UsersCom
49 SharedGlobalIconModule, 51 SharedGlobalIconModule,
50 SharedAbuseListModule, 52 SharedAbuseListModule,
51 SharedVideoCommentModule, 53 SharedVideoCommentModule,
54 SharedAccountAvatarModule,
55 SharedActorImageModule,
52 56
53 TableModule, 57 TableModule,
54 SelectButtonModule, 58 SelectButtonModule,
diff --git a/client/src/app/+admin/follows/followers-list/followers-list.component.html b/client/src/app/+admin/follows/followers-list/followers-list.component.html
index 622d464e4..633de9677 100644
--- a/client/src/app/+admin/follows/followers-list/followers-list.component.html
+++ b/client/src/app/+admin/follows/followers-list/followers-list.component.html
@@ -24,7 +24,7 @@
24 24
25 <ng-template pTemplate="header"> 25 <ng-template pTemplate="header">
26 <tr> 26 <tr>
27 <th style="width: 150px;">Actions</th> 27 <th style="width: 150px;" i18n>Actions</th>
28 <th i18n>Follower handle</th> 28 <th i18n>Follower handle</th>
29 <th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th> 29 <th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th>
30 <th style="width: 100px;" i18n pSortableColumn="score">Score <p-sortIcon field="score"></p-sortIcon></th> 30 <th style="width: 100px;" i18n pSortableColumn="score">Score <p-sortIcon field="score"></p-sortIcon></th>
diff --git a/client/src/app/+admin/follows/following-list/following-list.component.html b/client/src/app/+admin/follows/following-list/following-list.component.html
index cf87ec05f..f4e6a60fe 100644
--- a/client/src/app/+admin/follows/following-list/following-list.component.html
+++ b/client/src/app/+admin/follows/following-list/following-list.component.html
@@ -31,7 +31,7 @@
31 31
32 <ng-template pTemplate="header"> 32 <ng-template pTemplate="header">
33 <tr> 33 <tr>
34 <th style="width: 150px;">Action</th> 34 <th style="width: 150px;" i18n>Action</th>
35 <th i18n>Host</th> 35 <th i18n>Host</th>
36 <th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th> 36 <th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th>
37 <th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> 37 <th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
diff --git a/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html b/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html
index a654e51a6..f3bcca497 100644
--- a/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html
+++ b/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.html
@@ -24,7 +24,7 @@
24 <ng-template pTemplate="header"> 24 <ng-template pTemplate="header">
25 <tr> 25 <tr>
26 <th style="width: 40px;"></th> 26 <th style="width: 40px;"></th>
27 <th style="width: 150px;">Action</th> 27 <th style="width: 150px;" i18n>Action</th>
28 <th style="width: 160px;" i18n *ngIf="isDisplayingRemoteVideos()">Strategy</th> 28 <th style="width: 160px;" i18n *ngIf="isDisplayingRemoteVideos()">Strategy</th>
29 <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th > 29 <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th >
30 <th style="width: 100px;" i18n *ngIf="isDisplayingRemoteVideos()">Total size</th> 30 <th style="width: 100px;" i18n *ngIf="isDisplayingRemoteVideos()">Total size</th>
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
index 128f4962d..f5cf93adb 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
@@ -34,12 +34,7 @@
34 <td> 34 <td>
35 <a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer"> 35 <a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
36 <div class="chip two-lines"> 36 <div class="chip two-lines">
37 <img 37 <my-account-avatar [account]="accountBlock.blockedAccount"></my-account-avatar>
38 class="avatar"
39 [src]="accountBlock.blockedAccount.avatar?.path"
40 (error)="switchToDefaultAvatar($event)"
41 alt="Avatar"
42 >
43 <div> 38 <div>
44 {{ accountBlock.blockedAccount.displayName }} 39 {{ accountBlock.blockedAccount.displayName }}
45 <span class="text-muted">{{ accountBlock.blockedAccount.nameWithHost }}</span> 40 <span class="text-muted">{{ accountBlock.blockedAccount.nameWithHost }}</span>
diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
index 82c371f4d..d6aca10e7 100644
--- a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
+++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
@@ -164,7 +164,8 @@ export class VideoBlockListComponent extends RestTable implements OnInit, AfterV
164 baseUrl: `${environment.originServerUrl}/videos/embed/${entry.video.uuid}`, 164 baseUrl: `${environment.originServerUrl}/videos/embed/${entry.video.uuid}`,
165 title: false, 165 title: false,
166 warningTitle: false 166 warningTitle: false
167 }) 167 }),
168 entry.video.name
168 ) 169 )
169 } 170 }
170 171
diff --git a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html b/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
index fa4a8edfd..d360c3c51 100644
--- a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
+++ b/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
@@ -5,7 +5,7 @@
5 <my-feed [syndicationItems]="syndicationItems"></my-feed> 5 <my-feed [syndicationItems]="syndicationItems"></my-feed>
6</h1> 6</h1>
7 7
8<em>This view also shows comments from muted accounts.</em> 8<em i18n>This view also shows comments from muted accounts.</em>
9 9
10<p-table 10<p-table
11 [value]="comments" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions" 11 [value]="comments" [lazy]="true" [paginator]="totalRecords > 0" [totalRecords]="totalRecords" [rows]="rowsPerPage" [rowsPerPageOptions]="rowsPerPageOptions"
@@ -86,12 +86,8 @@
86 <td> 86 <td>
87 <a [href]="videoComment.account.localUrl" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer"> 87 <a [href]="videoComment.account.localUrl" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
88 <div class="chip two-lines"> 88 <div class="chip two-lines">
89 <img 89 <my-account-avatar [account]="videoComment.account"></my-account-avatar>
90 class="avatar" 90 <div>
91 [src]="videoComment.accountAvatarUrl"
92 alt=""
93 >
94 <div>
95 {{ videoComment.account.displayName }} 91 {{ videoComment.account.displayName }}
96 <span>{{ videoComment.by }}</span> 92 <span>{{ videoComment.by }}</span>
97 </div> 93 </div>
diff --git a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss b/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss
index d208944fe..c9262da09 100644
--- a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss
+++ b/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.scss
@@ -1,17 +1,9 @@
1@import 'mixins'; 1@import 'mixins';
2 2
3h1 { 3my-feed {
4 my-feed { 4 margin-left: 5px;
5 margin-left: 5px; 5 display: inline-block;
6 display: inline-block; 6 width: 15px;
7
8 ::ng-deep {
9 my-global-icon {
10 width: 15px !important;
11 top: 0 !important;
12 }
13 }
14 }
15} 7}
16 8
17my-global-icon { 9my-global-icon {
diff --git a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.html b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.html
index 82a965313..9cbec03a1 100644
--- a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.html
+++ b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.html
@@ -23,7 +23,7 @@
23 </a> 23 </a>
24 24
25 <div class="buttons"> 25 <div class="buttons">
26 <my-edit-button *ngIf="pluginType !== PluginType.THEME" [routerLink]="getShowRouterLink(plugin)" label="Settings" i18n-label></my-edit-button> 26 <my-edit-button *ngIf="!isTheme(plugin)" [routerLink]="getShowRouterLink(plugin)" label="Settings" i18n-label></my-edit-button>
27 27
28 <my-button class="update-button" *ngIf="isUpdateAvailable(plugin)" (click)="update(plugin)" [loading]="isUpdating(plugin)" 28 <my-button class="update-button" *ngIf="isUpdateAvailable(plugin)" (click)="update(plugin)" [loading]="isUpdating(plugin)"
29 [label]="getUpdateLabel(plugin)" icon="refresh" [attr.disabled]="isUpdating(plugin)" 29 [label]="getUpdateLabel(plugin)" icon="refresh" [attr.disabled]="isUpdating(plugin)"
diff --git a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts
index c78b19585..1a95980ae 100644
--- a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts
+++ b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts
@@ -31,8 +31,6 @@ export class PluginListInstalledComponent implements OnInit {
31 plugins: PeerTubePlugin[] = [] 31 plugins: PeerTubePlugin[] = []
32 updating: { [name: string]: boolean } = {} 32 updating: { [name: string]: boolean } = {}
33 33
34 PluginType = PluginType
35
36 onDataSubject = new Subject<any[]>() 34 onDataSubject = new Subject<any[]>()
37 35
38 constructor ( 36 constructor (
@@ -104,6 +102,10 @@ export class PluginListInstalledComponent implements OnInit {
104 return !!this.updating[this.getUpdatingKey(plugin)] 102 return !!this.updating[this.getUpdatingKey(plugin)]
105 } 103 }
106 104
105 isTheme (plugin: PeerTubePlugin) {
106 return plugin.type === PluginType.THEME
107 }
108
107 async uninstall (plugin: PeerTubePlugin) { 109 async uninstall (plugin: PeerTubePlugin) {
108 const res = await this.confirmService.confirm( 110 const res = await this.confirmService.confirm(
109 $localize`Do you really want to uninstall ${plugin.name}?`, 111 $localize`Do you really want to uninstall ${plugin.name}?`,
@@ -128,6 +130,16 @@ export class PluginListInstalledComponent implements OnInit {
128 const updatingKey = this.getUpdatingKey(plugin) 130 const updatingKey = this.getUpdatingKey(plugin)
129 if (this.updating[updatingKey]) return 131 if (this.updating[updatingKey]) return
130 132
133 if (this.isMajorUpgrade(plugin)) {
134 const res = await this.confirmService.confirm(
135 $localize`This is a major plugin upgrade. Please go on the plugin homepage to check potential release notes.`,
136 $localize`Upgrade`,
137 $localize`Proceed upgrade`
138 )
139
140 if (res === false) return
141 }
142
131 this.updating[updatingKey] = true 143 this.updating[updatingKey] = true
132 144
133 this.pluginApiService.update(plugin.name, plugin.type) 145 this.pluginApiService.update(plugin.name, plugin.type)
@@ -156,4 +168,13 @@ export class PluginListInstalledComponent implements OnInit {
156 private getUpdatingKey (plugin: PeerTubePlugin) { 168 private getUpdatingKey (plugin: PeerTubePlugin) {
157 return plugin.name + plugin.type 169 return plugin.name + plugin.type
158 } 170 }
171
172 private isMajorUpgrade (plugin: PeerTubePlugin) {
173 if (!plugin.latestVersion) return false
174
175 const latestMajor = plugin.latestVersion.split('.')[0]
176 const currentMajor = plugin.version.split('.')[0]
177
178 return latestMajor > currentMajor
179 }
159} 180}
diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
index 1b5fe45c6..727633399 100644
--- a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
+++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
@@ -3,7 +3,7 @@
3</div> 3</div>
4 4
5<div class="search-bar"> 5<div class="search-bar">
6 <input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..."/> 6 <input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." autofocus />
7</div> 7</div>
8 8
9<div class="alert alert-info" i18n *ngIf="pluginInstalled"> 9<div class="alert alert-info" i18n *ngIf="pluginInstalled">
@@ -20,8 +20,8 @@
20 <my-global-icon iconName="search"></my-global-icon> 20 <my-global-icon iconName="search"></my-global-icon>
21 21
22 <ng-container i18n> 22 <ng-container i18n>
23 {{ pagination.totalItems }} {pagination.totalItems, plural, =1 {result} other {results}} for "{{ search }}" 23 {{ pagination.totalItems }} {pagination.totalItems, plural, =1 {result} other {results}} for {{ search }}"
24 </ng-container> 24 </ng-container>
25 </ng-container> 25 </ng-container>
26</div> 26</div>
27 27
@@ -48,6 +48,8 @@
48 <span *ngIf="plugin.installed" class="badge badge-success">Installed</span> 48 <span *ngIf="plugin.installed" class="badge badge-success">Installed</span>
49 49
50 <div class="buttons"> 50 <div class="buttons">
51 <my-edit-button *ngIf="plugin.installed === true && !isThemeSearch()" [routerLink]="getShowRouterLink(plugin)" label="Settings" i18n-label></my-edit-button>
52
51 <my-button class="update-button" *ngIf="plugin.installed === false" (click)="install(plugin)" [loading]="isInstalling(plugin)" 53 <my-button class="update-button" *ngIf="plugin.installed === false" (click)="install(plugin)" [loading]="isInstalling(plugin)"
52 label="Install" icon="cloud-download" [attr.disabled]="isInstalling(plugin)" 54 label="Install" icon="cloud-download" [attr.disabled]="isInstalling(plugin)"
53 ></my-button> 55 ></my-button>
diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts
index 4c571dee4..d2c179aba 100644
--- a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts
+++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts
@@ -3,7 +3,7 @@ import { debounceTime, distinctUntilChanged } from 'rxjs/operators'
3import { Component, OnInit } from '@angular/core' 3import { Component, OnInit } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
5import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' 5import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service'
6import { ComponentPagination, ConfirmService, hasMoreItems, Notifier } from '@app/core' 6import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core'
7import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model' 7import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model'
8import { PluginType } from '@shared/models/plugins/plugin.type' 8import { PluginType } from '@shared/models/plugins/plugin.type'
9 9
@@ -39,6 +39,7 @@ export class PluginSearchComponent implements OnInit {
39 private searchSubject = new Subject<string>() 39 private searchSubject = new Subject<string>()
40 40
41 constructor ( 41 constructor (
42 private pluginService: PluginService,
42 private pluginApiService: PluginApiService, 43 private pluginApiService: PluginApiService,
43 private notifier: Notifier, 44 private notifier: Notifier,
44 private confirmService: ConfirmService, 45 private confirmService: ConfirmService,
@@ -119,6 +120,14 @@ export class PluginSearchComponent implements OnInit {
119 return this.pluginApiService.getPluginOrThemeHref(this.pluginType, name) 120 return this.pluginApiService.getPluginOrThemeHref(this.pluginType, name)
120 } 121 }
121 122
123 getShowRouterLink (plugin: PeerTubePluginIndex) {
124 return [ '/admin', 'plugins', 'show', this.pluginService.nameToNpmName(plugin.name, this.pluginType) ]
125 }
126
127 isThemeSearch () {
128 return this.pluginType === PluginType.THEME
129 }
130
122 async install (plugin: PeerTubePluginIndex) { 131 async install (plugin: PeerTubePluginIndex) {
123 if (this.installing[plugin.npmName]) return 132 if (this.installing[plugin.npmName]) return
124 133
diff --git a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.html b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.html
index cb2894568..ad65293d4 100644
--- a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.html
+++ b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.html
@@ -7,7 +7,7 @@
7 7
8 <form *ngIf="hasRegisteredSettings()" role="form" (ngSubmit)="formValidated()" [formGroup]="form"> 8 <form *ngIf="hasRegisteredSettings()" role="form" (ngSubmit)="formValidated()" [formGroup]="form">
9 <div class="form-group" *ngFor="let setting of registeredSettings"> 9 <div class="form-group" *ngFor="let setting of registeredSettings">
10 <my-dynamic-form-field [form]="form" [setting]="setting" [formErrors]="formErrors"></my-dynamic-form-field> 10 <my-dynamic-form-field [hidden]="isSettingHidden(setting)" [form]="form" [setting]="setting" [formErrors]="formErrors"></my-dynamic-form-field>
11 </div> 11 </div>
12 12
13 <input type="submit" i18n value="Update plugin settings" [disabled]="!form.valid"> 13 <input type="submit" i18n value="Update plugin settings" [disabled]="!form.valid">
diff --git a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
index 4e60ca290..ca9ad9922 100644
--- a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
+++ b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
@@ -2,7 +2,7 @@ import { Subscription } from 'rxjs'
2import { map, switchMap } from 'rxjs/operators' 2import { map, switchMap } from 'rxjs/operators'
3import { Component, OnDestroy, OnInit } from '@angular/core' 3import { Component, OnDestroy, OnInit } from '@angular/core'
4import { ActivatedRoute } from '@angular/router' 4import { ActivatedRoute } from '@angular/router'
5import { Notifier } from '@app/core' 5import { Notifier, PluginService } from '@app/core'
6import { BuildFormArgument } from '@app/shared/form-validators' 6import { BuildFormArgument } from '@app/shared/form-validators'
7import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' 7import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
8import { PeerTubePlugin, RegisterServerSettingOptions } from '@shared/models' 8import { PeerTubePlugin, RegisterServerSettingOptions } from '@shared/models'
@@ -19,10 +19,12 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
19 pluginTypeLabel: string 19 pluginTypeLabel: string
20 20
21 private sub: Subscription 21 private sub: Subscription
22 private npmName: string
22 23
23 constructor ( 24 constructor (
24 protected formValidatorService: FormValidatorService, 25 protected formValidatorService: FormValidatorService,
25 private pluginService: PluginApiService, 26 private pluginService: PluginService,
27 private pluginAPIService: PluginApiService,
26 private notifier: Notifier, 28 private notifier: Notifier,
27 private route: ActivatedRoute 29 private route: ActivatedRoute
28 ) { 30 ) {
@@ -32,9 +34,9 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
32 ngOnInit () { 34 ngOnInit () {
33 this.sub = this.route.params.subscribe( 35 this.sub = this.route.params.subscribe(
34 routeParams => { 36 routeParams => {
35 const npmName = routeParams['npmName'] 37 this.npmName = routeParams['npmName']
36 38
37 this.loadPlugin(npmName) 39 this.loadPlugin(this.npmName)
38 } 40 }
39 ) 41 )
40 } 42 }
@@ -46,7 +48,7 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
46 formValidated () { 48 formValidated () {
47 const settings = this.form.value 49 const settings = this.form.value
48 50
49 this.pluginService.updatePluginSettings(this.plugin.name, this.plugin.type, settings) 51 this.pluginAPIService.updatePluginSettings(this.plugin.name, this.plugin.type, settings)
50 .subscribe( 52 .subscribe(
51 () => { 53 () => {
52 this.notifier.success($localize`Settings updated.`) 54 this.notifier.success($localize`Settings updated.`)
@@ -60,18 +62,27 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
60 return Array.isArray(this.registeredSettings) && this.registeredSettings.length !== 0 62 return Array.isArray(this.registeredSettings) && this.registeredSettings.length !== 0
61 } 63 }
62 64
65 isSettingHidden (setting: RegisterServerSettingOptions) {
66 const script = this.pluginService.getRegisteredSettingsScript(this.npmName)
67
68 if (!script?.isSettingHidden) return false
69
70 return script.isSettingHidden({ setting, formValues: this.form.value })
71 }
72
63 private loadPlugin (npmName: string) { 73 private loadPlugin (npmName: string) {
64 this.pluginService.getPlugin(npmName) 74 this.pluginAPIService.getPlugin(npmName)
65 .pipe(switchMap(plugin => { 75 .pipe(switchMap(plugin => {
66 return this.pluginService.getPluginRegisteredSettings(plugin.name, plugin.type) 76 return this.pluginAPIService.getPluginRegisteredSettings(plugin.name, plugin.type)
67 .pipe(map(data => ({ plugin, registeredSettings: data.registeredSettings }))) 77 .pipe(map(data => ({ plugin, registeredSettings: data.registeredSettings })))
68 })) 78 }))
69 .subscribe( 79 .subscribe(
70 ({ plugin, registeredSettings }) => { 80 async ({ plugin, registeredSettings }) => {
71 this.plugin = plugin 81 this.plugin = plugin
72 this.registeredSettings = registeredSettings
73 82
74 this.pluginTypeLabel = this.pluginService.getPluginTypeLabel(this.plugin.type) 83 this.registeredSettings = await this.translateSettings(registeredSettings)
84
85 this.pluginTypeLabel = this.pluginAPIService.getPluginTypeLabel(this.plugin.type)
75 86
76 this.buildSettingsForm() 87 this.buildSettingsForm()
77 }, 88 },
@@ -104,4 +115,27 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
104 return registered.default 115 return registered.default
105 } 116 }
106 117
118 private async translateSettings (settings: RegisterServerSettingOptions[]) {
119 for (const setting of settings) {
120 for (const key of [ 'label', 'html', 'descriptionHTML' ]) {
121 if (setting[key]) setting[key] = await this.pluginService.translateBy(this.npmName, setting[key])
122 }
123
124 if (Array.isArray(setting.options)) {
125 const newOptions = []
126
127 for (const o of setting.options) {
128 newOptions.push({
129 value: o.value,
130 label: await this.pluginService.translateBy(this.npmName, o.label)
131 })
132 }
133
134 setting.options = newOptions
135 }
136 }
137
138 return settings
139 }
140
107} 141}
diff --git a/client/src/app/+admin/plugins/shared/plugin-api.service.ts b/client/src/app/+admin/plugins/shared/plugin-api.service.ts
index fad30576b..d91fccc09 100644
--- a/client/src/app/+admin/plugins/shared/plugin-api.service.ts
+++ b/client/src/app/+admin/plugins/shared/plugin-api.service.ts
@@ -94,7 +94,6 @@ export class PluginApiService {
94 94
95 return this.authHttp.get<RegisteredServerSettings>(path) 95 return this.authHttp.get<RegisteredServerSettings>(path)
96 .pipe( 96 .pipe(
97 switchMap(res => this.translateSettingsLabel(npmName, res)),
98 catchError(res => this.restExtractor.handleError(res)) 97 catchError(res => this.restExtractor.handleError(res))
99 ) 98 )
100 } 99 }
@@ -141,19 +140,4 @@ export class PluginApiService {
141 140
142 return `https://www.npmjs.com/package/peertube-${typeString}-${name}` 141 return `https://www.npmjs.com/package/peertube-${typeString}-${name}`
143 } 142 }
144
145 private translateSettingsLabel (npmName: string, res: RegisteredServerSettings): Observable<RegisteredServerSettings> {
146 return this.pluginService.translationsObservable
147 .pipe(
148 map(allTranslations => allTranslations[npmName]),
149 map(translations => {
150 const registeredSettings = res.registeredSettings
151 .map(r => {
152 return Object.assign({}, r, { label: peertubeTranslate(r.label, translations) })
153 })
154
155 return { registeredSettings }
156 })
157 )
158 }
159} 143}
diff --git a/client/src/app/+admin/plugins/shared/plugin-list.component.scss b/client/src/app/+admin/plugins/shared/plugin-list.component.scss
index 83030b7e0..f59a01b74 100644
--- a/client/src/app/+admin/plugins/shared/plugin-list.component.scss
+++ b/client/src/app/+admin/plugins/shared/plugin-list.component.scss
@@ -3,7 +3,7 @@
3 3
4.plugin { 4.plugin {
5 margin: 15px 0; 5 margin: 15px 0;
6 background-color: pvar(--submenuColor); 6 background-color: pvar(--submenuBackgroundColor);
7} 7}
8 8
9.first-row { 9.first-row {
diff --git a/client/src/app/+admin/system/debug/debug.component.html b/client/src/app/+admin/system/debug/debug.component.html
index 75f3df601..2dc509383 100644
--- a/client/src/app/+admin/system/debug/debug.component.html
+++ b/client/src/app/+admin/system/debug/debug.component.html
@@ -1,19 +1,19 @@
1<div class="root"> 1<div class="root">
2 <h4>IP</h4> 2 <h4 i18n>IP address</h4>
3 3
4 <p>PeerTube thinks your web browser public IP is <strong>{{ debug?.ip }}</strong>.</p> 4 <p i18n>PeerTube thinks your web browser public IP is <strong>{{ debug?.ip }}</strong>.</p>
5 5
6 <p>If this is not your correct public IP, please consider fixing it because:</p> 6 <p i18n>If this is not your correct public IP, please consider fixing it because:</p>
7 <ul> 7 <ul>
8 <li>Views may not be counted correctly (reduced compared to what they should be)</li> 8 <li i18n>Views may not be counted correctly (reduced compared to what they should be)</li>
9 <li>Anti brute force system could be overzealous</li> 9 <li i18n>Anti brute force system could be overzealous</li>
10 <li>P2P system could not work correctly</li> 10 <li i18n>P2P system could not work correctly</li>
11 </ul> 11 </ul>
12 12
13 <p>To fix it:<p> 13 <p i18n>To fix it:<p>
14 <ul> 14 <ul>
15 <li>Check the <code>trust_proxy</code> configuration key</li> 15 <li i18n>Check the <code>trust_proxy</code> configuration key</li>
16 <li>If you run PeerTube using Docker, check you run the <code>reverse-proxy</code> with <code>network_mode: "host"</code> 16 <li i18n>If you run PeerTube using Docker, check you run the <code>reverse-proxy</code> with <code>network_mode: "host"</code>
17 (see <a href="https://github.com/Chocobozzz/PeerTube/issues/1643#issuecomment-464789666">issue 1643</a>)</li> 17 (see <a href="https://github.com/Chocobozzz/PeerTube/issues/1643#issuecomment-464789666">issue 1643</a>)</li>
18 </ul> 18 </ul>
19</div> 19</div>
diff --git a/client/src/app/+admin/users/user-edit/user-edit.component.html b/client/src/app/+admin/users/user-edit/user-edit.component.html
index 243c6556a..5e92c0f36 100644
--- a/client/src/app/+admin/users/user-edit/user-edit.component.html
+++ b/client/src/app/+admin/users/user-edit/user-edit.component.html
@@ -72,7 +72,7 @@
72 <div class="anchor" id="user"></div> <!-- user anchor --> 72 <div class="anchor" id="user"></div> <!-- user anchor -->
73 <div *ngIf="isCreation()" class="account-title" i18n>NEW USER</div> 73 <div *ngIf="isCreation()" class="account-title" i18n>NEW USER</div>
74 <div *ngIf="!isCreation() && user" class="account-title"> 74 <div *ngIf="!isCreation() && user" class="account-title">
75 <my-actor-avatar-info [actor]="user.account"></my-actor-avatar-info> 75 <my-actor-avatar-edit [actor]="user.account" [editable]="false" [displaySubscribers]="false" [displayUsername]="false"></my-actor-avatar-edit>
76 </div> 76 </div>
77 </div> 77 </div>
78 78
diff --git a/client/src/app/+admin/users/user-edit/user-edit.component.scss b/client/src/app/+admin/users/user-edit/user-edit.component.scss
index aa87b8d6d..8b0ac8783 100644
--- a/client/src/app/+admin/users/user-edit/user-edit.component.scss
+++ b/client/src/app/+admin/users/user-edit/user-edit.component.scss
@@ -72,11 +72,3 @@ input[type=submit], button {
72 @include dashboard; 72 @include dashboard;
73 max-width: 900px; 73 max-width: 900px;
74} 74}
75
76my-actor-avatar-info ::ng-deep {
77 .actor-img-edit-container,
78 .actor-info-followers,
79 .actor-info-username {
80 display: none;
81 }
82}
diff --git a/client/src/app/+admin/users/user-list/user-list.component.html b/client/src/app/+admin/users/user-list/user-list.component.html
index 4a09fb392..e114f3425 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.html
+++ b/client/src/app/+admin/users/user-list/user-list.component.html
@@ -106,13 +106,8 @@
106 <td *ngIf="isSelected('username')"> 106 <td *ngIf="isSelected('username')">
107 <a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]"> 107 <a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]">
108 <div class="chip two-lines"> 108 <div class="chip two-lines">
109 <img 109 <my-account-avatar [account]="user?.account"></my-account-avatar>
110 class="avatar" 110 <div>
111 [src]="user?.account?.avatar?.path"
112 (error)="switchToDefaultAvatar($event)"
113 alt="Avatar"
114 >
115 <div>
116 <span class="user-table-primary-text">{{ user.account.displayName }}</span> 111 <span class="user-table-primary-text">{{ user.account.displayName }}</span>
117 <span class="text-muted">{{ user.username }}</span> 112 <span class="text-muted">{{ user.username }}</span>
118 </div> 113 </div>
diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts
index 7875b74ad..339e18206 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.ts
+++ b/client/src/app/+admin/users/user-list/user-list.component.ts
@@ -163,10 +163,6 @@ export class UserListComponent extends RestTable implements OnInit {
163 this.loadData() 163 this.loadData()
164 } 164 }
165 165
166 switchToDefaultAvatar ($event: Event) {
167 ($event.target as HTMLImageElement).src = Account.GET_DEFAULT_AVATAR_URL()
168 }
169
170 async unbanUsers (users: User[]) { 166 async unbanUsers (users: User[]) {
171 const res = await this.confirmService.confirm($localize`Do you really want to unban ${users.length} users?`, $localize`Unban`) 167 const res = await this.confirmService.confirm($localize`Do you really want to unban ${users.length} users?`, $localize`Unban`)
172 if (res === false) return 168 if (res === false) return