Begin admin design

pull/159/head
Chocobozzz 2017-12-08 10:41:49 +01:00
parent 18327bdf51
commit 04e0fc4888
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
21 changed files with 297 additions and 302 deletions

View File

@ -0,0 +1,27 @@
<div class="row">
<div class="sub-menu">
<a *ngIf="hasUsersRight()" routerLink="/admin/users" routerLinkActive="active" class="title-page">
Users
</a>
<a *ngIf="hasServerFollowRight()" routerLink="/admin/follows" routerLinkActive="active" class="title-page">
Manage follows
</a>
<a *ngIf="hasVideoAbusesRight()" routerLink="/admin/video-abuses" routerLinkActive="active" class="title-page">
Video abuses
</a>
<a *ngIf="hasVideoBlacklistRight()" routerLink="/admin/video-blacklist" routerLinkActive="active" class="title-page">
Video blacklist
</a>
<a *ngIf="hasJobsRight()" routerLink="/admin/jobs" routerLinkActive="active" class="title-page">
Jobs
</a>
</div>
<div class="margin-content">
<router-outlet></router-outlet>
</div>
</div>

View File

@ -1,7 +1,31 @@
import { Component } from '@angular/core'
import { UserRight } from '../../../../shared'
import { AuthService } from '../core/auth/auth.service'
@Component({
template: '<router-outlet></router-outlet>'
templateUrl: './admin.component.html',
styleUrls: [ './admin.component.scss' ]
})
export class AdminComponent {
constructor (private auth: AuthService) {}
hasUsersRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_USERS)
}
hasServerFollowRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_SERVER_FOLLOW)
}
hasVideoAbusesRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES)
}
hasVideoBlacklistRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
}
hasJobsRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_JOBS)
}
}

View File

@ -1,16 +1,12 @@
<div class="row">
<div class="content-padding">
<h3>Followers list</h3>
<h3>Followers list</h3>
<p-dataTable
[value]="followers" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
sortField="createdAt" (onLazyLoad)="loadLazy($event)"
>
<p-column field="id" header="ID"></p-column>
<p-column field="follower.host" header="Host"></p-column>
<p-column field="follower.score" header="Score"></p-column>
<p-column field="state" header="State"></p-column>
<p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
</p-dataTable>
</div>
</div>
<p-dataTable
[value]="followers" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
sortField="createdAt" (onLazyLoad)="loadLazy($event)"
>
<p-column field="id" header="ID"></p-column>
<p-column field="follower.host" header="Host"></p-column>
<p-column field="follower.score" header="Score"></p-column>
<p-column field="state" header="State"></p-column>
<p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
</p-dataTable>

View File

@ -1,35 +1,30 @@
<div class="row">
<div class="content-padding">
<h3>Add following</h3>
<h3>Add following</h3>
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
<form (ngSubmit)="addFollowing()" [formGroup]="form">
<div class="form-group" *ngFor="let host of hosts; let id = index; trackBy:customTrackBy">
<label [for]="'host-' + id">Host (so without "http://")</label>
<form (ngSubmit)="addFollowing()" [formGroup]="form">
<div class="form-group" *ngFor="let host of hosts; let id = index; trackBy:customTrackBy">
<label [for]="'host-' + id">Host (so without "http://")</label>
<div class="input-group">
<input
type="text" class="form-control" placeholder="example.com"
[id]="'host-' + id" [formControlName]="'host-' + id"
/>
<span class="input-group-btn">
<button *ngIf="displayAddField(id)" (click)="addField()" class="btn btn-default" type="button">+</button>
<button *ngIf="displayRemoveField(id)" (click)="removeField(id)" class="btn btn-default" type="button">-</button>
</span>
</div>
<div class="input-group">
<input
type="text" class="form-control" placeholder="example.com"
[id]="'host-' + id" [formControlName]="'host-' + id"
/>
<span class="input-group-btn">
<button *ngIf="displayAddField(id)" (click)="addField()" class="btn btn-default" type="button">+</button>
<button *ngIf="displayRemoveField(id)" (click)="removeField(id)" class="btn btn-default" type="button">-</button>
</span>
</div>
<div [hidden]="form.controls['host-' + id].valid || form.controls['host-' + id].pristine" class="alert alert-warning">
It should be a valid host.
</div>
</div>
<div *ngIf="canMakeFriends() === false" class="alert alert-warning">
It seems that you are not on a HTTPS server. Your webserver need to have TLS activated in order to follow servers.
</div>
<input type="submit" value="Add following" class="btn btn-default" [disabled]="!isFormValid()">
</form>
<div [hidden]="form.controls['host-' + id].valid || form.controls['host-' + id].pristine" class="alert alert-warning">
It should be a valid host.
</div>
</div>
</div>
<div *ngIf="canMakeFriends() === false" class="alert alert-warning">
It seems that you are not on a HTTPS server. Your webserver need to have TLS activated in order to follow servers.
</div>
<input type="submit" value="Add following" class="btn btn-default" [disabled]="!isFormValid()">
</form>

