-<div class="row">
- <div class="content-padding">
- <h3>Jobs list</h3>
-
- <p-dataTable
- [value]="jobs" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
- sortField="createdAt" (onLazyLoad)="loadLazy($event)"
- >
- <p-column field="id" header="ID"></p-column>
- <p-column field="category" header="Category"></p-column>
- <p-column field="handlerName" header="Handler name"></p-column>
- <p-column field="handlerInputData" header="Input data"></p-column>
- <p-column field="state" header="State"></p-column>
- <p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
- <p-column field="updatedAt" header="Updated date"></p-column>
- </p-dataTable>
- </div>
+<div class="admin-sub-header">
+ <div class="admin-sub-title">Jobs list</div>
</div>
+
+<p-dataTable
+ [value]="jobs" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
+ sortField="createdAt" (onLazyLoad)="loadLazy($event)" [scrollable]="true" [virtualScroll]="true" [scrollHeight]="scrollHeight"
+>
+ <p-column field="id" header="ID" [style]="{ width: '40px' }"></p-column>
+ <p-column field="category" header="Category" [style]="{ width: '100px' }"></p-column>
+ <p-column field="handlerName" header="Handler name" [style]="{ width: '150px' }"></p-column>
+ <p-column header="Input data">
+ <ng-template pTemplate="body" let-job="rowData">
+ <pre>{{ job.handlerInputData }}</pre>
+ </ng-template>
+ </p-column>
+ <p-column field="state" header="State" [style]="{ width: '100px' }"></p-column>
+ <p-column field="createdAt" header="Created date" [sortable]="true" [style]="{ width: '250px' }"></p-column>
+ <p-column field="updatedAt" header="Updated date" [style]="{ width: '250px' }"></p-column>
+</p-dataTable>
--- /dev/null
+pre {
+ font-size: 13px;
+}
-import { Component } from '@angular/core'
+import { Component, OnInit } from '@angular/core'
import { NotificationsService } from 'angular2-notifications'
import { SortMeta } from 'primeng/primeng'
import { Job } from '../../../../../../shared/index'
import { RestPagination, RestTable } from '../../../shared'
+import { viewportHeight } from '../../../shared/misc/utils'
import { JobService } from '../shared'
import { RestExtractor } from '../../../shared/rest/rest-extractor.service'
@Component({
selector: 'my-jobs-list',
templateUrl: './jobs-list.component.html',
- styleUrls: [ ]
+ styleUrls: [ './jobs-list.component.scss' ]
})
-export class JobsListComponent extends RestTable {
+export class JobsListComponent extends RestTable implements OnInit {
jobs: Job[] = []
totalRecords = 0
- rowsPerPage = 10
+ rowsPerPage = 20
sort: SortMeta = { field: 'createdAt', order: 1 }
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
+ scrollHeight = ''
constructor (
private notificationsService: NotificationsService,
super()
}
+ ngOnInit () {
+ // 270 -> headers + footer...
+ this.scrollHeight = (viewportHeight() - 380) + 'px'
+ }
+
protected loadData () {
this.jobsService
.getJobs(this.pagination, this.sort)
- .map(res => this.restExtractor.applyToResultListData(res, this.formatJob.bind(this)))
.subscribe(
resultList => {
this.jobs = resultList.data
err => this.notificationsService.error('Error', err.message)
)
}
-
- private formatJob (job: Job) {
- const handlerInputData = JSON.stringify(job.handlerInputData)
-
- return Object.assign(job, {
- handlerInputData
- })
- }
}
return this.authHttp.get<ResultList<Job>>(JobService.BASE_JOB_URL, { params })
.map(res => this.restExtractor.convertResultListDateToHuman(res))
+ .map(res => this.restExtractor.applyToResultListData(res, this.prettyPrintData))
.catch(err => this.restExtractor.handleError(err))
}
+
+ private prettyPrintData (obj: Job) {
+ const handlerInputData = JSON.stringify(obj.handlerInputData, null, 2)
+
+ return Object.assign(obj, { handlerInputData })
+ }
}
-<div class="sub-header">
+<div class="admin-sub-header">
<div class="admin-sub-title">Users list</div>
<a class="add-button" routerLink="/admin/users/add">
<p-column field="videoQuota" header="Video quota"></p-column>
<p-column field="roleLabel" header="Role"></p-column>
<p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
- <p-column header="Edit" styleClass="action-cell">
- <ng-template pTemplate="body" let-user="rowData">
- <a [routerLink]="getRouterUserEditLink(user)" title="Edit this user">
- <span class="glyphicon glyphicon-pencil glyphicon-black"></span>
- </a>
- </ng-template>
- </p-column>
- <p-column header="Delete" styleClass="action-cell">
- <ng-template pTemplate="body" let-user="rowData">
- <span (click)="removeUser(user)" class="glyphicon glyphicon-remove glyphicon-black" title="Remove this user"></span>
+ <p-column styleClass="action-cell">
+ <ng-template pTemplate="body" let-user="rowData">
+ <my-edit-button [routerLink]="getRouterUserEditLink(user)"></my-edit-button>
+ <my-delete-button (click)="removeUser(user)"></my-delete-button>
</ng-template>
</p-column>
</p-dataTable>
-.sub-header {
- display: flex;
- align-items: center;
- margin-bottom: 30px;
-
- .admin-sub-title {
- flex-grow: 1;
- }
-
.add-button {
@include peertube-button-link;
@include orange-button;
background-image: url('../../../../assets/images/admin/add.svg');
}
}
-}
Cancel
</span>
- <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
+ <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
<span class="icon icon-delete-white"></span>
Delete
</span>
</div>
<ng-template [ngIf]="isInSelectionMode() === false">
- <span class="action-button action-button-delete" (click)="deleteVideo(video)">
- <span class="icon icon-delete-grey"></span>
- Delete
- </span>
+ <my-delete-button (click)="deleteVideo(video)"></my-delete-button>
- <a class="action-button" [routerLink]="[ '/videos', 'edit', video.uuid ]">
- <span class="icon icon-edit"></span>
- Edit
- </a>
+ <my-edit-button [routerLink]="[ '/videos', 'edit', video.uuid ]"></my-edit-button>
</ng-template>
</div>
</div>
}
}
-.action-button {
- @include peertube-button-link;
-
- font-size: 15px;
- font-weight: $font-semibold;
- color: #585858;
- background-color: #E5E5E5;
-
- &:hover {
- background-color: #EFEFEF;
- }
+/deep/ .action-button {
&.action-button-delete {
margin-right: 10px;
}
.icon {
- @include icon(21px);
-
- position: relative;
- top: -2px;
-
- &.icon-edit {
- background-image: url('../../../assets/images/global/edit.svg');
- }
-
- &.icon-delete-grey {
- background-image: url('../../../assets/images/account/delete-grey.svg');
- }
-
&.icon-delete-white {
- background-image: url('../../../assets/images/account/delete-white.svg');
+ background-image: url('../../../assets/images/global/delete-white.svg');
}
}
}
--- /dev/null
+.action-button {
+ @include peertube-button-link;
+
+ font-size: 15px;
+ font-weight: $font-semibold;
+ color: #585858;
+ background-color: #E5E5E5;
+
+ &:hover {
+ background-color: #EFEFEF;
+ }
+
+ .icon {
+ @include icon(21px);
+
+ position: relative;
+ top: -2px;
+
+ &.icon-edit {
+ background-image: url('../../../assets/images/global/edit.svg');
+ }
+
+ &.icon-delete-grey {
+ background-image: url('../../../assets/images/global/delete-grey.svg');
+ }
+ }
+}
--- /dev/null
+<span class="action-button action-button-delete" >
+ <span class="icon icon-delete-grey"></span>
+ Delete
+</span>
--- /dev/null
+import { Component } from '@angular/core'
+
+@Component({
+ selector: 'my-delete-button',
+ styleUrls: [ './button.component.scss' ],
+ templateUrl: './delete-button.component.html'
+})
+
+export class DeleteButtonComponent {
+}
--- /dev/null
+<a class="action-button" [routerLink]="routerLink">
+ <span class="icon icon-edit"></span>
+ Edit
+</a>
--- /dev/null
+import { Component, Input } from '@angular/core'
+
+@Component({
+ selector: 'my-edit-button',
+ styleUrls: [ './button.component.scss' ],
+ templateUrl: './edit-button.component.html'
+})
+
+export class EditButtonComponent {
+ @Input() routerLink = []
+}
return decodeURIComponent(results[2].replace(/\+/g, ' '))
}
+function viewportHeight () {
+ return Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
+}
+
export {
+ viewportHeight,
getParameterByName
}
import { DataTableModule } from 'primeng/components/datatable/datatable'
import { AUTH_INTERCEPTOR_PROVIDER } from './auth'
+import { DeleteButtonComponent } from './misc/delete-button.component'
+import { EditButtonComponent } from './misc/edit-button.component'
import { FromNowPipe } from './misc/from-now.pipe'
import { LoaderComponent } from './misc/loader.component'
import { NumberFormatterPipe } from './misc/number-formatter.pipe'
LoaderComponent,
VideoThumbnailComponent,
VideoMiniatureComponent,
+ DeleteButtonComponent,
+ EditButtonComponent,
NumberFormatterPipe,
FromNowPipe
],
LoaderComponent,
VideoThumbnailComponent,
VideoMiniatureComponent,
+ DeleteButtonComponent,
+ EditButtonComponent,
NumberFormatterPipe,
FromNowPipe
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <defs></defs>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="Artboard-4" transform="translate(-224.000000, -159.000000)">
- <g id="25" transform="translate(224.000000, 159.000000)">
- <path d="M5,7 L5,20.0081158 C5,21.1082031 5.89706013,22 7.00585866,22 L16.9941413,22 C18.1019465,22 19,21.1066027 19,20.0081158 L19,7" id="Path-296" stroke="#585858" stroke-width="2"></path>
- <rect id="Rectangle-424" fill="#585858" x="2" y="4" width="20" height="2" rx="1"></rect>
- <path d="M9,10.9970301 C9,10.4463856 9.44386482,10 10,10 C10.5522847,10 11,10.4530363 11,10.9970301 L11,17.0029699 C11,17.5536144 10.5561352,18 10,18 C9.44771525,18 9,17.5469637 9,17.0029699 L9,10.9970301 Z M13,10.9970301 C13,10.4463856 13.4438648,10 14,10 C14.5522847,10 15,10.4530363 15,10.9970301 L15,17.0029699 C15,17.5536144 14.5561352,18 14,18 C13.4477153,18 13,17.5469637 13,17.0029699 L13,10.9970301 Z" id="Combined-Shape" fill="#585858"></path>
- <path d="M9,5 L9,2.99895656 C9,2.44724809 9.45097518,2 9.99077797,2 L14.009222,2 C14.5564136,2 15,2.44266033 15,2.99895656 L15,5" id="Path-33" stroke="#585858" stroke-width="2" stroke-linejoin="round"></path>
- </g>
- </g>
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <defs></defs>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="Artboard-4" transform="translate(-224.000000, -159.000000)">
- <g id="25" transform="translate(224.000000, 159.000000)">
- <path d="M5,7 L5,20.0081158 C5,21.1082031 5.89706013,22 7.00585866,22 L16.9941413,22 C18.1019465,22 19,21.1066027 19,20.0081158 L19,7" id="Path-296" stroke="#ffffff" stroke-width="2"></path>
- <rect id="Rectangle-424" fill="#ffffff" x="2" y="4" width="20" height="2" rx="1"></rect>
- <path d="M9,10.9970301 C9,10.4463856 9.44386482,10 10,10 C10.5522847,10 11,10.4530363 11,10.9970301 L11,17.0029699 C11,17.5536144 10.5561352,18 10,18 C9.44771525,18 9,17.5469637 9,17.0029699 L9,10.9970301 Z M13,10.9970301 C13,10.4463856 13.4438648,10 14,10 C14.5522847,10 15,10.4530363 15,10.9970301 L15,17.0029699 C15,17.5536144 14.5561352,18 14,18 C13.4477153,18 13,17.5469637 13,17.0029699 L13,10.9970301 Z" id="Combined-Shape" fill="#ffffff"></path>
- <path d="M9,5 L9,2.99895656 C9,2.44724809 9.45097518,2 9.99077797,2 L14.009222,2 C14.5564136,2 15,2.44266033 15,2.99895656 L15,5" id="Path-33" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"></path>
- </g>
- </g>
- </g>
-</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Artboard-4" transform="translate(-224.000000, -159.000000)">
+ <g id="25" transform="translate(224.000000, 159.000000)">
+ <path d="M5,7 L5,20.0081158 C5,21.1082031 5.89706013,22 7.00585866,22 L16.9941413,22 C18.1019465,22 19,21.1066027 19,20.0081158 L19,7" id="Path-296" stroke="#585858" stroke-width="2"></path>
+ <rect id="Rectangle-424" fill="#585858" x="2" y="4" width="20" height="2" rx="1"></rect>
+ <path d="M9,10.9970301 C9,10.4463856 9.44386482,10 10,10 C10.5522847,10 11,10.4530363 11,10.9970301 L11,17.0029699 C11,17.5536144 10.5561352,18 10,18 C9.44771525,18 9,17.5469637 9,17.0029699 L9,10.9970301 Z M13,10.9970301 C13,10.4463856 13.4438648,10 14,10 C14.5522847,10 15,10.4530363 15,10.9970301 L15,17.0029699 C15,17.5536144 14.5561352,18 14,18 C13.4477153,18 13,17.5469637 13,17.0029699 L13,10.9970301 Z" id="Combined-Shape" fill="#585858"></path>
+ <path d="M9,5 L9,2.99895656 C9,2.44724809 9.45097518,2 9.99077797,2 L14.009222,2 C14.5564136,2 15,2.44266033 15,2.99895656 L15,5" id="Path-33" stroke="#585858" stroke-width="2" stroke-linejoin="round"></path>
+ </g>
+ </g>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Artboard-4" transform="translate(-224.000000, -159.000000)">
+ <g id="25" transform="translate(224.000000, 159.000000)">
+ <path d="M5,7 L5,20.0081158 C5,21.1082031 5.89706013,22 7.00585866,22 L16.9941413,22 C18.1019465,22 19,21.1066027 19,20.0081158 L19,7" id="Path-296" stroke="#ffffff" stroke-width="2"></path>
+ <rect id="Rectangle-424" fill="#ffffff" x="2" y="4" width="20" height="2" rx="1"></rect>
+ <path d="M9,10.9970301 C9,10.4463856 9.44386482,10 10,10 C10.5522847,10 11,10.4530363 11,10.9970301 L11,17.0029699 C11,17.5536144 10.5561352,18 10,18 C9.44771525,18 9,17.5469637 9,17.0029699 L9,10.9970301 Z M13,10.9970301 C13,10.4463856 13.4438648,10 14,10 C14.5522847,10 15,10.4530363 15,10.9970301 L15,17.0029699 C15,17.5536144 14.5561352,18 14,18 C13.4477153,18 13,17.5469637 13,17.0029699 L13,10.9970301 Z" id="Combined-Shape" fill="#ffffff"></path>
+ <path d="M9,5 L9,2.99895656 C9,2.44724809 9.45097518,2 9.99077797,2 L14.009222,2 C14.5564136,2 15,2.44266033 15,2.99895656 L15,5" id="Path-33" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"></path>
+ </g>
+ </g>
+ </g>
+</svg>
}
}
+.admin-sub-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 30px;
+
+ .admin-sub-title {
+ flex-grow: 1;
+ }
+}
+
.admin-sub-title {
font-size: 20px;
font-weight: bold;
// ngprime data table customizations
p-datatable {
+ font-size: 15px !important;
+
+ .ui-datatable-scrollable-header {
+ background-color: #fff !important;
+ }
+
+ .ui-widget-content {
+ border: none !important;
+ }
+
+ .ui-datatable-virtual-table {
+ border-top: none !important;
+ }
+
+ td {
+ border: 1px solid #E5E5E5 !important;
+ padding: 15px;
+ }
+
+ tr {
+ background-color: #fff !important;
+ height: 46px;
+
+ &:hover {
+ background-color: #f0f0f0 !important;
+ }
+
+ &:not(:hover) {
+ .action-cell * {
+ display: none !important;
+ }
+ }
+
+ &:first-child td {
+ border-top: none !important;
+ }
+ }
+
+ th {
+ border: none !important;
+ border-bottom: 1px solid #f0f0f0 !important;
+ text-align: left !important;
+ padding: 5px 0 5px 15px !important;
+ font-weight: $font-semibold !important;
+ color: #000 !important;
+
+ &.ui-state-active, &.ui-sortable-column:hover {
+ background-color: #f0f0f0 !important;
+ border: 1px solid #f0f0f0 !important;
+ }
+ }
+
.action-cell {
+ width: 250px !important;
+ padding: 0 !important;
text-align: center;
+ }
- .glyphicon {
- cursor: pointer;
+ p-paginator {
+ overflow: hidden;
+ display: block;
+ padding-top: 2px;
+ border: 1px solid #f0f0f0 !important;
+ border-top: none !important;
+
+ .ui-paginator-bottom {
+ position: relative;
+ border: none !important;
+ border-top: 1px solid #f0f0f0 !important;
+ box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.16);
+ height: 40px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ a {
+ color: #000 !important;
+ font-weight: $font-semibold !important;
+ margin-right: 20px !important;
+ outline: 0 !important;
+ border-radius: 3px !important;
+ padding: 5px 2px !important;
+
+ &.ui-state-active {
+ &, &:hover, &:active, &:focus {
+ color: #fff !important;
+ background-color: $orange-color !important;
+ }
+ }
+ }
}
}
}