mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-05-09 12:02:53 +00:00
group management, add create new group functionality
This commit is contained in:
parent
2ea79aaa27
commit
7219f02783
@ -275,6 +275,7 @@ import { UserService } from './services/user.service';
|
|||||||
import { LoggedUserComponent } from './components/users/logged-user/logged-user.component';
|
import { LoggedUserComponent } from './components/users/logged-user/logged-user.component';
|
||||||
import { GroupManagementComponent } from './components/group-management/group-management.component';
|
import { GroupManagementComponent } from './components/group-management/group-management.component';
|
||||||
import { GroupFilterPipe } from './filters/group-filter.pipe';
|
import { GroupFilterPipe } from './filters/group-filter.pipe';
|
||||||
|
import { AddGroupDialogComponent } from './components/group-management/add-group-dialog/add-group-dialog.component';
|
||||||
import { AddUserDialogComponent } from './components/user-management/add-user-dialog/add-user-dialog.component';
|
import { AddUserDialogComponent } from './components/user-management/add-user-dialog/add-user-dialog.component';
|
||||||
import { UserFilterPipe } from './filters/user-filter.pipe';
|
import { UserFilterPipe } from './filters/user-filter.pipe';
|
||||||
|
|
||||||
@ -465,6 +466,7 @@ import { UserFilterPipe } from './filters/user-filter.pipe';
|
|||||||
EditNetworkConfigurationDialogComponent,
|
EditNetworkConfigurationDialogComponent,
|
||||||
UserManagementComponent,
|
UserManagementComponent,
|
||||||
ProjectReadmeComponent,
|
ProjectReadmeComponent,
|
||||||
|
AddGroupDialogComponent,
|
||||||
GroupFilterPipe,
|
GroupFilterPipe,
|
||||||
GroupManagementComponent,
|
GroupManagementComponent,
|
||||||
AddUserDialogComponent,
|
AddUserDialogComponent,
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GroupNameValidator {
|
||||||
|
get(groupName) {
|
||||||
|
const pattern = new RegExp(/[~`!#$%\^&*+=\[\]\\';,/{}|\\":<>\?]/);
|
||||||
|
|
||||||
|
if (!pattern.test(groupName.value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { invalidName: true };
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
<h1 mat-dialog-title>Create new group</h1>
|
||||||
|
<form [formGroup]="groupNameForm" class="file-name-form">
|
||||||
|
<mat-form-field class="file-name-form-field">
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
(keydown)="onKeyDown($event)"
|
||||||
|
type="text"
|
||||||
|
formControlName="groupName"
|
||||||
|
[ngClass]="{ 'is-invalid': form.groupName?.errors }"
|
||||||
|
placeholder="Please enter group name"
|
||||||
|
/>
|
||||||
|
<mat-error *ngIf="form.groupName?.touched && form.groupName?.errors && form.groupName?.errors.required"
|
||||||
|
>Group name is required</mat-error
|
||||||
|
>
|
||||||
|
<mat-error *ngIf="form.groupName?.errors && form.groupName?.errors.invalidName"
|
||||||
|
>Group name is incorrect</mat-error
|
||||||
|
>
|
||||||
|
<mat-error *ngIf="form.groupName?.errors && form.groupName?.errors.projectExist"
|
||||||
|
>Group with this name exists</mat-error
|
||||||
|
>
|
||||||
|
</mat-form-field>
|
||||||
|
<div mat-dialog-actions>
|
||||||
|
<button mat-button (click)="onNoClick()" color="accent">Cancel</button>
|
||||||
|
<button mat-button (click)="onAddClick()" tabindex="2" class="add-project-button" mat-raised-button color="primary">
|
||||||
|
Add group
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
@ -0,0 +1,7 @@
|
|||||||
|
.file-name-form-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-snackbar {
|
||||||
|
background: #2196f3;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AddGroupDialogComponent } from './add-group-dialog.component';
|
||||||
|
|
||||||
|
describe('AddGroupDialogComponent', () => {
|
||||||
|
let component: AddGroupDialogComponent;
|
||||||
|
let fixture: ComponentFixture<AddGroupDialogComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ AddGroupDialogComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AddGroupDialogComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,57 @@
|
|||||||
|
import {Component, Inject, OnInit} from '@angular/core';
|
||||||
|
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||||
|
import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
|
||||||
|
import {groupNameAsyncValidator} from "@components/group-management/add-group-dialog/groupNameAsyncValidator";
|
||||||
|
import {GroupNameValidator} from "@components/group-management/add-group-dialog/GroupNameValidator";
|
||||||
|
import {GroupService} from "../../../services/group.service";
|
||||||
|
import {Server} from "../../../models/server";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-add-group-dialog',
|
||||||
|
templateUrl: './add-group-dialog.component.html',
|
||||||
|
styleUrls: ['./add-group-dialog.component.scss'],
|
||||||
|
providers: [GroupNameValidator]
|
||||||
|
})
|
||||||
|
export class AddGroupDialogComponent implements OnInit {
|
||||||
|
|
||||||
|
groupNameForm: FormGroup;
|
||||||
|
|
||||||
|
constructor(private dialogRef: MatDialogRef<AddGroupDialogComponent>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: { server: Server },
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
|
private groupNameValidator: GroupNameValidator,
|
||||||
|
private groupService: GroupService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.groupNameForm = this.formBuilder.group({
|
||||||
|
groupName: new FormControl(
|
||||||
|
null,
|
||||||
|
[Validators.required, this.groupNameValidator.get],
|
||||||
|
[groupNameAsyncValidator(this.data.server, this.groupService)]
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyDown(event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
this.onAddClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get form() {
|
||||||
|
return this.groupNameForm.controls;
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddClick() {
|
||||||
|
if (this.groupNameForm.invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const groupName = this.groupNameForm.controls['groupName'].value;
|
||||||
|
this.dialogRef.close(groupName);
|
||||||
|
}
|
||||||
|
|
||||||
|
onNoClick() {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
import { timer } from 'rxjs';
|
||||||
|
import {map, switchMap, tap} from 'rxjs/operators';
|
||||||
|
import {Server} from "../../../models/server";
|
||||||
|
import {GroupService} from "../../../services/group.service";
|
||||||
|
|
||||||
|
export const groupNameAsyncValidator = (server: Server, groupService: GroupService) => {
|
||||||
|
return (control: FormControl) => {
|
||||||
|
return timer(500).pipe(
|
||||||
|
switchMap(() => groupService.getGroups(server)),
|
||||||
|
map((response) => {
|
||||||
|
console.log(response);
|
||||||
|
return (response.find((n) => n.name === control.value) ? { projectExist: true } : null);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
@ -2,6 +2,9 @@
|
|||||||
<div class="default-header">
|
<div class="default-header">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h1 class="col">Groups management</h1>
|
<h1 class="col">Groups management</h1>
|
||||||
|
<button class="col" mat-raised-button color="primary" (click)="addGroup()" class="add-group-button">
|
||||||
|
Add group
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -8,3 +8,8 @@ table {
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.add-group-button {
|
||||||
|
height: 40px;
|
||||||
|
width: 160px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
@ -18,6 +18,8 @@ import {GroupService} from "../../services/group.service";
|
|||||||
import {Server} from "../../models/server";
|
import {Server} from "../../models/server";
|
||||||
import {Group} from "../../models/groups/group";
|
import {Group} from "../../models/groups/group";
|
||||||
import {Sort} from "@angular/material/sort";
|
import {Sort} from "@angular/material/sort";
|
||||||
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
|
import {AddGroupDialogComponent} from "@components/group-management/add-group-dialog/add-group-dialog.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-group-management',
|
selector: 'app-group-management',
|
||||||
@ -37,6 +39,7 @@ export class GroupManagementComponent implements OnInit {
|
|||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
private toasterService: ToasterService,
|
private toasterService: ToasterService,
|
||||||
public groupService: GroupService,
|
public groupService: GroupService,
|
||||||
|
public dialog: MatDialog
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,4 +75,24 @@ export class GroupManagementComponent implements OnInit {
|
|||||||
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
|
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addGroup() {
|
||||||
|
this.dialog
|
||||||
|
.open(AddGroupDialogComponent, {width: '250px', height: '250px', data: {server: this.server}})
|
||||||
|
.afterClosed()
|
||||||
|
.subscribe((name: string) => {
|
||||||
|
if (name) {
|
||||||
|
this.groupService.addGroup(this.server, name)
|
||||||
|
.subscribe(() => {
|
||||||
|
this.groupService.getGroups(this.server).subscribe((groups: Group[]) => {
|
||||||
|
this.groups = groups;
|
||||||
|
this.sortedGroups = groups;
|
||||||
|
});
|
||||||
|
}, (error) => {
|
||||||
|
this.toasterService.error(`An error occur while trying to create new group ${name}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,12 @@
|
|||||||
*
|
*
|
||||||
* Author: Sylvain MATHIEU, Elise LEBEAU
|
* Author: Sylvain MATHIEU, Elise LEBEAU
|
||||||
*/
|
*/
|
||||||
import { Injectable } from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {HttpServer} from "./http-server.service";
|
import {HttpServer} from "./http-server.service";
|
||||||
import {Server} from "../models/server";
|
import {Server} from "../models/server";
|
||||||
import {Group} from "../models/groups/group";
|
import {Group} from "../models/groups/group";
|
||||||
import {User} from "../models/users/user";
|
import {User} from "../models/users/user";
|
||||||
|
import {Observable} from "rxjs";
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -23,7 +24,8 @@ export class GroupService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private httpServer: HttpServer
|
private httpServer: HttpServer
|
||||||
) { }
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
getGroups(server: Server) {
|
getGroups(server: Server) {
|
||||||
return this.httpServer.get<Group[]>(server, '/groups');
|
return this.httpServer.get<Group[]>(server, '/groups');
|
||||||
@ -32,4 +34,8 @@ export class GroupService {
|
|||||||
getGroupMember(server: Server, groupId: string) {
|
getGroupMember(server: Server, groupId: string) {
|
||||||
return this.httpServer.get<User[]>(server, `/groups/${groupId}/members`);
|
return this.httpServer.get<User[]>(server, `/groups/${groupId}/members`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addGroup(server: Server, name: string): Observable<Group> {
|
||||||
|
return this.httpServer.post<Group>(server, `/groups`, {name});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user