commit b6006ff48983d4e4a37daebe54189961ddc6a9c9
Author: hlavja <hlavjah@gmail.com>
Date:   Sun May 2 23:35:18 2021 +0200

    Re #8786 - Přidání uživatele - formulář, endpoint
    
    + OpenAPI definition for adding user
    + new popup form for adding user

diff --git a/src/app/auth/interceptors/auth.interceptor.ts b/src/app/auth/interceptors/auth.interceptor.ts
index 84e9408..97401c6 100644
--- a/src/app/auth/interceptors/auth.interceptor.ts
+++ b/src/app/auth/interceptors/auth.interceptor.ts
@@ -28,7 +28,7 @@ export class AuthInterceptor implements HttpInterceptor {
       return of(null);
     }
 
-    if (request.url.includes('DataService')){
+    if (request.url.includes('DataService') || request.url.includes('GroupService')){
       request = request.clone({
         setParams: {
           user: localStorage.getItem(GlobalVariable.USER_NAME)
diff --git a/src/app/shared/api/endpoints/api.module.ts b/src/app/shared/api/endpoints/api.module.ts
index 7c83a2f..a014dca 100644
--- a/src/app/shared/api/endpoints/api.module.ts
+++ b/src/app/shared/api/endpoints/api.module.ts
@@ -5,6 +5,7 @@ import { HttpClient } from '@angular/common/http';
 import { ApiConfiguration, ApiConfigurationParams } from './api-configuration';
 
 import { LoginService } from './services/login.service';
+import { AdministrationService } from './services/administration.service';
 import { GroupService } from './services/group.service';
 import { DataService } from './services/data.service';
 import { AnalyticsService } from './services/analytics.service';
@@ -20,6 +21,7 @@ import { SensorsService } from './services/sensors.service';
   declarations: [],
   providers: [
     LoginService,
+    AdministrationService,
     GroupService,
     DataService,
     AnalyticsService,
diff --git a/src/app/shared/api/endpoints/models.ts b/src/app/shared/api/endpoints/models.ts
index 34f655f..c900442 100644
--- a/src/app/shared/api/endpoints/models.ts
+++ b/src/app/shared/api/endpoints/models.ts
@@ -1,3 +1,4 @@
+export { Right } from './models/right';
 export { InsertUnit } from './models/insert-unit';
 export { InsertSensor } from './models/insert-sensor';
 export { InsertPhenomenon } from './models/insert-phenomenon';
diff --git a/src/app/shared/api/endpoints/models/right.ts b/src/app/shared/api/endpoints/models/right.ts
new file mode 100644
index 0000000..5e95f2e
--- /dev/null
+++ b/src/app/shared/api/endpoints/models/right.ts
@@ -0,0 +1,7 @@
+/* tslint:disable */
+/* eslint-disable */
+export interface Right {
+  note?: string;
+  rightsId?: number;
+  userRole?: string;
+}
diff --git a/src/app/shared/api/endpoints/services.ts b/src/app/shared/api/endpoints/services.ts
index 962a870..68c080b 100644
--- a/src/app/shared/api/endpoints/services.ts
+++ b/src/app/shared/api/endpoints/services.ts
@@ -1,4 +1,5 @@
 export { LoginService } from './services/login.service';
+export { AdministrationService } from './services/administration.service';
 export { GroupService } from './services/group.service';
 export { DataService } from './services/data.service';
 export { AnalyticsService } from './services/analytics.service';
diff --git a/src/app/shared/api/endpoints/services/administration.service.ts b/src/app/shared/api/endpoints/services/administration.service.ts
new file mode 100644
index 0000000..089a14e
--- /dev/null
+++ b/src/app/shared/api/endpoints/services/administration.service.ts
@@ -0,0 +1,135 @@
+/* tslint:disable */
+/* eslint-disable */
+import { Injectable } from '@angular/core';
+import { HttpClient, HttpResponse } from '@angular/common/http';
+import { BaseService } from '../base-service';
+import { ApiConfiguration } from '../api-configuration';
+import { StrictHttpResponse } from '../strict-http-response';
+import { RequestBuilder } from '../request-builder';
+import { Observable } from 'rxjs';
+import { map, filter } from 'rxjs/operators';
+
+import { Right } from '../models/right';
+import { UserInfo } from '../models/user-info';
+
+
+/**
+ * Administration service
+ */
+@Injectable({
+  providedIn: 'root',
+})
+export class AdministrationService extends BaseService {
+  constructor(
+    config: ApiConfiguration,
+    http: HttpClient
+  ) {
+    super(config, http);
+  }
+
+  /**
+   * Path part for operation createUser
+   */
+  static readonly CreateUserPath = '/senslog15/rest/user';
+
+  /**
+   * Create User.
+   *
+   *
+   *
+   * This method provides access to the full `HttpResponse`, allowing access to response headers.
+   * To access only the response body, use `createUser()` instead.
+   *
+   * This method sends `application/json` and handles request body of type `application/json`.
+   */
+  createUser$Response(params: {
+    body: UserInfo
+  }): Observable<StrictHttpResponse<void>> {
+
+    const rb = new RequestBuilder(this.rootUrl, AdministrationService.CreateUserPath, 'post');
+    if (params) {
+      rb.body(params.body, 'application/json');
+    }
+
+    return this.http.request(rb.build({
+      responseType: 'text',
+      accept: '*/*'
+    })).pipe(
+      filter((r: any) => r instanceof HttpResponse),
+      map((r: HttpResponse<any>) => {
+        return (r as HttpResponse<any>).clone({ body: undefined }) as StrictHttpResponse<void>;
+      })
+    );
+  }
+
+  /**
+   * Create User.
+   *
+   *
+   *
+   * This method provides access to only to the response body.
+   * To access the full response (for headers, for example), `createUser$Response()` instead.
+   *
+   * This method sends `application/json` and handles request body of type `application/json`.
+   */
+  createUser(params: {
+    body: UserInfo
+  }): Observable<void> {
+
+    return this.createUser$Response(params).pipe(
+      map((r: StrictHttpResponse<void>) => r.body as void)
+    );
+  }
+
+  /**
+   * Path part for operation getRights
+   */
+  static readonly GetRightsPath = '/senslog15/rest/user/rights';
+
+  /**
+   * Get rights.
+   *
+   *
+   *
+   * This method provides access to the full `HttpResponse`, allowing access to response headers.
+   * To access only the response body, use `getRights()` instead.
+   *
+   * This method doesn't expect any request body.
+   */
+  getRights$Response(params?: {
+  }): Observable<StrictHttpResponse<Array<Right>>> {
+
+    const rb = new RequestBuilder(this.rootUrl, AdministrationService.GetRightsPath, 'get');
+    if (params) {
+    }
+
+    return this.http.request(rb.build({
+      responseType: 'json',
+      accept: 'application/json'
+    })).pipe(
+      filter((r: any) => r instanceof HttpResponse),
+      map((r: HttpResponse<any>) => {
+        return r as StrictHttpResponse<Array<Right>>;
+      })
+    );
+  }
+
+  /**
+   * Get rights.
+   *
+   *
+   *
+   * This method provides access to only to the response body.
+   * To access the full response (for headers, for example), `getRights$Response()` instead.
+   *
+   * This method doesn't expect any request body.
+   */
+  getRights(params?: {
+  }): Observable<Array<Right>> {
+
+    return this.getRights$Response(params).pipe(
+      map((r: StrictHttpResponse<Array<Right>>) => r.body as Array<Right>)
+    );
+  }
+
+}
diff --git a/src/app/shared/api/openapi.yaml b/src/app/shared/api/openapi.yaml
index efbd734..30ee02b 100644
--- a/src/app/shared/api/openapi.yaml
+++ b/src/app/shared/api/openapi.yaml
@@ -25,6 +25,8 @@ tags:
   description: Insert endpoints
 - name: sensors
   description: Sensor service
+- name: administration
+  description: Administration service
 
 paths:
   /senslog15/ControllerServlet:
@@ -65,6 +67,20 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/UserInfo'
+    post:
+      tags:
+        - administration
+      summary: Create User
+      operationId: createUser
+      responses:
+        200:
+          description: created
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/UserInfo'
 
   /senslog1/GroupService:
     get:
@@ -306,8 +322,36 @@ paths:
                   type: array
                   items:
                     $ref: '#/components/schemas/InsertSensor'
+
+  /senslog15/rest/user/rights:
+    get:
+      tags:
+        - administration
+      summary: Get rights
+      operationId: getRights
+      responses:
+        200:
+          description: success
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/Right'
+
+
 components:
   schemas:
+    Right:
+      type: object
+      properties:
+        rightsId:
+          type: integer
+        userRole:
+          type: string
+        note:
+          type: string
+
     InsertUnit:
       type: object
       properties:
diff --git a/src/app/shared/nav-bar/components/nav-bar.component.html b/src/app/shared/nav-bar/components/nav-bar.component.html
index 8956976..6a03d47 100644
--- a/src/app/shared/nav-bar/components/nav-bar.component.html
+++ b/src/app/shared/nav-bar/components/nav-bar.component.html
@@ -11,7 +11,7 @@
               <a class="nav-link" [routerLink]="['/dashboard']"><h2>Dashboard</h2></a>
             </li>
             <li *ngIf="loggedUser?.userInfo?.rightsId == 0" class="nav-item">
-              <a class="nav-link" [routerLink]="['/administration']"><h2>Administration</h2></a>
+              <a class="nav-link" (click)="addUser()"><h2>Add user</h2></a>
             </li>
           </ul>
           <a class="navbar-brand" href="/">
@@ -31,3 +31,5 @@
     </nav>
   </div>
 </div>
+
+<app-user-insert-popup *ngIf="showAddUserPopup" [(isVisible)]="showAddUserPopup"></app-user-insert-popup>
diff --git a/src/app/shared/nav-bar/components/nav-bar.component.ts b/src/app/shared/nav-bar/components/nav-bar.component.ts
index a3349ab..10958ea 100644
--- a/src/app/shared/nav-bar/components/nav-bar.component.ts
+++ b/src/app/shared/nav-bar/components/nav-bar.component.ts
@@ -2,6 +2,7 @@ import {Component, OnDestroy, OnInit} from '@angular/core';
 import {AuthService} from '../../../auth/services/auth.service';
 import {User} from '../../../auth/models/user';
 import {Subscription} from 'rxjs';
+import {Right} from '../../api/endpoints/models/right';
 
 @Component({
   selector: 'app-nav-bar',
@@ -12,6 +13,8 @@ export class NavBarComponent implements OnInit, OnDestroy {
 
   loggedUser: User;
   subscription: Subscription[] = [];
+  showAddUserPopup = false;
+  rights: Right[];
   constructor(
     private authService: AuthService
   ) {
@@ -36,4 +39,8 @@ export class NavBarComponent implements OnInit, OnDestroy {
   ngOnDestroy(): void {
     this.subscription.forEach(subs => subs.unsubscribe());
   }
+
+  addUser() {
+    this.showAddUserPopup = true;
+  }
 }
diff --git a/src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.html b/src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.html
new file mode 100644
index 0000000..2acf842
--- /dev/null
+++ b/src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.html
@@ -0,0 +1,57 @@
+<p-dialog [visible]="isVisible" [modal]="true" [closable]="false" [draggable]="false" header="Add user"
+          [style]="{width: '50vw'}" [baseZIndex]="10000">
+
+  <form [formGroup]="insertForm">
+    <div class="input-group form-group">
+      <div class="input-group form-group">
+        <div class="input-group-prepend">
+          <span class="input-group-text">Username</span>
+        </div>
+        <input type="text" formControlName="userName" class="form-control" id="username" placeholder="Username"/>
+      </div>
+      <div class="input-group form-group">
+        <div class="input-group-prepend">
+          <span class="input-group-text">User password</span>
+        </div>
+        <input type="text" formControlName="userPass" class="form-control" id="password"
+               placeholder="Password"/>
+      </div>
+      <div class="input-group form-group">
+        <div class="input-group-prepend">
+          <span class="input-group-text">User real name</span>
+        </div>
+        <input type="text" formControlName="userRealName" class="form-control" id="userRealName"
+               placeholder="User real name"/>
+      </div>
+<!--      <div class="input-group form-group">
+        <div class="input-group-prepend">
+          <span class="input-group-text">Group</span>
+        </div>
+        <select formControlName="groups" id="groups">
+          <option *ngFor="let group of groups; let i = index" [value]="groups[i].id">
+            {{group[i]?.group_name}}
+          </option>
+        </select>
+      </div>-->
+      <div class="input-group form-group">
+        <div class="input-group-prepend">
+          <span class="input-group-text">Role</span>
+        </div>
+        <select formControlName="rights" id="rights">
+          <option *ngFor="let right of rights; let i = index" [value]="rights[i].rightsId">
+            {{rights[i].userRole}}
+          </option>
+        </select>
+      </div>
+    </div>
+  </form>
+
+  <p-footer>
+    <div class="row justify-content-end align-items-center">
+      <div>
+        <p-button icon="pi pi-check" (click)="saveUser()" type="submit" label="Save" class="pr-2"></p-button>
+        <p-button icon="pi pi-times" (click)="close()" label="Close" class="pr-2"></p-button>
+      </div>
+    </div>
+  </p-footer>
+</p-dialog>
diff --git a/src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.scss b/src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.ts b/src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.ts
new file mode 100644
index 0000000..1b3f91b
--- /dev/null
+++ b/src/app/shared/nav-bar/components/user-insert-popup/user-insert-popup.component.ts
@@ -0,0 +1,84 @@
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+import {map, tap} from 'rxjs/operators';
+import {GroupService} from '../../../api/endpoints/services/group.service';
+import {Group} from '../../../api/endpoints/models/group';
+import {AdministrationService} from '../../../api/endpoints/services/administration.service';
+import {Right} from '../../../api/endpoints/models/right';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+import {HttpResponse} from '@angular/common/http';
+
+@Component({
+  selector: 'app-user-insert-popup',
+  templateUrl: './user-insert-popup.component.html',
+  styleUrls: ['./user-insert-popup.component.scss']
+})
+export class UserInsertPopupComponent implements OnInit {
+
+  groups: Group[];
+  rights: Right[];
+  insertForm: FormGroup;
+  @Input() isVisible;
+  @Output() isVisibleChange: EventEmitter<boolean> = new EventEmitter<boolean>();
+
+  constructor(
+    private formBuilder: FormBuilder,
+    private groupService: GroupService,
+    private administrationService: AdministrationService
+  ) {
+    this.initForm();
+    // TODO this.getGroups();
+  }
+
+  ngOnInit(): void {
+  }
+
+  getGroups() {
+    this.groupService.getGroups({Operation: 'GetGroups'}).pipe(
+      tap(data => this.groups = data)
+    ).subscribe();
+    console.log(this.groups);
+  }
+
+  getRights() {
+    this.administrationService.getRights().pipe(
+      tap(data => this.rights = data)
+    ).subscribe();
+  }
+
+  close() {
+    this.isVisibleChange.emit(false);
+  }
+
+  saveUser() {
+    if (this.insertForm.valid) {
+      this.administrationService.createUser$Response({body: {
+        userPass: this.insertForm.controls.userPass.value,
+        userName: this.insertForm.controls.userName.value,
+        rightsId: this.insertForm.controls.rights.value,
+        userRealName: this.insertForm.controls.userRealName.value,
+          // TODO
+        groupId: 2
+        }
+      }).pipe(
+        map((response: HttpResponse<any>) => {
+          if (response.status === 200) { // Accepts only 200 status response, due to API Definition
+            this.close();
+          } else {
+            console.log('ERROR');
+          }
+        })
+      ).toPromise();
+    }
+  }
+
+  initForm() {
+    this.getRights();
+    this.insertForm = this.formBuilder.group({
+      userName: ['', Validators.required],
+      userPass: ['', Validators.required],
+      userRealName: ['', Validators.required],
+      // TODO groups: ['', Validators.required],
+      rights: ['', Validators.required]
+    });
+  }
+}
diff --git a/src/app/shared/nav-bar/nav-bar.module.ts b/src/app/shared/nav-bar/nav-bar.module.ts
index ebd34f2..5553452 100644
--- a/src/app/shared/nav-bar/nav-bar.module.ts
+++ b/src/app/shared/nav-bar/nav-bar.module.ts
@@ -3,17 +3,22 @@ import {CommonModule} from '@angular/common';
 import {NavBarComponent} from './components/nav-bar.component';
 import {RouterModule} from '@angular/router';
 import {ButtonModule} from 'primeng/button';
+import { UserInsertPopupComponent } from './components/user-insert-popup/user-insert-popup.component';
+import {DialogModule} from 'primeng/dialog';
+import {ReactiveFormsModule} from '@angular/forms';
 
 
 @NgModule({
-  declarations: [NavBarComponent],
+  declarations: [NavBarComponent, UserInsertPopupComponent],
   exports: [
     NavBarComponent
   ],
   imports: [
     CommonModule,
     RouterModule,
-    ButtonModule
+    ButtonModule,
+    DialogModule,
+    ReactiveFormsModule
   ]
 })
 export class NavBarModule {
