Merge remote-tracking branch 'origin/master'

pull/6/head
Max Ehrlicher-Schmidt 4 years ago
commit a00dd22615

@ -62,6 +62,8 @@ import { EquipmentComponent } from './pages/tables/equipment/equipment.component
import { TimeFramesComponent } from './pages/tables/time-frames/time-frames.component'; import { TimeFramesComponent } from './pages/tables/time-frames/time-frames.component';
import { NumberRangeCellComponent } from './components/tableComponents/number-range-cell/number-range-cell.component'; import { NumberRangeCellComponent } from './components/tableComponents/number-range-cell/number-range-cell.component';
import { DateRangeCellComponent } from './components/tableComponents/date-range-cell/date-range-cell.component'; import { DateRangeCellComponent } from './components/tableComponents/date-range-cell/date-range-cell.component';
import { SelectObjectDialogComponent } from './components/tableComponents/select-object-dialog/select-object-dialog.component';
import { AutocompleteSelectComponent } from './components/autocomplete-select/autocomplete-select.component';
@ -88,6 +90,8 @@ import { DateRangeCellComponent } from './components/tableComponents/date-range-
TimeFramesComponent, TimeFramesComponent,
NumberRangeCellComponent, NumberRangeCellComponent,
DateRangeCellComponent, DateRangeCellComponent,
SelectObjectDialogComponent,
AutocompleteSelectComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

