Added /users
This commit is contained in:
parent
0acd117e87
commit
193b17ac19
|
@ -1,3 +1,6 @@
|
||||||
|
import { EditUserComponent } from './pages/edit-user/edit-user.component';
|
||||||
|
import { AdminGuard } from './services/admin-guard.service';
|
||||||
|
import { UsersComponent } from './pages/users/users.component';
|
||||||
import { CreateAuthComponent } from './pages/create-auth/create-auth.component';
|
import { CreateAuthComponent } from './pages/create-auth/create-auth.component';
|
||||||
import { CreateSlaveComponent } from './pages/create-slave/create-slave.component';
|
import { CreateSlaveComponent } from './pages/create-slave/create-slave.component';
|
||||||
import { EditSlaveComponent } from './pages/edit-slave/edit-slave.component';
|
import { EditSlaveComponent } from './pages/edit-slave/edit-slave.component';
|
||||||
|
@ -57,6 +60,20 @@ const routes: Routes = [
|
||||||
component: CreateAuthComponent,
|
component: CreateAuthComponent,
|
||||||
data: { type: 'NATIVE' }
|
data: { type: 'NATIVE' }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
canActivate: [AdminGuard],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'users',
|
||||||
|
component: UsersComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'users/:userId',
|
||||||
|
component: EditUserComponent
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'password',
|
path: 'password',
|
||||||
component: PasswordComponent
|
component: PasswordComponent
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<app-navbar *ngIf="gs.isLoggedIn" brand="PDNS Manager">
|
<app-navbar *ngIf="gs.isLoggedIn" brand="PDNS Manager">
|
||||||
<app-navbar-entry icon="navicon" target="/domains">Domains</app-navbar-entry>
|
<app-navbar-entry icon="navicon" target="/domains">Domains</app-navbar-entry>
|
||||||
|
<app-navbar-entry *ngIf="gs.isAdmin" icon="users" target="/users">Users</app-navbar-entry>
|
||||||
<app-navbar-entry *ngIf="gs.isNative" icon="key" target="/password">Password</app-navbar-entry>
|
<app-navbar-entry *ngIf="gs.isNative" icon="key" target="/password">Password</app-navbar-entry>
|
||||||
|
|
||||||
<app-navbar-entry icon="sign-out" right (click)="onLogout()" neverActive>Logout</app-navbar-entry>
|
<app-navbar-entry icon="sign-out" right (click)="onLogout()" neverActive>Logout</app-navbar-entry>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import { EditUserComponent } from './pages/edit-user/edit-user.component';
|
||||||
|
import { UsersOperation } from './operations/users.operations';
|
||||||
|
import { AdminGuard } from './services/admin-guard.service';
|
||||||
import { CreateAuthComponent } from './pages/create-auth/create-auth.component';
|
import { CreateAuthComponent } from './pages/create-auth/create-auth.component';
|
||||||
import { StopPropagateClickDirective } from './utils/stop-propagate-click.directive';
|
import { StopPropagateClickDirective } from './utils/stop-propagate-click.directive';
|
||||||
import { PagesizeComponent } from './partials/pagesize/pagesize.component';
|
import { PagesizeComponent } from './partials/pagesize/pagesize.component';
|
||||||
|
@ -30,6 +33,7 @@ import { EditSlaveComponent } from './pages/edit-slave/edit-slave.component';
|
||||||
import { EditAuthComponent } from './pages/edit-auth/edit-auth.component';
|
import { EditAuthComponent } from './pages/edit-auth/edit-auth.component';
|
||||||
import { SelectComponent } from './partials/select/select.component';
|
import { SelectComponent } from './partials/select/select.component';
|
||||||
import { CreateSlaveComponent } from './pages/create-slave/create-slave.component';
|
import { CreateSlaveComponent } from './pages/create-slave/create-slave.component';
|
||||||
|
import { UsersComponent } from './pages/users/users.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -52,7 +56,9 @@ import { CreateSlaveComponent } from './pages/create-slave/create-slave.componen
|
||||||
SelectComponent,
|
SelectComponent,
|
||||||
StopPropagateClickDirective,
|
StopPropagateClickDirective,
|
||||||
CreateSlaveComponent,
|
CreateSlaveComponent,
|
||||||
CreateAuthComponent
|
CreateAuthComponent,
|
||||||
|
UsersComponent,
|
||||||
|
EditUserComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -66,7 +72,9 @@ import { CreateSlaveComponent } from './pages/create-slave/create-slave.componen
|
||||||
SessionOperation,
|
SessionOperation,
|
||||||
PasswordOperation,
|
PasswordOperation,
|
||||||
DomainsOperation,
|
DomainsOperation,
|
||||||
AuthGuard
|
UsersOperation,
|
||||||
|
AuthGuard,
|
||||||
|
AdminGuard
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
|
88
frontend/src/app/operations/users.operations.ts
Normal file
88
frontend/src/app/operations/users.operations.ts
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
import { UserApitype } from './../apitypes/User.apitype';
|
||||||
|
import { ListApitype } from './../apitypes/List.apitype';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpService } from '../services/http.service';
|
||||||
|
import { StateService } from '../services/state.service';
|
||||||
|
import { SessionApitype } from '../apitypes/Session.apitype';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UsersOperation {
|
||||||
|
|
||||||
|
constructor(private http: HttpService, private gs: StateService) { }
|
||||||
|
|
||||||
|
public async getList(page?: number, pageSize?: number, query?: string,
|
||||||
|
sort?: Array<String> | string, type?: string): Promise<ListApitype<UserApitype>> {
|
||||||
|
try {
|
||||||
|
return new ListApitype<UserApitype>(await this.http.get('/users', {
|
||||||
|
page: page,
|
||||||
|
pagesize: pageSize,
|
||||||
|
query: query,
|
||||||
|
sort: sort,
|
||||||
|
type: type
|
||||||
|
}));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return new ListApitype<UserApitype>({ paging: {}, results: [] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async delete(userId: number): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await this.http.delete(['/users', userId.toString()]);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getSingle(userId: number): Promise<UserApitype> {
|
||||||
|
try {
|
||||||
|
return new UserApitype(await this.http.get(['/users', userId.toString()]));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return new UserApitype({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateUser(userId: number, name?: string, type?: string, password?: string): Promise<boolean> {
|
||||||
|
const data = {};
|
||||||
|
if (name !== null && name !== undefined) {
|
||||||
|
data['name'] = name;
|
||||||
|
}
|
||||||
|
if (type !== null && type !== undefined) {
|
||||||
|
data['type'] = type;
|
||||||
|
}
|
||||||
|
if (password !== null && password !== undefined) {
|
||||||
|
data['password'] = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.http.put(['/users', userId.toString()], data);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async create(name: string, type: string, password: string): Promise<UserApitype> {
|
||||||
|
try {
|
||||||
|
const result = new UserApitype(await this.http.post('/users', {
|
||||||
|
name: name,
|
||||||
|
type: type,
|
||||||
|
password: password
|
||||||
|
}));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.response.status || e.response.status === 409) {
|
||||||
|
throw new Error('User already exists!');
|
||||||
|
} else {
|
||||||
|
console.error(e);
|
||||||
|
return new UserApitype({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,7 @@
|
||||||
</th>
|
</th>
|
||||||
<th class="w-20 align-middle">
|
<th class="w-20 align-middle">
|
||||||
<div class="form-inline">
|
<div class="form-inline">
|
||||||
<span>Name</span>
|
<span>Type</span>
|
||||||
<app-sort field="type" [activeFields]="sortField" (sort)="onSortEvent($event)"></app-sort>
|
<app-sort field="type" [activeFields]="sortField" (sort)="onSortEvent($event)"></app-sort>
|
||||||
<app-select [options]="typeFilterOptions" [formControl]="typeFilter"></app-select>
|
<app-select [options]="typeFilterOptions" [formControl]="typeFilter"></app-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<p>
|
||||||
|
Edit user works!
|
||||||
|
</p>
|
19
frontend/src/app/pages/edit-user/edit-user.component.ts
Normal file
19
frontend/src/app/pages/edit-user/edit-user.component.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-edit-user',
|
||||||
|
templateUrl: './edit-user.component.html',
|
||||||
|
styleUrls: ['./edit-user.component.scss']
|
||||||
|
})
|
||||||
|
export class EditUserComponent implements OnInit {
|
||||||
|
|
||||||
|
public type: string;
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
50
frontend/src/app/pages/users/users.component.html
Normal file
50
frontend/src/app/pages/users/users.component.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<div class="row justify-content-end">
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<button class="btn btn-secondary btn-sm">Add user</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 mt-2 mt-md-0">
|
||||||
|
<app-pagesize class="float-md-right" [pagesizes]="gs.pageSizes" [currentPagesize]="gs.pageSize" (pagesizeChange)="onPagesizeChange($event)"></app-pagesize>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="table-responsive-lg">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="w-10 align-middle">
|
||||||
|
<span>ID</span>
|
||||||
|
<app-sort field="id" [activeFields]="sortField" (sort)="onSortEvent($event)"></app-sort>
|
||||||
|
</th>
|
||||||
|
<th class="align-middle">
|
||||||
|
<div class="form-inline">
|
||||||
|
<span>Name</span>
|
||||||
|
<app-sort field="name" [activeFields]="sortField" (sort)="onSortEvent($event)"></app-sort>
|
||||||
|
<input class="form-control form-control-sm no-shadow" type="text" placeholder="Search" [formControl]="searchInput">
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<th class="w-20 align-middle">
|
||||||
|
<div class="form-inline">
|
||||||
|
<span>Type</span>
|
||||||
|
<app-sort field="type" [activeFields]="sortField" (sort)="onSortEvent($event)"></app-sort>
|
||||||
|
<app-select [options]="typeFilterOptions" [formControl]="typeFilter"></app-select>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<th class="w-5 align-middle"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let user of userList" class="cursor-pointer" (click)="onUserClick(user)">
|
||||||
|
<td>{{ user.id }}</td>
|
||||||
|
<td>{{ user.name }}</td>
|
||||||
|
<td>{{ user.type }}</td>
|
||||||
|
<td>
|
||||||
|
<app-fa-icon class="cursor-pointer" icon="trash" appStopPropagateClick (click)="onDeleteUser(user)"></app-fa-icon>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<app-paging [pagingInfo]="pagingInfo" [pageWidth]="3" (pageChange)="onPageChange($event)"></app-paging>
|
0
frontend/src/app/pages/users/users.component.scss
Normal file
0
frontend/src/app/pages/users/users.component.scss
Normal file
99
frontend/src/app/pages/users/users.component.ts
Normal file
99
frontend/src/app/pages/users/users.component.ts
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
import { UsersOperation } from './../../operations/users.operations';
|
||||||
|
import { UserApitype } from './../../apitypes/User.apitype';
|
||||||
|
import { SortEventDatatype } from './../../datatypes/sort-event.datatype';
|
||||||
|
import { ModalOptionsDatatype } from './../../datatypes/modal-options.datatype';
|
||||||
|
import { ModalService } from './../../services/modal.service';
|
||||||
|
import { StateService } from './../../services/state.service';
|
||||||
|
import { PagingApitype } from './../../apitypes/Paging.apitype';
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
|
||||||
|
import 'rxjs/add/operator/debounceTime';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-users',
|
||||||
|
templateUrl: './users.component.html',
|
||||||
|
styleUrls: ['./users.component.scss']
|
||||||
|
})
|
||||||
|
export class UsersComponent implements OnInit {
|
||||||
|
|
||||||
|
public pagingInfo = new PagingApitype({});
|
||||||
|
public pageRequested = 1;
|
||||||
|
|
||||||
|
public userList: UserApitype[] = [];
|
||||||
|
|
||||||
|
public sortField = '';
|
||||||
|
public sortOrder = 'asc';
|
||||||
|
|
||||||
|
public searchInput: FormControl;
|
||||||
|
public typeFilter: FormControl;
|
||||||
|
public typeFilterOptions = ['admin', 'user'];
|
||||||
|
|
||||||
|
constructor(private users: UsersOperation, public gs: StateService, private modal: ModalService, private router: Router) { }
|
||||||
|
|
||||||
|
public ngOnInit() {
|
||||||
|
this.searchInput = new FormControl('');
|
||||||
|
this.searchInput.valueChanges.debounceTime(500).subscribe(() => this.loadData());
|
||||||
|
|
||||||
|
this.typeFilter = new FormControl(null);
|
||||||
|
this.typeFilter.valueChanges.subscribe(() => this.loadData());
|
||||||
|
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async loadData() {
|
||||||
|
const sortStr = this.sortField !== '' ? this.sortField + '-' + this.sortOrder : null;
|
||||||
|
const searchStr = this.searchInput.value !== '' ? this.searchInput.value : null;
|
||||||
|
const typeFilter = this.typeFilter.value;
|
||||||
|
|
||||||
|
const res = await this.users.getList(this.pageRequested, this.gs.pageSize, searchStr, sortStr, typeFilter);
|
||||||
|
|
||||||
|
this.pagingInfo = res.paging;
|
||||||
|
this.userList = res.results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onDeleteUser(user: UserApitype) {
|
||||||
|
try {
|
||||||
|
await this.modal.showMessage(new ModalOptionsDatatype({
|
||||||
|
heading: 'Confirm deletion',
|
||||||
|
body: 'Are you shure you want to delete ' + user.name + '?',
|
||||||
|
acceptText: 'Delete',
|
||||||
|
dismisText: 'Cancel',
|
||||||
|
acceptClass: 'danger'
|
||||||
|
}));
|
||||||
|
|
||||||
|
await this.users.delete(user.id);
|
||||||
|
|
||||||
|
await this.loadData();
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onPageChange(newPage: number) {
|
||||||
|
this.pageRequested = newPage;
|
||||||
|
await this.loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onPagesizeChange(pagesize: number) {
|
||||||
|
this.gs.pageSize = pagesize;
|
||||||
|
this.pageRequested = 1;
|
||||||
|
await this.loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onUserClick(domain: UserApitype) {
|
||||||
|
this.router.navigate(['/users', domain.id.toString()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onSortEvent(sortEvent: SortEventDatatype) {
|
||||||
|
if (sortEvent.order === 0) {
|
||||||
|
this.sortField = '';
|
||||||
|
this.sortOrder = 'asc';
|
||||||
|
} else {
|
||||||
|
this.sortField = sortEvent.field;
|
||||||
|
this.sortOrder = sortEvent.order === 1 ? 'asc' : 'desc';
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.loadData();
|
||||||
|
}
|
||||||
|
}
|
18
frontend/src/app/services/admin-guard.service.ts
Normal file
18
frontend/src/app/services/admin-guard.service.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { StateService } from './state.service';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AdminGuard implements CanActivate {
|
||||||
|
|
||||||
|
constructor(private gs: StateService, private router: Router) { }
|
||||||
|
|
||||||
|
canActivate(): boolean {
|
||||||
|
if (!this.gs.isAdmin) {
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue