From 226b4bff2e8515fcfd7f3a5b9bdbc5c8c8962221 Mon Sep 17 00:00:00 2001 From: FlayInAHook Date: Tue, 15 Dec 2020 19:43:20 +0100 Subject: [PATCH] WIP Usermanagement --- src/app/app.module.ts | 14 + .../admin-data-page.component.html | 367 ++++++++++-------- .../admin-data-page.component.ts | 349 +++++++---------- .../dialogs/add/add.dialog.component.ts | 41 ++ src/app/components/dialogs/add/add.dialog.css | 19 + .../components/dialogs/add/add.dialog.html | 31 ++ .../dialogs/delete/delete.dialog.component.ts | 24 ++ .../dialogs/delete/delete.dialog.css | 8 + .../dialogs/delete/delete.dialog.html | 14 + .../dialogs/edit/edit.dialog.component.ts | 53 +++ .../components/dialogs/edit/edit.dialog.css | 19 + .../components/dialogs/edit/edit.dialog.html | 53 +++ .../form-select-search.component.html | 9 + .../form-select-search.component.scss | 40 ++ .../form-select-search.component.ts | 134 +++++++ src/app/models/user.ts | 3 +- src/app/pages/profile/profile.component.html | 3 + src/app/pages/profile/profile.component.ts | 2 +- src/app/services/user.service.ts | 32 +- 19 files changed, 844 insertions(+), 371 deletions(-) create mode 100644 src/app/components/dialogs/add/add.dialog.component.ts create mode 100644 src/app/components/dialogs/add/add.dialog.css create mode 100644 src/app/components/dialogs/add/add.dialog.html create mode 100644 src/app/components/dialogs/delete/delete.dialog.component.ts create mode 100644 src/app/components/dialogs/delete/delete.dialog.css create mode 100644 src/app/components/dialogs/delete/delete.dialog.html create mode 100644 src/app/components/dialogs/edit/edit.dialog.component.ts create mode 100644 src/app/components/dialogs/edit/edit.dialog.css create mode 100644 src/app/components/dialogs/edit/edit.dialog.html create mode 100644 src/app/components/from-select-search/form-select-search.component.html create mode 100644 src/app/components/from-select-search/form-select-search.component.scss create mode 100644 src/app/components/from-select-search/form-select-search.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index fa0b764..da275f9 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -66,6 +66,7 @@ import { SelectObjectDialogComponent } from './components/select-object-dialog/s import { AutocompleteSelectComponent } from './components/autocomplete-select/autocomplete-select.component'; import { LendingStationComponent } from './pages/dataPages/lending-station/lending-station.component'; import { ProfileComponent } from './pages/profile/profile.component'; +import { AdminDataPageComponent} from './components/admin-data-page/admin-data-page.component'; import { ErrorSnackbarComponent, SnackbarDialog, @@ -86,6 +87,10 @@ import { BikeEventsComponent } from './pages/tables/bike-events/bike-events.comp import { BikeEventTypesComponent } from './pages/tables/bike-event-types/bike-event-types.component'; import { WorkshopTypesComponent } from './pages/tables/workshop-types/workshop-types.component'; import { FilterRowComponent } from './components/tableComponents/filter-row/filter-row.component'; +import {DeleteDialogComponent} from './components/dialogs/delete/delete.dialog.component'; +import {AddDialogComponent} from './components/dialogs/add/add.dialog.component'; +import {EditDialogComponent} from './components/dialogs/edit/edit.dialog.component'; + @NgModule({ declarations: [ @@ -112,6 +117,10 @@ import { FilterRowComponent } from './components/tableComponents/filter-row/filt SelectObjectDialogComponent, AutocompleteSelectComponent, LendingStationComponent, + AddDialogComponent, + EditDialogComponent, + DeleteDialogComponent, + AdminDataPageComponent, ProfileComponent, ErrorSnackbarComponent, SnackbarDialog, @@ -168,6 +177,11 @@ import { FilterRowComponent } from './components/tableComponents/filter-row/filt MatNativeDateModule, MatChipsModule, ], + entryComponents: [ + AddDialogComponent, + EditDialogComponent, + DeleteDialogComponent + ], providers: [ NavService, MatNativeDateModule, diff --git a/src/app/components/admin-data-page/admin-data-page.component.html b/src/app/components/admin-data-page/admin-data-page.component.html index d8a50f2..efc6b9a 100644 --- a/src/app/components/admin-data-page/admin-data-page.component.html +++ b/src/app/components/admin-data-page/admin-data-page.component.html @@ -1,171 +1,216 @@ - -
-

Seite konnte nicht gefunden werden :(

+ + + Admin Table + + Reload data: + + + +
+ +
+ + + +
+ + + + + + Name + {{row.name}} + + + + E-Mail + {{row.email}} + + + + Passwort + {{row.password}} + + + + Rollen + {{row.roles}} + + + + + + + + + + + + + + + + + + + +
-
-

- {{ getHeadline !== undefined ? getHeadline(data) : data[headlineDataPath] }} - {{ headlineIconName }} -

- - - -

{{ object.title }}

+ + + + + + + \ No newline at end of file diff --git a/src/app/components/admin-data-page/admin-data-page.component.ts b/src/app/components/admin-data-page/admin-data-page.component.ts index 5f309ee..ea60eef 100644 --- a/src/app/components/admin-data-page/admin-data-page.component.ts +++ b/src/app/components/admin-data-page/admin-data-page.component.ts @@ -1,246 +1,187 @@ +import { HttpClient } from '@angular/common/http'; import { Component, + ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, + ViewChild, } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; -import { ActivatedRoute } from '@angular/router'; -import { deepen } from '../../helperFunctions/deepenObject'; -import { flatten } from '../../helperFunctions/flattenObject'; -import { SchemaService } from '../../services/schema.service'; -import { SelectObjectDialogComponent } from '../select-object-dialog/select-object-dialog.component'; - -interface PropertyTypeInfo { - dataPath: string; - translation: string; - acceptedForUpdating?: boolean; - requiredForUpdating?: boolean; - required?: boolean; - type?: string; -} - -interface PropertyGroupInfo { - type: string; - title: string; - properties: PropertyTypeInfo[]; -} -interface ReferenceTableInfo { - type: string; - title: string; - dataPath: string; - dataService: any; - columnInfo: PropertyTypeInfo[]; - nameToShowInSelection: any; - propertyNameOfUpdateInput: string; - referenceIds: Array; -} +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +import { fromEvent } from 'rxjs'; +import { first } from 'rxjs/operators'; +import { User } from '../../models/user'; +import {UserService} from '../../services/user.service'; +import {DeleteDialogComponent} from '../../components/dialogs/delete/delete.dialog.component'; +import {AddDialogComponent} from '../../components/dialogs/add/add.dialog.component'; +import {EditDialogComponent} from '../../components/dialogs/edit/edit.dialog.component'; + +import {deepCopy} from '../../helperFunctions/deepCopy'; @Component({ selector: 'app-admin-data-page', templateUrl: './admin-data-page.component.html', - styleUrls: ['./admindata-page.component.scss'], + styleUrls: ['./admin-data-page.component.scss'], }) -export class DataPageComponent implements OnInit, OnDestroy { - @Input() - propertiesInfo: Array = []; - - @Input() - dataService: any; - - /** specifies which property should be shown in the headline */ - @Input() - headlineDataPath: string; - /** specifies which string should be shown in the headline. If this is provided headlineDataPath is ignored*/ - @Input() - getHeadline: (any) => string; - @Input() - headlineIconName: string = 'help_outline'; - @Input() - pageDataGQLType: string; - @Input() - pageDataGQLUpdateInputType: string; - @Input() - propertyNameOfUpdateInput: string; - - relockingInterval = null; - @Input() - relockingIntervalDuration = 1000 * 60 * 1; - - @Output() lockEvent = new EventEmitter(); - @Output() saveEvent = new EventEmitter(); - @Output() cancelEvent = new EventEmitter(); - - id: string; - data: any = null; - isLoading: boolean = false; - isSavingOrLocking: boolean = false; - - propertyValidity = {}; - - constructor( - private route: ActivatedRoute, - private schemaService: SchemaService, - public dialog: MatDialog - ) {} - - ngOnInit(): void { - this.addPropertiesFromGQLSchemaToObject(this.propertiesInfo); - this.id = this.route.snapshot.paramMap.get('id'); - this.reloadPageData(); - this.dataService.pageData.subscribe((data) => { - if (data == null) { - this.data = null; - } else if (this.data?.isLockedByMe && data?.isLockedByMe) { - // dont overwrite data when in edit mode and relock is performed - return; - } else { - this.data = flatten(data); +export class AdminDataPageComponent implements OnInit { + + + displayedColumns = ['name', 'email', 'password', 'roles', 'actions']; + dataSource : MatTableDataSource; + index: number; + id: number; + + constructor(public httpClient: HttpClient, + public dialog: MatDialog, + private userService: UserService) {} + + @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator; + @ViewChild(MatSort, {static: true}) sort: MatSort; + @ViewChild('filter', {static: true}) filter: ElementRef; + + ngOnInit() { + this.loadData(); + } + + refresh() { + this.loadData(); + } + + + addNew() { + const dialogRef = this.dialog.open(AddDialogComponent, { + data: {user: User } + }); + + dialogRef.afterClosed().subscribe(result => { + if (result === 1) { + + + this.dataSource.data.push(this.userService.getDialogData()); + + this.refreshTable(); } }); - this.dataService.isLoadingPageData.subscribe( - (isLoading) => (this.isLoading = isLoading) - ); - this.dataService.loadingRowIds.subscribe((loadingRowIds) => { - this.isSavingOrLocking = loadingRowIds.includes(this.id); + } + + startEdit(user : User) { + const dialogRef = this.dialog.open(EditDialogComponent, { + data: deepCopy(user) }); - this.relockingInterval = setInterval(() => { - if (this.data?.isLockedByMe) { - this.lock(); + dialogRef.afterClosed().subscribe(result => { + if (result === 1) { + console.log("editing done"); + + const foundIndex = this.dataSource.data.findIndex(x => x.email === this.userService.getDialogData().email); + + this.dataSource.data[foundIndex] = this.userService.getDialogData(); + + this.refreshTable(); } - }, this.relockingIntervalDuration); + }); } - ngOnDestroy() { - clearInterval(this.relockingInterval); - } + deleteItem(i: number, id: number, title: string, state: string, url: string) { + this.index = i; + this.id = id; + const dialogRef = this.dialog.open(DeleteDialogComponent, { + data: {id: id, title: title, state: state, url: url} + }); - addPropertiesFromGQLSchemaToObject(infoObject: any) { - for (const prop of infoObject) { - if (prop.type === 'Link') { - continue; - } - if (prop.type === 'Group') { - this.addPropertiesFromGQLSchemaToObject(prop.properties); - } else if (prop.type === 'ReferenceTable') { - prop.tableDataGQLType = - prop.tableDataGQLType || - this.schemaService.getTypeInformation( - this.pageDataGQLType, - prop.dataPath - ).type; - if (!prop.type) { - console.error( - "Didn't found type for: " + - prop.dataPath + - ' on ' + - this.pageDataGQLType - ); - } - prop.referenceIds = []; - } else { - const typeInformation = this.schemaService.getTypeInformation( - this.pageDataGQLType, - prop.dataPath - ); - prop.type = prop.type || typeInformation.type; - prop.list = typeInformation.isList; - if (!prop.type) { - console.error( - "Didn't found type for: " + - prop.dataPath + - ' on ' + - this.pageDataGQLType - ); - } - prop.required = - prop.required != null ? prop.required : typeInformation.isRequired; - - const updateTypeInformation = this.schemaService.getTypeInformation( - this.pageDataGQLUpdateInputType, - prop.dataPath - ); - prop.acceptedForUpdating = - prop.acceptedForUpdating != null - ? prop.acceptedForUpdating - : updateTypeInformation.isPartOfType; - - prop.requiredForUpdating = - prop.requiredForUpdating != null - ? prop.requiredForUpdating - : prop.required || typeInformation.isRequired; + dialogRef.afterClosed().subscribe(result => { + if (result === 1) { + const foundIndex = this.dataSource.data.findIndex(x => x.id === this.id); + + this.dataSource.data.splice(foundIndex, 1); + this.refreshTable(); } - } + }); } - lock() { - this.lockEvent.emit(deepen(this.data)); + + private refreshTable() { + //this.paginator._changePageSize(this.paginator.pageSize); + this.dataSource._updateChangeSubscription(); } - validityChange(propName: string, isValid: Event) { - this.propertyValidity[propName] = isValid; + public loadData() { + this.userService.getAllUsers().pipe(first()).subscribe((data: User[]) => { + this.dataSource = new MatTableDataSource(data); + }); + fromEvent(this.filter.nativeElement, 'keyup') + // .debounceTime(150) + // .distinctUntilChanged() + .subscribe(() => { + if (!this.dataSource) { + return; + } + this.dataSource.filter = this.filter.nativeElement.value; + }); } - countUnvalidProperties() { - let unvalidFieldsCount = 0; - for (const prop in this.propertyValidity) { - if (!this.propertyValidity[prop]) { - unvalidFieldsCount++; - } - } - return unvalidFieldsCount; + ngAfterViewInit() { + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; } - save() { - this.saveEvent.emit( - this.schemaService.filterObject( - this.pageDataGQLUpdateInputType, - deepen(this.data) - ) - ); + orderData(id: string, start?: "asc" | "desc") { + const matSort = this.dataSource.sort; + const disableClear = false; + + matSort.sort({ id: null, start, disableClear }); + matSort.sort({ id, start, disableClear }); + + this.dataSource.sort = this.sort; } - cancel() { - this.cancelEvent.emit(deepen(this.data)); + + private load() { + console.log("trying to load"); + } - openSelectObjectDialog(object: any) { - const dialogRef = this.dialog.open(SelectObjectDialogComponent, { - width: 'auto', - autoFocus: false, - data: { - nameToShowInSelection: object.nameToShowInSelection, - currentlySelectedObjectId: object.currentlySelectedObjectId(this.data), - possibleObjects: object.possibleObjects, + delete(user: User) { + let ownPassword : string; + this.userService.deleteUser(user.email, ownPassword) + .pipe(first()) + .subscribe( + data => { + //this.loadAllObjects(); }, - }); - dialogRef.afterClosed().subscribe((selectedObject) => { - if (selectedObject) { - this.data[object.propertyNameOfReferenceId] = selectedObject.id; - const newObjectFlattened = flatten(selectedObject); - for (const newProperty in newObjectFlattened) { - this.data[object.propertyPrefixToOverwrite + '.' + newProperty] = - newObjectFlattened[newProperty]; - } - } else if (selectedObject === null) { - this.data[object.propertyNameOfReferenceId] = null; - for (const prop in this.data) { - if (prop.startsWith(object.propertyPrefixToOverwrite)) { - this.data[prop] = null; - } - } + error => { + } - }); + ); } - addReferenceIdsToObject(ids: string[], object) { - this.data[object.propertyNameOfUpdateInput] = ids; + edit(user: User) { + let ownPassword : string; + this.userService.updateUser(user, ownPassword) + .pipe(first()) + .subscribe( + data => { + //this.loadAllObjects(); + }, + error => { + + } + ); } - reloadPageData() { - this.dataService.loadPageData({ id: this.id }); - } + /*findActualData(_id: string) { + for (let data of this.actualData) { + if (data._id === _id) { + return data; + } + } + } */ } + + + diff --git a/src/app/components/dialogs/add/add.dialog.component.ts b/src/app/components/dialogs/add/add.dialog.component.ts new file mode 100644 index 0000000..61e14cb --- /dev/null +++ b/src/app/components/dialogs/add/add.dialog.component.ts @@ -0,0 +1,41 @@ +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import {Component, Inject} from '@angular/core'; +import {UserService} from '../../../services/user.service'; +import {FormControl, Validators} from '@angular/forms'; +import {User} from '../../../models/user'; + +@Component({ + selector: 'app-add.dialog', + templateUrl: '../../dialogs/add/add.dialog.html', + styleUrls: ['../../dialogs/add/add.dialog.css'] +}) + +export class AddDialogComponent { + constructor(public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: User, + public userService: UserService) { } + + formControl = new FormControl('', [ + Validators.required + // Validators.email, + ]); + + getErrorMessage() { + return this.formControl.hasError('required') ? 'Required field' : + this.formControl.hasError('email') ? 'Not a valid email' : + ''; + } + + submit() { + // emppty stuff + } + + onNoClick(): void { + this.dialogRef.close(); + } + + public confirmAdd(): void { + this.userService.addUser(this.data); + //this.dataService.addIssue(this.data); + } +} diff --git a/src/app/components/dialogs/add/add.dialog.css b/src/app/components/dialogs/add/add.dialog.css new file mode 100644 index 0000000..eb484a9 --- /dev/null +++ b/src/app/components/dialogs/add/add.dialog.css @@ -0,0 +1,19 @@ +.container { + display: flex; + flex-direction: column; + min-width: 450px; +} + +.container > * { + width: 100%; +} + +.form { + display: flex; + padding-top: 6px; +} + +.mat-form-field { + font-size: 16px; + flex-grow: 1; +} diff --git a/src/app/components/dialogs/add/add.dialog.html b/src/app/components/dialogs/add/add.dialog.html new file mode 100644 index 0000000..58e7721 --- /dev/null +++ b/src/app/components/dialogs/add/add.dialog.html @@ -0,0 +1,31 @@ +
+

Add new Issue

+ +
+ +
+ + + {{getErrorMessage()}} + +
+ +
+ + + {{getErrorMessage()}} + +
+ +
+ + + +
+ +
+ + +
+
+
diff --git a/src/app/components/dialogs/delete/delete.dialog.component.ts b/src/app/components/dialogs/delete/delete.dialog.component.ts new file mode 100644 index 0000000..97aadfa --- /dev/null +++ b/src/app/components/dialogs/delete/delete.dialog.component.ts @@ -0,0 +1,24 @@ +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import {Component, Inject} from '@angular/core'; +import {UserService} from '../../../services/user.service'; + + +@Component({ + selector: 'app-delete.dialog', + templateUrl: '../../dialogs/delete/delete.dialog.html', + styleUrls: ['../../dialogs/delete/delete.dialog.css'] +}) +export class DeleteDialogComponent { + + constructor(public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, public userService: UserService) { } + + onNoClick(): void { + this.dialogRef.close(); + } + + confirmDelete(): void { + this.userService.deleteUser(this.data.mail, this.data.ownPassword); + //this.dataService.deleteIssue(this.data.id); + } +} diff --git a/src/app/components/dialogs/delete/delete.dialog.css b/src/app/components/dialogs/delete/delete.dialog.css new file mode 100644 index 0000000..93a17ae --- /dev/null +++ b/src/app/components/dialogs/delete/delete.dialog.css @@ -0,0 +1,8 @@ +.container { + display: flex; + flex-direction: column; +} + +.container > * { + width: 100%; +} diff --git a/src/app/components/dialogs/delete/delete.dialog.html b/src/app/components/dialogs/delete/delete.dialog.html new file mode 100644 index 0000000..18f2d1f --- /dev/null +++ b/src/app/components/dialogs/delete/delete.dialog.html @@ -0,0 +1,14 @@ +
+

Are you sure?

+
+ Name: {{data.name}} +

+ E-Mail: {{data.email}} +

+
+ +
+ + +
+
diff --git a/src/app/components/dialogs/edit/edit.dialog.component.ts b/src/app/components/dialogs/edit/edit.dialog.component.ts new file mode 100644 index 0000000..ab75ced --- /dev/null +++ b/src/app/components/dialogs/edit/edit.dialog.component.ts @@ -0,0 +1,53 @@ +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import {Component, Inject} from '@angular/core'; +import {UserService} from '../../../services/user.service'; +import {FormControl, Validators} from '@angular/forms'; +import { first } from 'rxjs/operators'; +import { SnackBarService } from 'src/app/services/snackbar.service'; + +@Component({ + selector: 'app-baza.dialog', + templateUrl: '../../dialogs/edit/edit.dialog.html', + styleUrls: ['../../dialogs/edit/edit.dialog.css'] +}) +export class EditDialogComponent { + + hide = true; + + constructor(public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, public userService: UserService, public snackbarService : SnackBarService) { } + + formControl = new FormControl('', [ + Validators.required + // Validators.email, + ]); + + getErrorMessage() { + return this.formControl.hasError('required') ? 'Required field' : + this.formControl.hasError('email') ? 'Not a valid email' : + ''; + } + + submit() { + // emppty stuff + } + + onNoClick(): void { + this.dialogRef.close(); + } + + stopEdit(): void { + this.data.roles = []; + this.userService.updateUser(this.data).pipe(first()) + .subscribe( + data => { + this.snackbarService.openSnackBar("Der Nutzer wurde erfolgreich verändert!"); + //this.loadAllObjects(); + }, + error => { + console.log("Eroor while editing: " + JSON.stringify(error)); + this.snackbarService.openSnackBar(error, "Ok", true); + } + ); + } +} diff --git a/src/app/components/dialogs/edit/edit.dialog.css b/src/app/components/dialogs/edit/edit.dialog.css new file mode 100644 index 0000000..eb484a9 --- /dev/null +++ b/src/app/components/dialogs/edit/edit.dialog.css @@ -0,0 +1,19 @@ +.container { + display: flex; + flex-direction: column; + min-width: 450px; +} + +.container > * { + width: 100%; +} + +.form { + display: flex; + padding-top: 6px; +} + +.mat-form-field { + font-size: 16px; + flex-grow: 1; +} diff --git a/src/app/components/dialogs/edit/edit.dialog.html b/src/app/components/dialogs/edit/edit.dialog.html new file mode 100644 index 0000000..49cf5f1 --- /dev/null +++ b/src/app/components/dialogs/edit/edit.dialog.html @@ -0,0 +1,53 @@ +
+

Issue id: {{data.id}}

+ +
+ +
+ + + {{getErrorMessage()}} + +
+ +
+ + + {{getErrorMessage()}} + +
+ +
+ + + +
+ + +
+ + Eigenes Passwort + + + +
+ +
+ + +
+
+
diff --git a/src/app/components/from-select-search/form-select-search.component.html b/src/app/components/from-select-search/form-select-search.component.html new file mode 100644 index 0000000..71501a7 --- /dev/null +++ b/src/app/components/from-select-search/form-select-search.component.html @@ -0,0 +1,9 @@ + + + {{label}} + + + + {{risk.NAME}} + + \ No newline at end of file diff --git a/src/app/components/from-select-search/form-select-search.component.scss b/src/app/components/from-select-search/form-select-search.component.scss new file mode 100644 index 0000000..ca2b881 --- /dev/null +++ b/src/app/components/from-select-search/form-select-search.component.scss @@ -0,0 +1,40 @@ +.mat-stepper-horizontal { + margin-top: 8px; + } + + .mat-form-field { + margin-top: 16px; + } + + + .right-align { + text-align: right; + } + + input.right-align::-webkit-outer-spin-button, + input.right-align::-webkit-inner-spin-button { + display: none; + } + + input.right-align { + -moz-appearance: textfield; + } + + .flex { + display: flex; + } + + .form-field-less-top-margin{ + margin-top: 0.5em; + } + + .anti-margin{ + margin-left: 0; + margin-right: 0; + } + + .mat-form-field{ + width: 100%; + } + + \ No newline at end of file diff --git a/src/app/components/from-select-search/form-select-search.component.ts b/src/app/components/from-select-search/form-select-search.component.ts new file mode 100644 index 0000000..b11ffd2 --- /dev/null +++ b/src/app/components/from-select-search/form-select-search.component.ts @@ -0,0 +1,134 @@ +import { Component, OnInit, OnDestroy, Input, OnChanges, SimpleChanges } from "@angular/core"; +import { Subscription, ReplaySubject, Subject } from "rxjs"; +import { FormGroup, FormControl, FormBuilder } from '@angular/forms'; +import { takeUntil } from 'rxjs/operators'; + + +@Component({ selector: "select-search", templateUrl: "form-select-search.component.html", styleUrls: ["./form-select-search.component.scss"] }) +export class FormSelectSearchComponent implements OnInit, OnDestroy, OnChanges { + + + //@Input() group: FormGroup; + //@Input() controlName: string; + @Input() formCtrl: FormControl; + + @Input() data: any[]; + @Input() preSelectedData: any[]; + @Input() label: string; + @Input() multiple: boolean; + + selectedOptions: any[] = []; + + public filteredInterfacesBMulti: ReplaySubject = new ReplaySubject(1); + + + public searchCtrl: FormControl = new FormControl(); + + + constructor(private _formBuilder: FormBuilder) { + + } + + ngOnChanges(changes: SimpleChanges) { + // only run when property "data" changed + + if (changes['data']) { + + if (this.preSelectedData !== undefined){ + //console.log( this.label + " is not undefined :D"); + //console.log(this.label + " preselected: " + this.preSelectedData); + //console.log(JSON.stringify(this.preSelectedData)) + this.riskListGeneratorB(this.preSelectedData); + console.log(this.label + " selected options: "+ JSON.stringify(this.selectedOptions) + " all options: " + JSON.stringify(this.data)); + } + + //this.listenInterfacesSearchable(); + this.filterInterfacesBMulti(); + } + if (changes['preSelectedData']) { + + if (this.preSelectedData !== undefined){ + /*console.log(this.label + " preselect data change"); + console.log(this.label + " preselected: " + this.preSelectedData); + console.log(JSON.stringify(this.preSelectedData))*/ + this.riskListGeneratorB(this.preSelectedData); + console.log(this.label + " selected options: "+ JSON.stringify(this.selectedOptions) + " all options: " + JSON.stringify(this.data)); + } + + //this.listenInterfacesSearchable(); + this.filterInterfacesBMulti(); + } + } + + ngOnInit() { + //this.group.addControl('searchCtrl', this.searchCtrl); + //this.formCtrl = this.group[this.controlName]; + if (this.preSelectedData !== undefined){ + /*console.log("preselected is not undefined :D"); + console.log("preselected: " + this.preSelectedData);*/ + this.riskListGeneratorB(this.preSelectedData); + console.log("selected options: "+ JSON.stringify(this.selectedOptions) + " all options: " + JSON.stringify(this.data)); + } + + this.listenInterfacesSearchable(); + } + + private listenInterfacesSearchable(){ + this.filteredInterfacesBMulti.next(this.data.slice()); + + this.searchCtrl.valueChanges + .pipe(takeUntil(this._onDestroy)) + .subscribe(() => { + this.filterInterfacesBMulti(); + }); + + } + + private _onDestroy = new Subject(); + + ngOnDestroy() { + this._onDestroy.next(); + this._onDestroy.complete(); + } + + + private filterInterfacesBMulti() { + if (!this.data) { + return; + } + // get the search keyword + let search = this.searchCtrl.value; + if (!search) { + this.filteredInterfacesBMulti.next(this.data.slice()); + return; + } else { + search = search.toLowerCase(); + } + // filter the banks + this.filteredInterfacesBMulti.next( + this.data.filter(interf => interf.NAME.toLowerCase().indexOf(search) > -1) + ); + } + + + + private riskListGeneratorB(risks: any[]) { + for (let risk of risks) { + for (let riskItem of this.data) { + if (risk._id === riskItem._id) { + console.log(this.label + " added id actual data: " + risk._id + " id background data: " + riskItem._id); + if (this.multiple === undefined){ + this.selectedOptions = riskItem; + console.log("set instead of add"); + } else if (this.selectedOptions.find(e => e._id === risk._id) == undefined){ // only add it to the list if its not added already + this.selectedOptions.push(riskItem); + } + + } + } + } + } + + + +} diff --git a/src/app/models/user.ts b/src/app/models/user.ts index 5381ae1..4a9881e 100644 --- a/src/app/models/user.ts +++ b/src/app/models/user.ts @@ -10,7 +10,8 @@ export class User { email: string; own_password: string; password: string; + roles: string[]; attributes : { - profile_url: string; + profile_url?: string; } } \ No newline at end of file diff --git a/src/app/pages/profile/profile.component.html b/src/app/pages/profile/profile.component.html index 7720d6c..191c9c2 100644 --- a/src/app/pages/profile/profile.component.html +++ b/src/app/pages/profile/profile.component.html @@ -87,6 +87,9 @@
+ +