diff options
author | Chocobozzz <me@florianbigard.com> | 2019-07-10 18:30:27 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-07-24 10:58:16 +0200 |
commit | d00dc28dd73ad9dd419d5a5ac6ac747cefbc6e8b (patch) | |
tree | c94c2b22de6707eaafcc4348f69934f265c52f52 /client/src/app/+admin/plugins | |
parent | ad91e7006e41f8ee5b8dcefee30f99e8ca44133a (diff) | |
download | PeerTube-d00dc28dd73ad9dd419d5a5ac6ac747cefbc6e8b.tar.gz PeerTube-d00dc28dd73ad9dd419d5a5ac6ac747cefbc6e8b.tar.zst PeerTube-d00dc28dd73ad9dd419d5a5ac6ac747cefbc6e8b.zip |
WIP plugins: list installed plugins in client
Diffstat (limited to 'client/src/app/+admin/plugins')
15 files changed, 271 insertions, 0 deletions
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 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | ||
2 | import { PluginType } from '@shared/models/plugins/plugin.type' | ||
3 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
4 | import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' | ||
5 | import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model' | ||
6 | import { Notifier } from '@app/core' | ||
7 | import { 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 | }) | ||
14 | export 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 @@ | |||
1 | import { Component, OnInit, ViewChild } from '@angular/core' | ||
2 | import { Notifier } from '@app/core' | ||
3 | import { SortMeta } from 'primeng/components/common/sortmeta' | ||
4 | import { ConfirmService, ServerService } from '../../../core' | ||
5 | import { RestPagination, RestTable, UserService } from '../../../shared' | ||
6 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
7 | import { User } from '../../../../../../shared' | ||
8 | import { UserBanModalComponent } from '@app/shared/moderation' | ||
9 | import { DropdownAction } from '@app/shared/buttons/action-dropdown.component' | ||
10 | import { PluginType } from '@shared/models/plugins/plugin.type' | ||
11 | import { 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 | }) | ||
18 | export 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 @@ | |||
1 | import { 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 | }) | ||
8 | export 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 @@ | |||
1 | import { Component } from '@angular/core' | ||
2 | |||
3 | @Component({ | ||
4 | templateUrl: './plugins.component.html', | ||
5 | styleUrls: [ './plugins.component.scss' ] | ||
6 | }) | ||
7 | export 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 @@ | |||
1 | import { Routes } from '@angular/router' | ||
2 | |||
3 | import { UserRightGuard } from '../../core' | ||
4 | import { UserRight } from '../../../../../shared' | ||
5 | import { PluginListInstalledComponent } from '@app/+admin/plugins/plugin-list-installed/plugin-list-installed.component' | ||
6 | import { PluginSearchComponent } from '@app/+admin/plugins/plugin-search/plugin-search.component' | ||
7 | import { PluginShowInstalledComponent } from '@app/+admin/plugins/plugin-show-installed/plugin-show-installed.component' | ||
8 | import { PluginsComponent } from '@app/+admin/plugins/plugins.component' | ||
9 | |||
10 | export 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 @@ | |||
1 | import { catchError } from 'rxjs/operators' | ||
2 | import { HttpClient, HttpParams } from '@angular/common/http' | ||
3 | import { Injectable } from '@angular/core' | ||
4 | import { environment } from '../../../../environments/environment' | ||
5 | import { RestExtractor, RestService } from '../../../shared' | ||
6 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
7 | import { PluginType } from '@shared/models/plugins/plugin.type' | ||
8 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' | ||
9 | import { ResultList } from '@shared/models' | ||
10 | import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model' | ||
11 | |||
12 | @Injectable() | ||
13 | export 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 | } | ||