View File

@ -1,20 +1,16 @@
<div class="row">
<div class="content-padding">
<h3>Following list</h3>
<h3>Following list</h3>
<p-dataTable
[value]="following" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
sortField="createdAt" (onLazyLoad)="loadLazy($event)"
>
<p-column field="id" header="ID"></p-column>
<p-column field="following.host" header="Host"></p-column>
<p-column field="state" header="State"></p-column>
<p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
<p-column header="Unfollow" styleClass="action-cell">
<ng-template pTemplate="body" let-following="rowData">
<span (click)="removeFollowing(following)" class="glyphicon glyphicon-remove glyphicon-black" title="Unfollow"></span>
</ng-template>
</p-column>
</p-dataTable>
</div>
</div>
<p-dataTable
[value]="following" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
sortField="createdAt" (onLazyLoad)="loadLazy($event)"
>
<p-column field="id" header="ID"></p-column>
<p-column field="following.host" header="Host"></p-column>
<p-column field="state" header="State"></p-column>
<p-column field="createdAt" header="Created date" [sortable]="true"></p-column>
<p-column header="Unfollow" styleClass="action-cell">
<ng-template pTemplate="body" let-following="rowData">
<span (click)="removeFollowing(following)" class="glyphicon glyphicon-remove glyphicon-black" title="Unfollow"></span>
</ng-template>
</p-column>
</p-dataTable>

View File

@ -1,21 +1,3 @@
.follows-menu {
margin-top: 20px;
}
tabset /deep/ {
.nav-link {
padding: 0;
}
.tab-link {
display: block;
text-align: center;
height: 40px;
width: 120px;
line-height: 40px;
&:hover, &:active, &:focus {
text-decoration: none !important;
}
}
}

View File

@ -1,73 +1,68 @@
<div class="row">
<div class="content-padding">
<div class="admin-sub-title" *ngIf="isCreation() === true">Add user</div>
<div class="admin-sub-title" *ngIf="isCreation() === false">Edit user {{ username }}</div>
<h3 *ngIf="isCreation() === true">Add user</h3>
<h3 *ngIf="isCreation() === false">Edit user {{ username }}</h3>
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
<form role="form" (ngSubmit)="formValidated()" [formGroup]="form">
<div class="form-group" *ngIf="isCreation()">
<label for="username">Username</label>
<input
type="text" class="form-control" id="username" placeholder="john"
formControlName="username"
>
<div *ngIf="formErrors.username" class="alert alert-danger">
{{ formErrors.username }}
</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input
type="text" class="form-control" id="email" placeholder="mail@example.com"
formControlName="email"
>
<div *ngIf="formErrors.email" class="alert alert-danger">
{{ formErrors.email }}
</div>
</div>
<div class="form-group" *ngIf="isCreation()">
<label for="password">Password</label>
<input
type="password" class="form-control" id="password"
formControlName="password"
>
<div *ngIf="formErrors.password" class="alert alert-danger">
{{ formErrors.password }}
</div>
</div>
<div class="form-group">
<label for="role">Role</label>
<select class="form-control" id="role" formControlName="role">
<option *ngFor="let role of roles" [value]="role.value">
{{ role.label }}
</option>
</select>
<div *ngIf="formErrors.role" class="alert alert-danger">
{{ formErrors.role }}
</div>
</div>
<div class="form-group">
<label for="videoQuota">Video quota</label>
<select class="form-control" id="videoQuota" formControlName="videoQuota">
<option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
{{ videoQuotaOption.label }}
</option>
</select>
<div class="transcoding-information" *ngIf="isTranscodingInformationDisplayed()">
Transcoding is enabled on server. The video quota only take in account <strong>original</strong> video. <br />
In maximum, this user could use ~ {{ computeQuotaWithTranscoding() | bytes }}.
</div>
</div>
<input type="submit" value="{{ getFormButtonTitle() }}" class="btn btn-default" [disabled]="!form.valid">
</form>
<form role="form" (ngSubmit)="formValidated()" [formGroup]="form">
<div class="form-group" *ngIf="isCreation()">
<label for="username">Username</label>
<input
type="text" class="form-control" id="username" placeholder="john"
formControlName="username" [ngClass]="{ 'input-error': formErrors['username'] }"
>
<div *ngIf="formErrors.username" class="form-error">
{{ formErrors.username }}
</div>
</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input
type="text" class="form-control" id="email" placeholder="mail@example.com"
formControlName="email" [ngClass]="{ 'input-error': formErrors['email'] }"
>
<div *ngIf="formErrors.email" class="form-error">
{{ formErrors.email }}
</div>
</div>
<div class="form-group" *ngIf="isCreation()">
<label for="password">Password</label>
<input
type="password" class="form-control" id="password"
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
>
<div *ngIf="formErrors.password" class="form-error">
{{ formErrors.password }}
</div>
</div>
<div class="form-group">
<label for="role">Role</label>
<select class="form-control" id="role" formControlName="role">
<option *ngFor="let role of roles" [value]="role.value">
{{ role.label }}
</option>
</select>
<div *ngIf="formErrors.role" class="form-error">
{{ formErrors.role }}
</div>
</div>
<div class="form-group">
<label for="videoQuota">Video quota</label>
<select class="form-control" id="videoQuota" formControlName="videoQuota">
<option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
{{ videoQuotaOption.label }}
</option>
</select>
<div class="transcoding-information" *ngIf="isTranscodingInformationDisplayed()">
Transcoding is enabled on server. The video quota only take in account <strong>original</strong> video. <br />
In maximum, this user could use ~ {{ computeQuotaWithTranscoding() | bytes }}.
</div>
</div>
<input type="submit" value="{{ getFormButtonTitle() }}" class="btn btn-default" [disabled]="!form.valid">
</form>

