Refactor admin plugins
This commit is contained in:
parent
9744bb2ae8
commit
2accfdd8ec
|
@ -302,11 +302,13 @@
|
|||
"defaultProject": "PeerTube",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"prefix": "app",
|
||||
"style": "scss"
|
||||
"prefix": "my",
|
||||
"style": "scss",
|
||||
"skipTests": true,
|
||||
"flat": true
|
||||
},
|
||||
"@schematics/angular:directive": {
|
||||
"prefix": "app"
|
||||
"prefix": "my"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { ChartModule } from 'primeng/chart'
|
||||
import { SelectButtonModule } from 'primeng/selectbutton'
|
||||
import { TableModule } from 'primeng/table'
|
||||
import { NgModule } from '@angular/core'
|
||||
import { SharedAbuseListModule } from '@app/shared/shared-abuse-list'
|
||||
|
@ -45,7 +44,7 @@ import {
|
|||
PluginApiService,
|
||||
PluginCardComponent,
|
||||
PluginListInstalledComponent,
|
||||
PluginsComponent,
|
||||
PluginNavigationComponent,
|
||||
PluginSearchComponent,
|
||||
PluginShowInstalledComponent
|
||||
} from './plugins'
|
||||
|
@ -70,7 +69,6 @@ import { JobsComponent } from './system/jobs/jobs.component'
|
|||
SharedTablesModule,
|
||||
|
||||
TableModule,
|
||||
SelectButtonModule,
|
||||
ChartModule
|
||||
],
|
||||
|
||||
|
@ -98,11 +96,11 @@ import { JobsComponent } from './system/jobs/jobs.component'
|
|||
InstanceServerBlocklistComponent,
|
||||
InstanceAccountBlocklistComponent,
|
||||
|
||||
PluginsComponent,
|
||||
PluginListInstalledComponent,
|
||||
PluginSearchComponent,
|
||||
PluginShowInstalledComponent,
|
||||
PluginCardComponent,
|
||||
PluginNavigationComponent,
|
||||
|
||||
JobsComponent,
|
||||
LogsComponent,
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
export * from './plugins.component'
|
||||
export * from './shared'
|
||||
export * from './plugin-list-installed'
|
||||
export * from './plugin-search'
|
||||
export * from './plugin-show-installed'
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<div class="toggle-plugin-type">
|
||||
<p-selectButton [options]="pluginTypeOptions" [(ngModel)]="pluginType" (ngModelChange)="reloadPlugins()"></p-selectButton>
|
||||
</div>
|
||||
<my-plugin-navigation [pluginType]="pluginType"></my-plugin-navigation>
|
||||
|
||||
<div class="no-results" *ngIf="pagination.totalItems === 0">
|
||||
{{ getNoResultMessage() }}
|
||||
|
|
|
@ -10,14 +10,10 @@ import { PeerTubePlugin, PluginType } from '@shared/models'
|
|||
@Component({
|
||||
selector: 'my-plugin-list-installed',
|
||||
templateUrl: './plugin-list-installed.component.html',
|
||||
styleUrls: [
|
||||
'../shared/toggle-plugin-type.scss',
|
||||
'./plugin-list-installed.component.scss'
|
||||
]
|
||||
styleUrls: [ './plugin-list-installed.component.scss' ]
|
||||
})
|
||||
export class PluginListInstalledComponent implements OnInit {
|
||||
pluginTypeOptions: { label: string, value: PluginType }[] = []
|
||||
pluginType: PluginType = PluginType.PLUGIN
|
||||
pluginType: PluginType
|
||||
|
||||
pagination: ComponentPagination = {
|
||||
currentPage: 1,
|
||||
|
@ -39,22 +35,28 @@ export class PluginListInstalledComponent implements OnInit {
|
|||
private router: Router,
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
this.pluginTypeOptions = this.pluginApiService.getPluginTypeOptions()
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
const query = this.route.snapshot.queryParams
|
||||
if (query['pluginType']) this.pluginType = parseInt(query['pluginType'], 10)
|
||||
if (!this.route.snapshot.queryParams['pluginType']) {
|
||||
const queryParams = { pluginType: PluginType.PLUGIN }
|
||||
|
||||
this.reloadPlugins()
|
||||
this.router.navigate([], { queryParams })
|
||||
}
|
||||
|
||||
this.route.queryParams.subscribe(query => {
|
||||
if (!query['pluginType']) return
|
||||
|
||||
this.pluginType = parseInt(query['pluginType'], 10)
|
||||
|
||||
this.reloadPlugins()
|
||||
})
|
||||
}
|
||||
|
||||
reloadPlugins () {
|
||||
this.pagination.currentPage = 1
|
||||
this.plugins = []
|
||||
|
||||
this.router.navigate([], { queryParams: { pluginType: this.pluginType } })
|
||||
|
||||
this.loadMorePlugins()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,27 @@
|
|||
<div class="toggle-plugin-type">
|
||||
<p-selectButton [options]="pluginTypeOptions" [(ngModel)]="pluginType" (ngModelChange)="reloadPlugins()"></p-selectButton>
|
||||
</div>
|
||||
|
||||
<div class="search-bar">
|
||||
<input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." myAutofocus />
|
||||
</div>
|
||||
<my-plugin-navigation [pluginType]="pluginType"></my-plugin-navigation>
|
||||
|
||||
<div class="alert alert-info" i18n *ngIf="pluginInstalled">
|
||||
To load your new installed plugins or themes, refresh the page.
|
||||
</div>
|
||||
|
||||
<div class="result-title" *ngIf="!isSearching">
|
||||
<div class="result-and-search">
|
||||
<ng-container *ngIf="!search">
|
||||
<my-global-icon iconName="trending" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Popular</ng-container>
|
||||
<ng-container *ngIf="!isThemeSearch()" i18n>Popular plugins</ng-container>
|
||||
<ng-container *ngIf="isThemeSearch()" i18n>Popular themes</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!!search">
|
||||
<ng-container *ngIf="search && !isSearching">
|
||||
<my-global-icon iconName="search"></my-global-icon>
|
||||
|
||||
<ng-container i18n>
|
||||
{{ pagination.totalItems }} {pagination.totalItems, plural, =1 {result} other {results}} for "{{ search }}"
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<div class="search-bar">
|
||||
<input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." myAutofocus />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="no-results" i18n *ngIf="pagination.totalItems === 0">
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
@use '_variables' as *;
|
||||
@use '_mixins' as *;
|
||||
|
||||
.search-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 30px 0;
|
||||
|
||||
input {
|
||||
@include peertube-input-text(60%);
|
||||
height: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
.result-title {
|
||||
.result-and-search {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15px;
|
||||
margin: 30px 0 15px;
|
||||
display: flex;
|
||||
|
||||
my-global-icon {
|
||||
@include margin-right(5px);
|
||||
}
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
margin-left: auto;
|
||||
|
||||
input {
|
||||
@include peertube-input-text(500px);
|
||||
|
||||
height: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
.badge {
|
||||
@include margin-left(15px);
|
||||
|
||||
|
|
|
@ -9,14 +9,10 @@ import { PeerTubePluginIndex, PluginType } from '@shared/models'
|
|||
@Component({
|
||||
selector: 'my-plugin-search',
|
||||
templateUrl: './plugin-search.component.html',
|
||||
styleUrls: [
|
||||
'../shared/toggle-plugin-type.scss',
|
||||
'./plugin-search.component.scss'
|
||||
]
|
||||
styleUrls: [ './plugin-search.component.scss' ]
|
||||
})
|
||||
export class PluginSearchComponent implements OnInit {
|
||||
pluginTypeOptions: { label: string, value: PluginType }[] = []
|
||||
pluginType: PluginType = PluginType.PLUGIN
|
||||
pluginType: PluginType
|
||||
|
||||
pagination: ComponentPagination = {
|
||||
currentPage: 1,
|
||||
|
@ -44,24 +40,30 @@ export class PluginSearchComponent implements OnInit {
|
|||
private router: Router,
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
this.pluginTypeOptions = this.pluginApiService.getPluginTypeOptions()
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
const query = this.route.snapshot.queryParams
|
||||
if (query['pluginType']) this.pluginType = parseInt(query['pluginType'], 10)
|
||||
if (!this.route.snapshot.queryParams['pluginType']) {
|
||||
const queryParams = { pluginType: PluginType.PLUGIN }
|
||||
|
||||
this.router.navigate([], { queryParams })
|
||||
}
|
||||
|
||||
this.route.queryParams.subscribe(query => {
|
||||
if (!query['pluginType']) return
|
||||
|
||||
this.pluginType = parseInt(query['pluginType'], 10)
|
||||
this.search = query['search'] || ''
|
||||
|
||||
this.reloadPlugins()
|
||||
})
|
||||
|
||||
this.searchSubject.asObservable()
|
||||
.pipe(
|
||||
debounceTime(400),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
.subscribe(search => {
|
||||
this.search = search
|
||||
this.reloadPlugins()
|
||||
})
|
||||
|
||||
this.reloadPlugins()
|
||||
.subscribe(search => this.router.navigate([], { queryParams: { search }, queryParamsHandling: 'merge' }))
|
||||
}
|
||||
|
||||
onSearchChange (event: Event) {
|
||||
|
@ -74,8 +76,6 @@ export class PluginSearchComponent implements OnInit {
|
|||
this.pagination.currentPage = 1
|
||||
this.plugins = []
|
||||
|
||||
this.router.navigate([], { queryParams: { pluginType: this.pluginType } })
|
||||
|
||||
this.loadMorePlugins()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
<div class="admin-sub-header">
|
||||
<div class="admin-sub-nav">
|
||||
<a i18n routerLink="list-installed" routerLinkActive="active">Installed</a>
|
||||
|
||||
<a i18n routerLink="search" routerLinkActive="active">Search</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<router-outlet></router-outlet>
|
|
@ -1,7 +0,0 @@
|
|||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
templateUrl: './plugins.component.html'
|
||||
})
|
||||
export class PluginsComponent {
|
||||
}
|
|
@ -2,14 +2,12 @@ import { Routes } from '@angular/router'
|
|||
import { PluginListInstalledComponent } from '@app/+admin/plugins/plugin-list-installed/plugin-list-installed.component'
|
||||
import { PluginSearchComponent } from '@app/+admin/plugins/plugin-search/plugin-search.component'
|
||||
import { PluginShowInstalledComponent } from '@app/+admin/plugins/plugin-show-installed/plugin-show-installed.component'
|
||||
import { PluginsComponent } from '@app/+admin/plugins/plugins.component'
|
||||
import { UserRightGuard } from '@app/core'
|
||||
import { UserRight } from '@shared/models'
|
||||
|
||||
export const PluginsRoutes: Routes = [
|
||||
{
|
||||
path: 'plugins',
|
||||
component: PluginsComponent,
|
||||
canActivate: [ UserRightGuard ],
|
||||
data: {
|
||||
userRight: UserRight.MANAGE_PLUGINS
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
export * from './plugin-api.service'
|
||||
export * from './plugin-card.component'
|
||||
export * from './plugin-navigation.component'
|
||||
|
|
|
@ -25,19 +25,6 @@ export class PluginApiService {
|
|||
private pluginService: PluginService
|
||||
) { }
|
||||
|
||||
getPluginTypeOptions () {
|
||||
return [
|
||||
{
|
||||
label: $localize`Plugins`,
|
||||
value: PluginType.PLUGIN
|
||||
},
|
||||
{
|
||||
label: $localize`Themes`,
|
||||
value: PluginType.THEME
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
getPluginTypeLabel (type: PluginType) {
|
||||
if (type === PluginType.PLUGIN) {
|
||||
return $localize`plugin`
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<div class="root">
|
||||
<div class="btn-group" role="group" i18n-aria-label aria-label="Navigate between installed plugins and themes or find new ones">
|
||||
<a i18n routerLink="/admin/plugins/list-installed" [queryParams]="{ pluginType: pluginType }" routerLinkActive="active">Installed</a>
|
||||
<a i18n routerLink="/admin/plugins/search" [queryParams]="{ pluginType: pluginType }" routerLinkActive="active">Search</a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" role="group" i18n-aria-label aria-label="Navigate between plugins and themes">
|
||||
<a [ngClass]="{ active: pluginType === 1 }" routerLink="." [queryParams]="{ pluginType: 1 }" queryParamsHandling="merge" class="">Plugins</a>
|
||||
<a [ngClass]="{ active: pluginType === 2 }" routerLink="." [queryParams]="{ pluginType: 2 }" queryParamsHandling="merge" class="">Themes</a>
|
||||
</div>
|
||||
</div>
|
|
@ -1,8 +1,11 @@
|
|||
@use '_variables' as *;
|
||||
@use '_mixins' as *;
|
||||
|
||||
.toggle-plugin-type {
|
||||
.root {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.btn-group:not(:last-child) {
|
||||
@include margin-right(15px);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import { Component, Input } from '@angular/core'
|
||||
import { PluginType } from '@shared/models/plugins'
|
||||
|
||||
@Component({
|
||||
selector: 'my-plugin-navigation',
|
||||
templateUrl: './plugin-navigation.component.html',
|
||||
styleUrls: [ './plugin-navigation.component.scss' ]
|
||||
})
|
||||
export class PluginNavigationComponent {
|
||||
@Input() pluginType: PluginType
|
||||
}
|
|
@ -261,28 +261,6 @@ my-input-toggle-hidden ::ng-deep input {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.admin-sub-nav a {
|
||||
@include disable-default-a-behaviour;
|
||||
|
||||
font-size: 16px;
|
||||
color: pvar(--mainForegroundColor);
|
||||
padding: 5px 15px;
|
||||
border-radius: 0.25rem;
|
||||
font-weight: $font-semibold;
|
||||
opacity: 0.6;
|
||||
|
||||
&.active {
|
||||
background-color: pvar(--submenuBackgroundColor);
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In tables, don't have a hover different background
|
||||
|
@ -402,19 +380,6 @@ ngx-loading-bar {
|
|||
|
||||
.admin-sub-header {
|
||||
flex-direction: column;
|
||||
|
||||
.admin-sub-nav {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
height: 50px;
|
||||
padding: 10px 0;
|
||||
width: 100%;
|
||||
|
||||
a {
|
||||
@include margin-left(5px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my-markdown-textarea {
|
||||
|
|
|
@ -334,6 +334,34 @@ ngb-tooltip-window {
|
|||
}
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
font-weight: $font-semibold;
|
||||
|
||||
.active {
|
||||
@include orange-button;
|
||||
}
|
||||
|
||||
:not(.active) {
|
||||
@include grey-button;
|
||||
}
|
||||
|
||||
> * {
|
||||
@include peertube-button-link;
|
||||
|
||||
box-shadow: none !important;
|
||||
|
||||
&:not(:first-child) {
|
||||
border-top-left-radius: 0 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
border-top-right-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// input box-shadow on focus
|
||||
.form-control {
|
||||
font-size: 15px;
|
||||
|
|
Loading…
Reference in New Issue