diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b68abea..869ad7f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -62,6 +62,8 @@ import { EquipmentComponent } from './pages/tables/equipment/equipment.component import { TimeFramesComponent } from './pages/tables/time-frames/time-frames.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 { 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, NumberRangeCellComponent, DateRangeCellComponent, + SelectObjectDialogComponent, + AutocompleteSelectComponent, ], imports: [ BrowserModule, diff --git a/src/app/components/autocomplete-select/autocomplete-select.component.html b/src/app/components/autocomplete-select/autocomplete-select.component.html new file mode 100644 index 0000000..e51b5f2 --- /dev/null +++ b/src/app/components/autocomplete-select/autocomplete-select.component.html @@ -0,0 +1,21 @@ +
+ + + + + {{ nameToShowInSelection(object) }} + + + +
diff --git a/src/app/components/autocomplete-select/autocomplete-select.component.scss b/src/app/components/autocomplete-select/autocomplete-select.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/autocomplete-select/autocomplete-select.component.ts b/src/app/components/autocomplete-select/autocomplete-select.component.ts new file mode 100644 index 0000000..eef16e9 --- /dev/null +++ b/src/app/components/autocomplete-select/autocomplete-select.component.ts @@ -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) + ); + } +} diff --git a/src/app/components/reference-table/reference-table.component.html b/src/app/components/reference-table/reference-table.component.html index 9ef7177..c335d46 100644 --- a/src/app/components/reference-table/reference-table.component.html +++ b/src/app/components/reference-table/reference-table.component.html @@ -1,30 +1,15 @@
-
- - - - - {{ nameToShowInSelection(element) }} - - - -
+
+ +
Tabelle filtern = new MatTableDataSource([]); possibleValues: Array = []; - possibleValueOptions: Array = []; + idsOfObjectsToHide = []; reloadingTable = false; - addForm: FormGroup = new FormGroup({ addGroup: new FormControl() }); - tableFilterString = ''; filterStringChanged: Subject = new Subject(); @@ -108,9 +99,6 @@ export class ReferenceTableComponent { if (this.editableReferences) { this.displayedColumns.push('buttons'); } - this.addForm - .get('addGroup') - .valueChanges.subscribe(() => this.filterPossibleValueOptions()); this.filterStringChanged .pipe(debounceTime(400)) @@ -133,10 +121,9 @@ export class ReferenceTableComponent { this.possibleValues = []; if (data) { for (const row of data) { - this.possibleValues.push(flatten(row)); + this.possibleValues.push(row); } } - this.filterPossibleValueOptions(); } ); this.dataServiceThatProvidesThePossibleData.loadTableData(); @@ -161,25 +148,26 @@ export class ReferenceTableComponent { } delete(row: any) { - const index = this.dataSource.data.findIndex( + let index = this.dataSource.data.findIndex( (element) => element.id === row.id ); - if (index === -1) { - return; - } + if (index !== -1) { this.dataSource.data.splice(index, 1); this.dataSource.data = this.dataSource.data; //needed to trigger update lol - this.filterPossibleValueOptions(); this.onReferenceChange(); + } + + // show it again in the selection + this.idsOfObjectsToHide = this.idsOfObjectsToHide.filter( + (id) => id !== row.id + ); } addReference(row: any) { - this.addForm.get('addGroup').reset(); - this.dataSource.data = [row, ...this.dataSource.data]; - + this.dataSource.data = [flatten(row), ...this.dataSource.data]; + this.idsOfObjectsToHide = [row.id, ...this.idsOfObjectsToHide]; this.tableFilterString = ''; this.applyTableFilter(); - this.filterPossibleValueOptions(); this.onReferenceChange(); } @@ -187,22 +175,6 @@ export class ReferenceTableComponent { 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 { this.filterStringChanged.next(this.tableFilterString); } diff --git a/src/app/components/sidenav-profile/sidenav-profile.component.ts b/src/app/components/sidenav-profile/sidenav-profile.component.ts index 3b14530..c3aff0f 100644 --- a/src/app/components/sidenav-profile/sidenav-profile.component.ts +++ b/src/app/components/sidenav-profile/sidenav-profile.component.ts @@ -10,7 +10,7 @@ import { SnackBarService } from '../../services/snackbar.service'; export class SidenavProfileComponent implements OnInit { name: String; email: String; - profileURL: String; + profileURL: String = '/assets/flotte_logo.png'; constructor( private auth: AuthService, private snackBar: SnackBarService) { } diff --git a/src/app/components/table/table.component.html b/src/app/components/table/table.component.html index 2718e37..cf3b86c 100644 --- a/src/app/components/table/table.component.html +++ b/src/app/components/table/table.component.html @@ -117,7 +117,11 @@ + + + + + + {{ element[column.dataPath] }} + {{ element[column.dataPath] }} + + diff --git a/src/app/components/table/table.component.ts b/src/app/components/table/table.component.ts index f1f4c52..1de1ad9 100644 --- a/src/app/components/table/table.component.ts +++ b/src/app/components/table/table.component.ts @@ -21,6 +21,7 @@ import { ActivatedRoute } from '@angular/router'; import { Subject } from 'rxjs'; import { debounceTime } from 'rxjs/internal/operators/debounceTime'; import { type } from 'os'; +import { SelectObjectDialogComponent } from '../tableComponents/select-object-dialog/select-object-dialog.component'; @Component({ 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) { return this.data.data.find((row) => row.id === id); } diff --git a/src/app/components/tableComponents/select-object-dialog/select-object-dialog.component.html b/src/app/components/tableComponents/select-object-dialog/select-object-dialog.component.html new file mode 100644 index 0000000..13a2084 --- /dev/null +++ b/src/app/components/tableComponents/select-object-dialog/select-object-dialog.component.html @@ -0,0 +1,21 @@ +
+

Neues Objekt auswählen

+
+ +
+ + + aktuell ausgewählt: {{getSelectedObjectName()}} +
+ +
+ + +
diff --git a/src/app/components/tableComponents/select-object-dialog/select-object-dialog.component.scss b/src/app/components/tableComponents/select-object-dialog/select-object-dialog.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/tableComponents/select-object-dialog/select-object-dialog.component.ts b/src/app/components/tableComponents/select-object-dialog/select-object-dialog.component.ts new file mode 100644 index 0000000..8a259a6 --- /dev/null +++ b/src/app/components/tableComponents/select-object-dialog/select-object-dialog.component.ts @@ -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, + @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(); + } +} diff --git a/src/app/pages/dataPages/bike/bike.component.ts b/src/app/pages/dataPages/bike/bike.component.ts index 4c64042..d2f59d7 100644 --- a/src/app/pages/dataPages/bike/bike.component.ts +++ b/src/app/pages/dataPages/bike/bike.component.ts @@ -193,7 +193,7 @@ export class BikeComponent implements OnInit { { dataPath: 'description', translation: 'Beschreibung' }, ], nameToShowInSelection: (element) => { - return element.name; + return element?.name; }, linkToTable: (element) => { return '/table/equipmentTypes'; diff --git a/src/app/pages/tables/time-frames/time-frames.component.ts b/src/app/pages/tables/time-frames/time-frames.component.ts index c870aab..a663aea 100644 --- a/src/app/pages/tables/time-frames/time-frames.component.ts +++ b/src/app/pages/tables/time-frames/time-frames.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit } from '@angular/core'; +import { BikesService } from 'src/app/services/bikes.service'; import { TimeFrameService } from 'src/app/services/timeFrame.service'; @Component({ selector: 'app-time-frames', @@ -9,13 +10,28 @@ export class TimeFramesComponent implements OnInit { headline = 'Zeitscheiben'; columnInfo = [ - { dataPath: 'dateRange', translation: 'Zeitraum', type: 'DateRange', readonly: false }, + { + dataPath: 'dateRange', + translation: 'Zeitraum', + type: 'DateRange', + readonly: false, + }, { dataPath: 'cargoBike.name', translation: 'Lastenrad', link: (element) => { 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', @@ -33,7 +49,18 @@ export class TimeFramesComponent implements OnInit { tableDataGQLUpdateInputType: string = 'TimeFrameUpdateInput'; 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() { this.dataService = this.service; diff --git a/src/assets/flotte_logo.png b/src/assets/flotte_logo.png new file mode 100644 index 0000000..56c968e Binary files /dev/null and b/src/assets/flotte_logo.png differ diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 12af62b..14c4902 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,5 +1,5 @@ export const environment = { production: true, - apiUrl: "http://173.212.197.169:4000", // graphql api url without /graphql! - authUrl: "http://173.212.197.169:8080" // user server url + apiUrl: "https://api.flotte-berlin.duckdns.org", // graphql api url without /graphql! + authUrl: "https://userserver.flotte-berlin.duckdns.org" // user server url };