View File

@ -1,3 +1,21 @@
.admin-sub-title {
margin-bottom: 30px;
}
input:not([type=submit]) {
@include peertube-input-text(340px);
display: block;
}
select {
@include peertube-select(340px);
}
input[type=submit] {
@include peertube-button;
@include orange-button;
}
.transcoding-information {
margin-top: 5px;
font-size: 11px;

View File

@ -1,35 +1,32 @@
<div class="row">
<div class="content-padding">
<div class="sub-header">
<div class="admin-sub-title">Users list</div>
<h3>Users list</h3>
<p-dataTable
[value]="users" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
sortField="id" (onLazyLoad)="loadLazy($event)"
>
<p-column field="id" header="ID" [sortable]="true"></p-column>
<p-column field="username" header="Username" [sortable]="true"></p-column>
<p-column field="email" header="Email"></p-column>
<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>
</ng-template>
</p-column>
</p-dataTable>
<a class="add-user btn btn-success pull-right" [routerLink]="['/admin/users/add']">
<span class="glyphicon glyphicon-plus"></span>
Add user
</a>
</div>
<a class="add-button" routerLink="/admin/users/add">
<span class="icon icon-add"></span>
Add user
</a>
</div>
<p-dataTable
[value]="users" [lazy]="true" [paginator]="true" [totalRecords]="totalRecords" [rows]="rowsPerPage"
sortField="id" (onLazyLoad)="loadLazy($event)"
>
<p-column field="id" header="ID" [sortable]="true"></p-column>
<p-column field="username" header="Username" [sortable]="true"></p-column>
<p-column field="email" header="Email"></p-column>
<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>
</ng-template>
</p-column>
</p-dataTable>

View File

@ -1,3 +1,21 @@
.add-user {
margin-top: 10px;
.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;
.icon.icon-add {
@include icon(22px);
margin-right: 3px;
background-image: url('../../../../assets/images/admin/add.svg');
}
}
}

View File

@ -19,8 +19,7 @@
<div class="title-menu-left">
<div class="title-menu-left-block menu">
<my-menu *ngIf="isMenuDisplayed && isInAdmin() === false"></my-menu>
<my-menu-admin *ngIf="isMenuDisplayed && isInAdmin() === true"></my-menu-admin>
<my-menu *ngIf="isMenuDisplayed"></my-menu>
</div>
</div>

View File