@ -0,0 +1,21 @@
<form [formGroup]="addForm">
<mat-form-field>
<input
type="text"
matInput
#trigger="matAutocompleteTrigger"
placeholder="Objekt suchen"
formControlName="addGroup"
[matAutocomplete]="autoGroup"
/>
<mat-autocomplete #autoGroup="matAutocomplete" panelWidth="auto">
<mat-option
*ngFor="let object of filteredPossibleObjects"
[value]="nameToShowInSelection(object)"
(click)="onOptionClicked($event, object, trigger)"
>
{{ nameToShowInSelection(object) }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>

@ -0,0 +1,97 @@
import {
Component,
EventEmitter,
Input,
OnInit,
Output,
ViewChild,
} from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
@Component({
selector: 'app-autocomplete-select',
templateUrl: './autocomplete-select.component.html',
styleUrls: ['./autocomplete-select.component.scss'],
})
export class AutocompleteSelectComponent implements OnInit {
@Input()
set possibleObjects(objects: any[]) {
this._possibleObjects = objects;
this.filterPossibleObjects();
}
get possibleObjects(): any[] {
return this._possibleObjects;
}
_possibleObjects: any[];
@Input()
set idsOfObjectsToHide(value) {
this._idsOfObjectsToHide = value;
setTimeout(() => this.filterPossibleObjects());
}
get idsOfObjectsToHide(): string[] {
return this._idsOfObjectsToHide;
}
_idsOfObjectsToHide: string[] = [];
@Input()
set editable(value: boolean) {
this._editable = value;
value
? this.addForm.get('addGroup').enable()
: this.addForm.get('addGroup').disable();
}
get editable() {
return this._editable;
}
_editable: boolean = false;
/** function that returns the string that should be displayed in the selection */
@Input()
nameToShowInSelection;
@Input()
keepAutocompleteOpenAfterClick: boolean = false;
@Output() selectedElementChange = new EventEmitter();
addForm: FormGroup = new FormGroup({ addGroup: new FormControl() });
filteredPossibleObjects: any[] = [];
constructor() {}
ngOnInit(): void {
this.addForm
.get('addGroup')
.valueChanges.subscribe(() => this.filterPossibleObjects());
}
onOptionClicked(event: Event, element: any, trigger: MatAutocompleteTrigger) {
event.stopPropagation();
if (this.keepAutocompleteOpenAfterClick) {
trigger.openPanel();
}
this.addForm.get('addGroup').reset();
this.selectedElementChange.emit(element);
}
filterPossibleObjects() {
this.filteredPossibleObjects = this.possibleObjects.filter(
(element) =>
this.idsOfObjectsToHide.findIndex((id) => id === element.id) === -1
);
let searchString = this.addForm.get('addGroup').value;
if (!searchString) {
return;
}
searchString = searchString.toLocaleLowerCase();
this.filteredPossibleObjects = this.filteredPossibleObjects.filter(
(element) =>
this.nameToShowInSelection(element)
.toLocaleLowerCase()
.includes(searchString)
);
}
}

@ -1,30 +1,15 @@
<div class="table-page-wrapper"> <div class="table-page-wrapper">
<div class="table-control"> <div class="table-control">
<form [formGroup]="addForm" *ngIf="editableReferences"> <div *ngIf="editableReferences">
<mat-form-field> <app-autocomplete-select
<input [editable]="editable"
type="text" [possibleObjects]="possibleValues"
matInput [idsOfObjectsToHide]="idsOfObjectsToHide"
#trigger="matAutocompleteTrigger" [nameToShowInSelection]="nameToShowInSelection"
placeholder="Element hinzufügen" [keepAutocompleteOpenAfterClick]="true"
formControlName="addGroup" (selectedElementChange)="addReference($event)"
[matAutocomplete]="autoGroup" ></app-autocomplete-select>
/> </div>
<mat-autocomplete #autoGroup="matAutocomplete" panelWidth="auto">
<mat-option
*ngFor="let element of possibleValueOptions"
[value]="nameToShowInSelection(element)"
(click)="
addReference(element);
$event.stopPropagation();
trigger.openPanel()
"
>
{{ nameToShowInSelection(element) }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
<mat-form-field class="filter"> <mat-form-field class="filter">
<mat-label>Tabelle filtern</mat-label> <mat-label>Tabelle filtern</mat-label>
<input <input

@ -36,16 +36,7 @@ export class ReferenceTableComponent {
@Input() @Input()
nameToShowInSelection: any; nameToShowInSelection: any;
@Input() @Input()
set editable(value: boolean) { editable: boolean = false;
this._editable = value;
value
? this.addForm.get('addGroup').enable()
: this.addForm.get('addGroup').disable();
}
get editable() {
return this._editable;
}
_editable: boolean = false;
@Input() @Input()
set editableReferences(value: boolean) { set editableReferences(value: boolean) {
@ -66,8 +57,10 @@ export class ReferenceTableComponent {
return; return;
} }
this.dataSource.data = []; this.dataSource.data = [];
this.idsOfObjectsToHide = [];
for (const element of newdata) { for (const element of newdata) {
this.dataSource.data.push(flatten(element)); this.dataSource.data.push(flatten(element));
this.idsOfObjectsToHide.push(element.id);
} }
this.dataSource.data = this.dataSource.data; this.dataSource.data = this.dataSource.data;
this.onReferenceChange(); this.onReferenceChange();
@ -89,12 +82,10 @@ export class ReferenceTableComponent {
/** data source of the table */ /** data source of the table */
dataSource: MatTableDataSource<any> = new MatTableDataSource([]); dataSource: MatTableDataSource<any> = new MatTableDataSource([]);
possibleValues: Array<any> = []; possibleValues: Array<any> = [];
possibleValueOptions: Array<any> = []; idsOfObjectsToHide = [];
reloadingTable = false; reloadingTable = false;
addForm: FormGroup = new FormGroup({ addGroup: new FormControl() });
tableFilterString = ''; tableFilterString = '';
filterStringChanged: Subject<string> = new Subject<string>(); filterStringChanged: Subject<string> = new Subject<string>();
@ -108,9 +99,6 @@ export class ReferenceTableComponent {
if (this.editableReferences) { if (this.editableReferences) {
this.displayedColumns.push('buttons'); this.displayedColumns.push('buttons');
} }
this.addForm
.get('addGroup')
.valueChanges.subscribe(() => this.filterPossibleValueOptions());
this.filterStringChanged this.filterStringChanged
.pipe(debounceTime(400)) .pipe(debounceTime(400))
@ -133,10 +121,9 @@ export class ReferenceTableComponent {
this.possibleValues = []; this.possibleValues = [];
if (data) { if (data) {
for (const row of data) { for (const row of data) {
this.possibleValues.push(flatten(row)); this.possibleValues.push(row);
} }
} }
this.filterPossibleValueOptions();
} }
); );
this.dataServiceThatProvidesThePossibleData.loadTableData(); this.dataServiceThatProvidesThePossibleData.loadTableData();
@ -161,25 +148,26 @@ export class ReferenceTableComponent {
} }
delete(row: any) { delete(row: any) {
const index = this.dataSource.data.findIndex( let index = this.dataSource.data.findIndex(
(element) => element.id === row.id (element) => element.id === row.id
); );
if (index === -1) { if (index !== -1) {
return;
}
this.dataSource.data.splice(index, 1); this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data; //needed to trigger update lol this.dataSource.data = this.dataSource.data; //needed to trigger update lol
this.filterPossibleValueOptions();
this.onReferenceChange(); this.onReferenceChange();
}
// show it again in the selection
this.idsOfObjectsToHide = this.idsOfObjectsToHide.filter(
(id) => id !== row.id
);
} }
addReference(row: any) { addReference(row: any) {
this.addForm.get('addGroup').reset(); this.dataSource.data = [flatten(row), ...this.dataSource.data];
this.dataSource.data = [row, ...this.dataSource.data]; this.idsOfObjectsToHide = [row.id, ...this.idsOfObjectsToHide];
this.tableFilterString = ''; this.tableFilterString = '';
this.applyTableFilter(); this.applyTableFilter();
this.filterPossibleValueOptions();
this.onReferenceChange(); this.onReferenceChange();
} }
@ -187,22 +175,6 @@ export class ReferenceTableComponent {
return this.dataSource.data.find((row) => row.id === id); return this.dataSource.data.find((row) => row.id === id);
} }
filterPossibleValueOptions() {
this.possibleValueOptions = this.possibleValues.filter(
(element) => !this.dataSource.data.find((row) => row.id === element.id)
);
let searchString = this.addForm.get('addGroup').value;
if (!searchString) {
return;
}
searchString = searchString.toLocaleLowerCase();
this.possibleValueOptions = this.possibleValueOptions.filter((element) =>
this.nameToShowInSelection(element)
.toLocaleLowerCase()
.includes(searchString)
);
}
newFilterStringValue(): void { newFilterStringValue(): void {
this.filterStringChanged.next(this.tableFilterString); this.filterStringChanged.next(this.tableFilterString);
} }

@ -10,7 +10,7 @@ import { SnackBarService } from '../../services/snackbar.service';
export class SidenavProfileComponent implements OnInit { export class SidenavProfileComponent implements OnInit {
name: String; name: String;
email: String; email: String;
profileURL: String; profileURL: String = '/assets/flotte_logo.png';
constructor( private auth: AuthService, private snackBar: SnackBarService) { } constructor( private auth: AuthService, private snackBar: SnackBarService) { }

@ -117,7 +117,11 @@
</th> </th>
<td mat-cell *matCellDef="let element"> <td mat-cell *matCellDef="let element">
<ng-container <ng-container
*ngIf="column.type !== 'DateRange' && column.type !== 'NumRange'" *ngIf="
column.type !== 'DateRange' &&
column.type !== 'NumRange' &&
column.possibleObjects === undefined
"
> >
<app-cell <app-cell
*ngIf=" *ngIf="
@ -183,6 +187,29 @@
[(to)]="element[column.dataPath + '.to']" [(to)]="element[column.dataPath + '.to']"
></app-date-range-cell> ></app-date-range-cell>
</ng-container> </ng-container>
<ng-container *ngIf="column.possibleObjects">
<ng-container
*ngIf="
element.newObject || element.isLockedByMe;
else stringValue
"
>
<button mat-button (click)="openSelectObjectDialog(element, column)">
{{ element[column.dataPath] }}
<mat-icon>expand_more</mat-icon>
</button>
</ng-container>
<ng-template #stringValue>
<span *ngIf="!column.link">{{ element[column.dataPath] }}</span>
<a
mat-button
color="primary"
*ngIf="column.link"
[routerLink]="column.link(element)"
>{{ element[column.dataPath] }}</a
>
</ng-template>
</ng-container>
</td> </td>
</ng-container> </ng-container>

@ -21,6 +21,7 @@ import { ActivatedRoute } from '@angular/router';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/internal/operators/debounceTime'; import { debounceTime } from 'rxjs/internal/operators/debounceTime';
import { type } from 'os'; import { type } from 'os';
import { SelectObjectDialogComponent } from '../tableComponents/select-object-dialog/select-object-dialog.component';
@Component({ @Component({
selector: 'app-table', selector: 'app-table',
@ -331,6 +332,26 @@ export class TableComponent implements AfterViewInit {
}); });
} }
openSelectObjectDialog(row: any, column: any) {
console.log(row);
console.log(column);
const dialogRef = this.dialog.open(SelectObjectDialogComponent, {
width: 'auto',
autoFocus: false,
data: {
nameToShowInSelection: column.nameToShowInSelection,
currentlySelectedObjectId: column.currentlySelectedObjectId(row),
possibleObjects: column.possibleObjects,
},
});
dialogRef.afterClosed().subscribe((selectedObject) => {
if (selectedObject) {
row[column.propertyNameOfReferenceId] = selectedObject.id;
row[column.dataPath] = column.valueToOverwriteDataPath(selectedObject);
}
});
}
getRowById(id: string) { getRowById(id: string) {
return this.data.data.find((row) => row.id === id); return this.data.data.find((row) => row.id === id);
} }

@ -0,0 +1,21 @@
<div mat-dialog-content>
<h1 mat-dialog-title>Neues Objekt auswählen</h1>
</div>
<div mat-dialog-content>
<app-autocomplete-select
[editable]="true"
[possibleObjects]="data.possibleObjects"
[nameToShowInSelection]="data.nameToShowInSelection"
(selectedElementChange)="onObjectClicked($event)"
></app-autocomplete-select>
<span>aktuell ausgewählt: <b>{{getSelectedObjectName()}}</b></span>
</div>
<div mat-dialog-actions>
<button mat-button (click)="onCancelClick()" i18n>Abbrechen</button>
<button mat-button (click)="onConfirmClick()" color="primary">
Übernehmen
</button>
</div>

@ -0,0 +1,44 @@
import { Component, Inject, OnInit } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { DeleteConfirmationDialog } from '../../table/table.component';
@Component({
selector: 'app-select-object-dialog',
templateUrl: './select-object-dialog.component.html',
styleUrls: ['./select-object-dialog.component.scss'],
})
export class SelectObjectDialogComponent implements OnInit {
constructor(
public dialogRef: MatDialogRef<DeleteConfirmationDialog>,
@Inject(MAT_DIALOG_DATA) public data: any
) {
console.log(this.data);
}
ngOnInit(): void {}
onObjectClicked(object: any) {
this.data.currentlySelectedObjectId = object.id;
}
getSelectedObject() {
return this.data.possibleObjects.find(
(object) => object.id === this.data.currentlySelectedObjectId
)
}
getSelectedObjectName() {
const selectedObject = this.getSelectedObject();
if (!selectedObject) {
return "";
}
return this.data.nameToShowInSelection(selectedObject);
}
onConfirmClick(): void {
this.dialogRef.close(this.getSelectedObject());
}
onCancelClick(): void {
this.dialogRef.close();
}
}

@ -193,7 +193,7 @@ export class BikeComponent implements OnInit {
{ dataPath: 'description', translation: 'Beschreibung' }, { dataPath: 'description', translation: 'Beschreibung' },
], ],
nameToShowInSelection: (element) => { nameToShowInSelection: (element) => {
return element.name; return element?.name;
}, },
linkToTable: (element) => { linkToTable: (element) => {
return '/table/equipmentTypes'; return '/table/equipmentTypes';

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { BikesService } from 'src/app/services/bikes.service';
import { TimeFrameService } from 'src/app/services/timeFrame.service'; import { TimeFrameService } from 'src/app/services/timeFrame.service';
@Component({ @Component({
selector: 'app-time-frames', selector: 'app-time-frames',
@ -9,13 +10,28 @@ export class TimeFramesComponent implements OnInit {
headline = 'Zeitscheiben'; headline = 'Zeitscheiben';
columnInfo = [ columnInfo = [
{ dataPath: 'dateRange', translation: 'Zeitraum', type: 'DateRange', readonly: false }, {
dataPath: 'dateRange',
translation: 'Zeitraum',
type: 'DateRange',
readonly: false,
},
{ {
dataPath: 'cargoBike.name', dataPath: 'cargoBike.name',
translation: 'Lastenrad', translation: 'Lastenrad',
link: (element) => { link: (element) => {
return '/bike/' + element['cargoBike.id']; return '/bike/' + element['cargoBike.id'];
}, },
possibleObjects: [
{ id: 1, name: 'test' },
{ id: 2, name: 'bike2' },
],
nameToShowInSelection: (bike) => bike.name,
valueToOverwriteDataPath: (bike) => bike.name,
currentlySelectedObjectId: (timeFrame) => {
return timeFrame['cargoBike.id'];
},
propertyNameOfReferenceId: 'cargoBikeId'
}, },
{ {
dataPath: 'lendingStation.name', dataPath: 'lendingStation.name',
@ -33,7 +49,18 @@ export class TimeFramesComponent implements OnInit {
tableDataGQLUpdateInputType: string = 'TimeFrameUpdateInput'; tableDataGQLUpdateInputType: string = 'TimeFrameUpdateInput';
loadingRowIds: string[] = []; loadingRowIds: string[] = [];
constructor(private service: TimeFrameService) {} constructor(
private service: TimeFrameService,
private bikesService: BikesService
) {
this.bikesService.loadTableData();
this.bikesService.tableData.subscribe((data) => {
this.columnInfo.find(
(column) => column.dataPath === 'cargoBike.name'
).possibleObjects = data;
});
// TODO: add LendingStationService
}
ngOnInit() { ngOnInit() {
this.dataService = this.service; this.dataService = this.service;

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

@ -1,5 +1,5 @@
export const environment = { export const environment = {
production: true, production: true,
apiUrl: "http://173.212.197.169:4000", // graphql api url without /graphql! apiUrl: "https://api.flotte-berlin.duckdns.org", // graphql api url without /graphql!
authUrl: "http://173.212.197.169:8080" // user server url authUrl: "https://userserver.flotte-berlin.duckdns.org" // user server url
}; };

Loading…
Cancel
Save