aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app')
-rw-r--r--client/src/app/+admin/admin-routing.module.ts4
-rw-r--r--client/src/app/+admin/admin.component.html4
-rw-r--r--client/src/app/+admin/admin.component.ts4
-rw-r--r--client/src/app/+admin/admin.module.ts15
-rw-r--r--client/src/app/+admin/plugins/index.ts1
-rw-r--r--client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.html13
-rw-r--r--client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.scss8
-rw-r--r--client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts72
-rw-r--r--client/src/app/+admin/plugins/plugin-search/plugin-search.component.html0
-rw-r--r--client/src/app/+admin/plugins/plugin-search/plugin-search.component.scss2
-rw-r--r--client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts30
-rw-r--r--client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.html0
-rw-r--r--client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.scss2
-rw-r--r--client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts14
-rw-r--r--client/src/app/+admin/plugins/plugins.component.html11
-rw-r--r--client/src/app/+admin/plugins/plugins.component.scss7
-rw-r--r--client/src/app/+admin/plugins/plugins.component.ts8
-rw-r--r--client/src/app/+admin/plugins/plugins.routes.ts53
-rw-r--r--client/src/app/+admin/plugins/shared/plugin-api.service.ts50
-rw-r--r--client/src/app/core/plugins/plugin.service.ts2
-rw-r--r--client/src/app/core/theme/theme.service.ts5
21 files changed, 302 insertions, 3 deletions
diff --git a/client/src/app/+admin/admin-routing.module.ts b/client/src/app/+admin/admin-routing.module.ts
index 215da1e4f..79c57221b 100644
--- a/client/src/app/+admin/admin-routing.module.ts
+++ b/client/src/app/+admin/admin-routing.module.ts
@@ -9,6 +9,7 @@ import { FollowsRoutes } from './follows'
9import { UsersRoutes } from './users' 9import { UsersRoutes } from './users'
10import { ModerationRoutes } from '@app/+admin/moderation/moderation.routes' 10import { ModerationRoutes } from '@app/+admin/moderation/moderation.routes'
11import { SystemRoutes } from '@app/+admin/system' 11import { SystemRoutes } from '@app/+admin/system'
12import { PluginsRoutes } from '@app/+admin/plugins/plugins.routes'
12 13
13const adminRoutes: Routes = [ 14const adminRoutes: Routes = [
14 { 15 {
@@ -26,7 +27,8 @@ const adminRoutes: Routes = [
26 ...UsersRoutes, 27 ...UsersRoutes,
27 ...ModerationRoutes, 28 ...ModerationRoutes,
28 ...SystemRoutes, 29 ...SystemRoutes,
29 ...ConfigRoutes 30 ...ConfigRoutes,
31 ...PluginsRoutes
30 ] 32 ]
31 } 33 }
32] 34]
diff --git a/client/src/app/+admin/admin.component.html b/client/src/app/+admin/admin.component.html
index 98f45a7d1..9a3d90c18 100644
--- a/client/src/app/+admin/admin.component.html
+++ b/client/src/app/+admin/admin.component.html
@@ -16,6 +16,10 @@
16 Configuration 16 Configuration
17 </a> 17 </a>
18 18
19 <a i18n *ngIf="hasPluginsRight()" routerLink="/admin/plugins" routerLinkActive="active" class="title-page">
20 Plugins/Themes
21 </a>
22
19 <a i18n *ngIf="hasJobsRight() || hasLogsRight() || hasDebugRight()" routerLink="/admin/system" routerLinkActive="active" class="title-page"> 23 <a i18n *ngIf="hasJobsRight() || hasLogsRight() || hasDebugRight()" routerLink="/admin/system" routerLinkActive="active" class="title-page">
20 System 24 System
21 </a> 25 </a>
diff --git a/client/src/app/+admin/admin.component.ts b/client/src/app/+admin/admin.component.ts
index 408de4837..b23999d40 100644
--- a/client/src/app/+admin/admin.component.ts
+++ b/client/src/app/+admin/admin.component.ts
@@ -28,6 +28,10 @@ export class AdminComponent {
28 return this.auth.getUser().hasRight(UserRight.MANAGE_CONFIGURATION) 28 return this.auth.getUser().hasRight(UserRight.MANAGE_CONFIGURATION)
29 } 29 }
30 30
31 hasPluginsRight () {
32 return this.auth.getUser().hasRight(UserRight.MANAGE_PLUGINS)
33 }
34
31 hasLogsRight () { 35 hasLogsRight () {
32 return this.auth.getUser().hasRight(UserRight.MANAGE_LOGS) 36 return this.auth.getUser().hasRight(UserRight.MANAGE_LOGS)
33 } 37 }
diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts
index 9ab883f60..256b7e1f5 100644
--- a/client/src/app/+admin/admin.module.ts
+++ b/client/src/app/+admin/admin.module.ts
@@ -21,11 +21,18 @@ import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } f
21import { JobsComponent } from '@app/+admin/system/jobs/jobs.component' 21import { JobsComponent } from '@app/+admin/system/jobs/jobs.component'
22import { JobService, LogsComponent, LogsService, SystemComponent } from '@app/+admin/system' 22import { JobService, LogsComponent, LogsService, SystemComponent } from '@app/+admin/system'
23import { DebugComponent, DebugService } from '@app/+admin/system/debug' 23import { DebugComponent, DebugService } from '@app/+admin/system/debug'
24import { PluginsComponent } from '@app/+admin/plugins/plugins.component'
25import { PluginListInstalledComponent } from '@app/+admin/plugins/plugin-list-installed/plugin-list-installed.component'
26import { PluginSearchComponent } from '@app/+admin/plugins/plugin-search/plugin-search.component'
27import { PluginShowInstalledComponent } from '@app/+admin/plugins/plugin-show-installed/plugin-show-installed.component'
28import { SelectButtonModule } from 'primeng/primeng'
29import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service'
24 30
25@NgModule({ 31@NgModule({
26 imports: [ 32 imports: [
27 AdminRoutingModule, 33 AdminRoutingModule,
28 TableModule, 34 TableModule,
35 SelectButtonModule,
29 SharedModule 36 SharedModule
30 ], 37 ],
31 38
@@ -52,6 +59,11 @@ import { DebugComponent, DebugService } from '@app/+admin/system/debug'
52 InstanceServerBlocklistComponent, 59 InstanceServerBlocklistComponent,
53 InstanceAccountBlocklistComponent, 60 InstanceAccountBlocklistComponent,
54 61
62 PluginsComponent,
63 PluginListInstalledComponent,
64 PluginSearchComponent,
65 PluginShowInstalledComponent,
66
55 SystemComponent, 67 SystemComponent,
56 JobsComponent, 68 JobsComponent,
57 LogsComponent, 69 LogsComponent,
@@ -70,7 +82,8 @@ import { DebugComponent, DebugService } from '@app/+admin/system/debug'
70 JobService, 82 JobService,
71 LogsService, 83 LogsService,
72 DebugService, 84 DebugService,
73 ConfigService 85 ConfigService,
86 PluginApiService
74 ] 87 ]
75}) 88})
76export class AdminModule { } 89export class AdminModule { }
diff --git a/client/src/app/+admin/plugins/index.ts b/client/src/app/+admin/plugins/index.ts
new file mode 100644
index 000000000..b75a94556
--- /dev/null
+++ b/client/src/app/+admin/plugins/index.ts
@@ -0,0 +1 @@
export * from './plugins.component'
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
new file mode 100644
index 000000000..6bb8bcd75
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.html
@@ -0,0 +1,13 @@
1<div class="toggle-plugin-type">
2 <p-selectButton [options]="pluginTypeOptions" [(ngModel)]="pluginType" (ngModelChange)="reloadPlugins()"></p-selectButton>
3</div>
4
5<div class="no-results" i18n *ngIf="pagination.totalItems === 0">
6 {{ getNoResultMessage() }}
7</div>
8
9<div class="plugins" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true">
10 <div class="section plugin" *ngFor="let plugin of plugins">
11 {{ plugin.name }}
12 </div>
13</div>
diff --git a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.scss b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.scss
new file mode 100644
index 000000000..9e98fcd34
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.scss
@@ -0,0 +1,8 @@
1@import '_variables';
2@import '_mixins';
3
4.toggle-plugin-type {
5 display: flex;
6 justify-content: center;
7 margin-bottom: 30px;
8}
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
new file mode 100644
index 000000000..9745bc36b
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts
@@ -0,0 +1,72 @@
1import { Component, OnInit } from '@angular/core'
2import { PluginType } from '@shared/models/plugins/plugin.type'
3import { I18n } from '@ngx-translate/i18n-polyfill'
4import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service'
5import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model'
6import { Notifier } from '@app/core'
7import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model'
8
9@Component({
10 selector: 'my-plugin-list-installed',
11 templateUrl: './plugin-list-installed.component.html',
12 styleUrls: [ './plugin-list-installed.component.scss' ]
13})
14export class PluginListInstalledComponent implements OnInit {
15 pluginTypeOptions: { label: string, value: PluginType }[] = []
16 pluginType: PluginType = PluginType.PLUGIN
17
18 pagination: ComponentPagination = {
19 currentPage: 1,
20 itemsPerPage: 10
21 }
22 sort = 'name'
23
24 plugins: PeerTubePlugin[] = []
25
26 constructor (
27 private i18n: I18n,
28 private pluginService: PluginApiService,
29 private notifier: Notifier
30 ) {
31 this.pluginTypeOptions = this.pluginService.getPluginTypeOptions()
32 }
33
34 ngOnInit () {
35 this.reloadPlugins()
36 }
37
38 reloadPlugins () {
39 this.pagination.currentPage = 1
40 this.plugins = []
41
42 this.loadMorePlugins()
43 }
44
45 loadMorePlugins () {
46 this.pluginService.getPlugins(this.pluginType, this.pagination, this.sort)
47 .subscribe(
48 res => {
49 this.plugins = this.plugins.concat(res.data)
50 this.pagination.totalItems = res.total
51 },
52
53 err => this.notifier.error(err.message)
54 )
55 }
56
57 onNearOfBottom () {
58 if (!hasMoreItems(this.pagination)) return
59
60 this.pagination.currentPage += 1
61
62 this.loadMorePlugins()
63 }
64
65 getNoResultMessage () {
66 if (this.pluginType === PluginType.PLUGIN) {
67 return this.i18n('You don\'t have plugins installed yet.')
68 }
69
70 return this.i18n('You don\'t have themes installed yet.')
71 }
72}
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
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.scss b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.scss
new file mode 100644
index 000000000..5e6774739
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.scss
@@ -0,0 +1,2 @@
1@import '_variables';
2@import '_mixins';
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
new file mode 100644
index 000000000..db1f91f3d
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts
@@ -0,0 +1,30 @@
1import { Component, OnInit, ViewChild } from '@angular/core'
2import { Notifier } from '@app/core'
3import { SortMeta } from 'primeng/components/common/sortmeta'
4import { ConfirmService, ServerService } from '../../../core'
5import { RestPagination, RestTable, UserService } from '../../../shared'
6import { I18n } from '@ngx-translate/i18n-polyfill'
7import { User } from '../../../../../../shared'
8import { UserBanModalComponent } from '@app/shared/moderation'
9import { DropdownAction } from '@app/shared/buttons/action-dropdown.component'
10import { PluginType } from '@shared/models/plugins/plugin.type'
11import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service'
12
13@Component({
14 selector: 'my-plugin-search',
15 templateUrl: './plugin-search.component.html',
16 styleUrls: [ './plugin-search.component.scss' ]
17})
18export class PluginSearchComponent implements OnInit {
19 pluginTypeOptions: { label: string, value: PluginType }[] = []
20
21 constructor (
22 private i18n: I18n,
23 private pluginService: PluginApiService
24 ) {
25 this.pluginTypeOptions = this.pluginService.getPluginTypeOptions()
26 }
27
28 ngOnInit () {
29 }
30}
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
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.html
diff --git a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.scss b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.scss
new file mode 100644
index 000000000..5e6774739
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.scss
@@ -0,0 +1,2 @@
1@import '_variables';
2@import '_mixins';
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
new file mode 100644
index 000000000..f65599532
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
@@ -0,0 +1,14 @@
1import { Component, OnInit } from '@angular/core'
2
3@Component({
4 selector: 'my-plugin-show-installed',
5 templateUrl: './plugin-show-installed.component.html',
6 styleUrls: [ './plugin-show-installed.component.scss' ]
7})
8export class PluginShowInstalledComponent implements OnInit {
9
10 ngOnInit () {
11
12 }
13
14}
diff --git a/client/src/app/+admin/plugins/plugins.component.html b/client/src/app/+admin/plugins/plugins.component.html
new file mode 100644
index 000000000..3dc4939da
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugins.component.html
@@ -0,0 +1,11 @@
1<div class="admin-sub-header">
2 <div i18n class="form-sub-title">Plugins/Themes</div>
3
4 <div class="admin-sub-nav">
5 <a i18n routerLink="list-installed" routerLinkActive="active">Installed</a>
6
7 <a i18n routerLink="search" routerLinkActive="active">Search</a>
8 </div>
9</div>
10
11<router-outlet></router-outlet>
diff --git a/client/src/app/+admin/plugins/plugins.component.scss b/client/src/app/+admin/plugins/plugins.component.scss
new file mode 100644
index 000000000..9f61bcf7a
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugins.component.scss
@@ -0,0 +1,7 @@
1@import '_variables';
2@import '_mixins';
3
4.form-sub-title {
5 flex-grow: 0;
6 margin-right: 30px;
7}
diff --git a/client/src/app/+admin/plugins/plugins.component.ts b/client/src/app/+admin/plugins/plugins.component.ts
new file mode 100644
index 000000000..6ec6fa4a1
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugins.component.ts
@@ -0,0 +1,8 @@
1import { Component } from '@angular/core'
2
3@Component({
4 templateUrl: './plugins.component.html',
5 styleUrls: [ './plugins.component.scss' ]
6})
7export class PluginsComponent {
8}
diff --git a/client/src/app/+admin/plugins/plugins.routes.ts b/client/src/app/+admin/plugins/plugins.routes.ts
new file mode 100644
index 000000000..58b5534fb
--- /dev/null
+++ b/client/src/app/+admin/plugins/plugins.routes.ts
@@ -0,0 +1,53 @@
1import { Routes } from '@angular/router'
2
3import { UserRightGuard } from '../../core'
4import { UserRight } from '../../../../../shared'
5import { PluginListInstalledComponent } from '@app/+admin/plugins/plugin-list-installed/plugin-list-installed.component'
6import { PluginSearchComponent } from '@app/+admin/plugins/plugin-search/plugin-search.component'
7import { PluginShowInstalledComponent } from '@app/+admin/plugins/plugin-show-installed/plugin-show-installed.component'
8import { PluginsComponent } from '@app/+admin/plugins/plugins.component'
9
10export const PluginsRoutes: Routes = [
11 {
12 path: 'plugins',
13 component: PluginsComponent,
14 canActivate: [ UserRightGuard ],
15 data: {
16 userRight: UserRight.MANAGE_PLUGINS
17 },
18 children: [
19 {
20 path: '',
21 redirectTo: 'list-installed',
22 pathMatch: 'full'
23 },
24 {
25 path: 'list-installed',
26 component: PluginListInstalledComponent,
27 data: {
28 meta: {
29 title: 'List installed plugins'
30 }
31 }
32 },
33 {
34 path: 'search',
35 component: PluginSearchComponent,
36 data: {
37 meta: {
38 title: 'Search plugins'
39 }
40 }
41 },
42 {
43 path: 'show/:name',
44 component: PluginShowInstalledComponent,
45 data: {
46 meta: {
47 title: 'Show plugin'
48 }
49 }
50 }
51 ]
52 }
53]
diff --git a/client/src/app/+admin/plugins/shared/plugin-api.service.ts b/client/src/app/+admin/plugins/shared/plugin-api.service.ts
new file mode 100644
index 000000000..bfc2b918f
--- /dev/null
+++ b/client/src/app/+admin/plugins/shared/plugin-api.service.ts
@@ -0,0 +1,50 @@
1import { catchError } from 'rxjs/operators'
2import { HttpClient, HttpParams } from '@angular/common/http'
3import { Injectable } from '@angular/core'
4import { environment } from '../../../../environments/environment'
5import { RestExtractor, RestService } from '../../../shared'
6import { I18n } from '@ngx-translate/i18n-polyfill'
7import { PluginType } from '@shared/models/plugins/plugin.type'
8import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
9import { ResultList } from '@shared/models'
10import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model'
11
12@Injectable()
13export class PluginApiService {
14 private static BASE_APPLICATION_URL = environment.apiUrl + '/api/v1/plugins'
15
16 constructor (
17 private authHttp: HttpClient,
18 private restExtractor: RestExtractor,
19 private restService: RestService,
20 private i18n: I18n
21 ) { }
22
23 getPluginTypeOptions () {
24 return [
25 {
26 label: this.i18n('Plugin'),
27 value: PluginType.PLUGIN
28 },
29 {
30 label: this.i18n('Theme'),
31 value: PluginType.THEME
32 }
33 ]
34 }
35
36 getPlugins (
37 type: PluginType,
38 componentPagination: ComponentPagination,
39 sort: string
40 ) {
41 const pagination = this.restService.componentPaginationToRestPagination(componentPagination)
42
43 let params = new HttpParams()
44 params = this.restService.addRestGetParams(params, pagination, sort)
45 params = params.append('type', type.toString())
46
47 return this.authHttp.get<ResultList<PeerTubePlugin>>(PluginApiService.BASE_APPLICATION_URL, { params })
48 .pipe(catchError(res => this.restExtractor.handleError(res)))
49 }
50}
diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts
index 4abe9ee8d..86bde2d02 100644
--- a/client/src/app/core/plugins/plugin.service.ts
+++ b/client/src/app/core/plugins/plugin.service.ts
@@ -5,7 +5,7 @@ import { ServerService } from '@app/core/server/server.service'
5import { ClientScript } from '@shared/models/plugins/plugin-package-json.model' 5import { ClientScript } from '@shared/models/plugins/plugin-package-json.model'
6import { PluginScope } from '@shared/models/plugins/plugin-scope.type' 6import { PluginScope } from '@shared/models/plugins/plugin-scope.type'
7import { environment } from '../../../environments/environment' 7import { environment } from '../../../environments/environment'
8import { RegisterHookOptions } from '@shared/models/plugins/register.model' 8import { RegisterHookOptions } from '@shared/models/plugins/register-hook.model'
9import { ReplaySubject } from 'rxjs' 9import { ReplaySubject } from 'rxjs'
10import { first, shareReplay } from 'rxjs/operators' 10import { first, shareReplay } from 'rxjs/operators'
11 11
diff --git a/client/src/app/core/theme/theme.service.ts b/client/src/app/core/theme/theme.service.ts
index ad59c203b..76199d1cc 100644
--- a/client/src/app/core/theme/theme.service.ts
+++ b/client/src/app/core/theme/theme.service.ts
@@ -83,6 +83,7 @@ export class ThemeService {
83 console.log('Enabling %s theme.', currentTheme) 83 console.log('Enabling %s theme.', currentTheme)
84 84
85 this.loadTheme(currentTheme) 85 this.loadTheme(currentTheme)
86
86 const theme = this.getTheme(currentTheme) 87 const theme = this.getTheme(currentTheme)
87 if (theme) { 88 if (theme) {
88 console.log('Adding scripts of theme %s.', currentTheme) 89 console.log('Adding scripts of theme %s.', currentTheme)
@@ -95,6 +96,10 @@ export class ThemeService {
95 } 96 }
96 97
97 private listenUserTheme () { 98 private listenUserTheme () {
99 if (!this.auth.isLoggedIn()) {
100 this.updateCurrentTheme()
101 }
102
98 this.auth.userInformationLoaded 103 this.auth.userInformationLoaded
99 .subscribe(() => this.updateCurrentTheme()) 104 .subscribe(() => this.updateCurrentTheme())
100 } 105 }