@ -20,7 +20,7 @@ import { LoginModule } from './login'
import { SignupModule } from './signup'
import { SharedModule } from './shared'
import { VideosModule } from './videos'
import { MenuComponent, MenuAdminComponent } from './menu'
import { MenuComponent } from './menu'
import { HeaderComponent } from './header'
export function metaFactory (): MetaLoader {
@ -52,7 +52,6 @@ const APP_PROVIDERS = [
AppComponent,
MenuComponent,
MenuAdminComponent,
HeaderComponent
],
imports: [

View File

@ -27,10 +27,9 @@
margin-right: 25px;
.icon.icon-upload {
display: inline-block;
background: url('../../assets/images/header/upload.svg') no-repeat;
background-size: contain;
width: 22px;
@include icon(22px);
background-image: url('../../assets/images/header/upload.svg');
height: 24px;
vertical-align: middle;
margin-right: 6px;

View File

@ -1,2 +1 @@
export * from './menu.component'
export * from './menu-admin.component'

View File

@ -1,35 +0,0 @@
<menu>
<div class="panel-block">
<a *ngIf="hasUsersRight()" routerLink="/admin/users" routerLinkActive="active">
<span class="hidden-xs glyphicon glyphicon-user"></span>
List users
</a>
<a *ngIf="hasServerFollowRight()" routerLink="/admin/follows" routerLinkActive="active">
<span class="hidden-xs glyphicon glyphicon-cloud"></span>
Manage follows
</a>
<a *ngIf="hasVideoAbusesRight()" routerLink="/admin/video-abuses" routerLinkActive="active">
<span class="hidden-xs glyphicon glyphicon-alert"></span>
Video abuses
</a>
<a *ngIf="hasVideoBlacklistRight()" routerLink="/admin/video-blacklist" routerLinkActive="active">
<span class="hidden-xs glyphicon glyphicon-eye-close"></span>
Video blacklist
</a>
<a *ngIf="hasJobsRight()" routerLink="/admin/jobs" routerLinkActive="active">
<span class="hidden-xs glyphicon glyphicon-tasks"></span>
Jobs
</a>
</div>
<div class="panel-block">
<a routerLink="/videos/list" routerLinkActive="active">
<span class="hidden-xs glyphicon glyphicon-cog"></span>
Quit admin.
</a>
</div>
</menu>

View File

@ -1,33 +0,0 @@
import { Component } from '@angular/core'
import { AuthService } from '../core/auth/auth.service'
import { UserRight } from '../../../../shared'
@Component({
selector: 'my-menu-admin',
templateUrl: './menu-admin.component.html',
styleUrls: [ './menu.component.scss' ]
})
export class MenuAdminComponent {
constructor (private auth: AuthService) {}
hasUsersRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_USERS)
}
hasServerFollowRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_SERVER_FOLLOW)
}
hasVideoAbusesRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_ABUSES)
}
hasVideoBlacklistRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
}
hasJobsRight () {
return this.auth.getUser().hasRight(UserRight.MANAGE_JOBS)
}
}

View File

@ -5,37 +5,3 @@ textarea {
font-size: 15px;
height: 150px;
}
.previews /deep/ {
font-size: 15px !important;
.nav {
margin-top: 10px;
font-size: 16px !important;
border: none !important;
.nav-item .nav-link {
color: #000 !important;
height: 30px !important;
margin-right: 30px;
padding: 0 15px;
display: flex;
align-items: center;
border-radius: 3px;
border: none !important;
&.active, &:hover {
background-color: #F0F0F0;
}
&.active {
font-weight: $font-semibold !important;
}
}
}
.tab-content {
min-height: 75px;
padding: 15px;
}
}

View File

@ -0,0 +1,13 @@
<?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(-92.000000, -115.000000)">
<g id="2" transform="translate(92.000000, 115.000000)">
<circle id="Oval-1" stroke="#ffffff" stroke-width="2" cx="12" cy="12" r="10"></circle>
<rect id="Rectangle-1" fill="#ffffff" x="11" y="7" width="2" height="10" rx="1"></rect>
<rect id="Rectangle-1" fill="#ffffff" x="7" y="11" width="10" height="2" rx="1"></rect>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 785 B

View File

@ -89,7 +89,12 @@ label {
&:hover, &:active, &:focus {
color: #000;
}
}
.admin-sub-title {
font-size: 20px;
font-weight: bold;
}
// On small screen, menu is absolute and displayed over the page
@ -132,7 +137,7 @@ label {
to { -moz-transform: rotate(360deg);}
}
/* ngprime data table customizations */
// ngprime data table customizations
p-datatable {
.action-cell {
text-align: center;
@ -143,6 +148,7 @@ p-datatable {
}
}
// Bootstrap customizations
.dropdown-menu {
border-radius: 3px;
box-shadow: 0 3px 6px;
@ -167,6 +173,40 @@ p-datatable {
}
}
.nav {
margin-top: 10px;
font-size: 16px !important;
border: none !important;
.nav-item .nav-link {
height: 30px !important;
margin-right: 30px;
padding: 0 15px;
display: flex;
align-items: center;
border-radius: 3px;
border: none !important;
&, & a {
color: #000 !important;
}
&.active, &:hover {
background-color: #F0F0F0;
}
&.active {
font-weight: $font-semibold !important;
}
}
.tab-content {
min-height: 75px;
padding: 15px;
}
}
.orange-button {
@include peertube-button;
@include orange-button;

View File

@ -113,7 +113,7 @@ describe('Test users', function () {
it('Should upload the video with the correct token', async function () {
const videoAttributes = {}
await uploadVideo(server.url, accessToken, videoAttributes, 204)
await uploadVideo(server.url, accessToken, videoAttributes)
const res = await getVideosList(server.url)
const video = res.body.data[ 0 ]
@ -125,7 +125,7 @@ describe('Test users', function () {
it('Should upload the video again with the correct token', async function () {
const videoAttributes = {}
await uploadVideo(server.url, accessToken, videoAttributes, 204)
await uploadVideo(server.url, accessToken, videoAttributes)
})
it('Should retrieve a video rating', async function () {