Add reference table

urls
Max Ehrlicher-Schmidt 4 years ago
parent 80771eded3
commit 260e105504

@ -27,7 +27,7 @@ import {MatSelectModule} from '@angular/material/select';
import { MatPaginatorModule } from '@angular/material/paginator'; import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort'; import { MatSortModule } from '@angular/material/sort';
import {MatDialogModule} from '@angular/material/dialog'; import {MatDialogModule} from '@angular/material/dialog';
import {MatAutocompleteModule} from '@angular/material/autocomplete';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
@ -49,7 +49,8 @@ import { TableComponent, DeleteConfirmationDialog } from './components/table/tab
import { DataPageComponent } from './components/data-page/data-page.component'; import { DataPageComponent } from './components/data-page/data-page.component';
import { EquipmentTypesComponent } from './pages/tables/equipment-types/equipment-types.component'; import { EquipmentTypesComponent } from './pages/tables/equipment-types/equipment-types.component';
import { EngagementTypesComponent } from './pages/tables/engagement-types/engagement-types.component'; import { EngagementTypesComponent } from './pages/tables/engagement-types/engagement-types.component';
import { WorkshopsComponent } from './pages/tables/workshops/workshops.component' import { WorkshopsComponent } from './pages/tables/workshops/workshops.component';
import { ReferenceTableComponent } from './components/reference-table/reference-table.component'
@NgModule({ @NgModule({
@ -69,7 +70,8 @@ import { WorkshopsComponent } from './pages/tables/workshops/workshops.component
DataPageComponent, DataPageComponent,
EquipmentTypesComponent, EquipmentTypesComponent,
EngagementTypesComponent, EngagementTypesComponent,
WorkshopsComponent WorkshopsComponent,
ReferenceTableComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
@ -100,7 +102,8 @@ import { WorkshopsComponent } from './pages/tables/workshops/workshops.component
MatSelectModule, MatSelectModule,
MatPaginatorModule, MatPaginatorModule,
MatSortModule, MatSortModule,
MatDialogModule MatDialogModule,
MatAutocompleteModule
], ],
providers: [NavService, providers: [NavService,
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }], { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }],

@ -12,16 +12,30 @@
{{ data[headlineDataPath] }} {{ data[headlineDataPath] }}
</h1> </h1>
<ng-container *ngFor="let object of propertiesInfo"> <ng-container *ngFor="let object of propertiesInfo">
<mat-card class="card" *ngIf="object.isGroup"> <mat-card class="inline-card" *ngIf="object.type === 'Group'">
<mat-card-title>{{object.title}}</mat-card-title> <mat-card-title>{{ object.title }}</mat-card-title>
<app-cell *ngFor="let prop of object.properties" <app-cell
*ngFor="let prop of object.properties"
[editable]="data.isLockedByMe && !prop.readonly" [editable]="data.isLockedByMe && !prop.readonly"
[(value)]="data[prop.name]" [(value)]="data[prop.name]"
[label]="prop.translation || prop.name" [label]="prop.translation || prop.name"
[inputType]="prop.type" [inputType]="prop.type"
></app-cell> ></app-cell>
</mat-card> </mat-card>
<mat-card class="inline-card" *ngIf="object.type === 'ReferenceTable'">
<mat-card-title>{{ object.title }}</mat-card-title>
<app-reference-table
[dataServiceThatProvidesThePossibleData]="object.dataService"
[nameToShowInSelection]="object.nameToShowInSelection"
[columnInfo]="object.columnInfo"
[data]="data[object.name]"
[editable]="data.isLockedByMe"
[tableDataGQLType]="object.tableDataGQLType"
(referenceIds)="addReferenceIdsToObject($event, object)"
></app-reference-table>
</mat-card>
</ng-container> </ng-container>
</div> </div>
@ -37,40 +51,40 @@
</button> </button>
<div id="floating-fab-button-box"> <div id="floating-fab-button-box">
<button <button
mat-fab mat-fab
(click)="lock()" (click)="lock()"
*ngIf="!data.isLockedByMe && !data.isLocked" *ngIf="!data.isLockedByMe && !data.isLocked"
class="floating-fab-button" class="floating-fab-button"
color="primary" color="primary"
[disabled]="isSavingOrLocking || isLoading" [disabled]="isSavingOrLocking || isLoading"
> >
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
</button> </button>
<button <button
mat-mini-fab mat-mini-fab
(click)="cancel()" (click)="cancel()"
*ngIf="data.isLockedByMe" *ngIf="data.isLockedByMe"
class="floating-fab-button" class="floating-fab-button"
[disabled]="isSavingOrLocking || isLoading" [disabled]="isSavingOrLocking || isLoading"
> >
<mat-icon>cancel</mat-icon> <mat-icon>cancel</mat-icon>
</button> </button>
<button <button
mat-fab mat-fab
(click)="save()" (click)="save()"
*ngIf="data.isLockedByMe" *ngIf="data.isLockedByMe"
class="floating-fab-button" class="floating-fab-button"
[disabled]="isSavingOrLocking || isLoading" [disabled]="isSavingOrLocking || isLoading"
> >
<mat-icon>save</mat-icon> <mat-icon>save</mat-icon>
</button> </button>
<button <button
mat-fab mat-fab
*ngIf="data.isLocked" *ngIf="data.isLocked"
matTooltip="Dieser Eintrag wird gerade von einem anderen Bearbeiter editiert. Aktualisieren Sie die Seite, um den neuen Status abzurufen." matTooltip="Dieser Eintrag wird gerade von einem anderen Bearbeiter editiert. Aktualisieren Sie die Seite, um den neuen Status abzurufen."
class="floating-fab-button" class="floating-fab-button"
> >
<mat-icon>locked</mat-icon> <mat-icon>locked</mat-icon>
</button> </button>
</div> </div>

@ -6,9 +6,9 @@
box-sizing: border-box; box-sizing: border-box;
overflow: auto; overflow: auto;
padding: 2em; padding: 2em;
.card { .inline-card {
display: inline-table; display: inline-table;
width: 20em; min-width: 20em;
margin: 1em; margin: 1em;
} }
} }

@ -4,17 +4,27 @@ import { deepen } from 'src/app/helperFunctions/deepenObject';
import { flatten } from 'src/app/helperFunctions/flattenObject'; import { flatten } from 'src/app/helperFunctions/flattenObject';
import { SchemaService } from 'src/app/services/schema.service'; import { SchemaService } from 'src/app/services/schema.service';
interface PropertyInfoType { interface PropertyTypeInfo {
name: string; name: string;
translation: string; translation: string;
readonly?: boolean; readonly?: boolean;
type?: string; type?: string;
} }
interface PropertyGroup { interface PropertyGroupInfo {
isGroup: boolean; type: string;
title: string; title: string;
properties: PropertyInfoType[]; properties: PropertyTypeInfo[];
}
interface ReferenceTableInfo {
type: string;
title: string;
name: string;
dataService: any;
columnInfo: PropertyTypeInfo[];
nameToShowInSelection: any;
propertyNameOfUpdateInput: string;
referenceIds: Array<string>;
} }
@Component({ @Component({
@ -24,7 +34,7 @@ interface PropertyGroup {
}) })
export class DataPageComponent implements OnInit { export class DataPageComponent implements OnInit {
@Input() @Input()
propertiesInfo: Array<PropertyInfoType | PropertyGroup> = []; propertiesInfo: Array<any> = [];
@Input() @Input()
dataService: any; dataService: any;
@ -32,9 +42,11 @@ export class DataPageComponent implements OnInit {
@Input() @Input()
headlineDataPath: string; headlineDataPath: string;
@Input() @Input()
pageDataGQLType: string = 'CargoBike'; pageDataGQLType: string;
@Input() @Input()
pageDataGQLUpdateInputType: string = 'CargoBikeUpdateInput'; pageDataGQLUpdateInputType: string;
@Input()
propertyNameOfUpdateInput: string;
@Output() lockEvent = new EventEmitter(); @Output() lockEvent = new EventEmitter();
@Output() saveEvent = new EventEmitter(); @Output() saveEvent = new EventEmitter();
@ -67,8 +79,14 @@ export class DataPageComponent implements OnInit {
addPropertiesFromGQLSchemaToObject(infoObject: any) { addPropertiesFromGQLSchemaToObject(infoObject: any) {
for (const prop of infoObject) { for (const prop of infoObject) {
if (prop.isGroup) { if (prop.type === 'Group') {
this.addPropertiesFromGQLSchemaToObject(prop.properties); this.addPropertiesFromGQLSchemaToObject(prop.properties);
} else if (prop.type === 'ReferenceTable') {
prop.tableDataGQLType =
prop.tableDataGQLType ||
this.schemaService.getTypeInformation(this.pageDataGQLType, prop.name)
.type;
prop.referenceIds = [];
} else { } else {
const typeInformation = this.schemaService.getTypeInformation( const typeInformation = this.schemaService.getTypeInformation(
this.pageDataGQLType, this.pageDataGQLType,
@ -98,7 +116,11 @@ export class DataPageComponent implements OnInit {
} }
cancel() { cancel() {
this.cancelEvent.emit(deepen(this.data)) this.cancelEvent.emit(deepen(this.data));
}
addReferenceIdsToObject(ids: string[], object) {
this.data[object.propertyNameOfUpdateInput] = ids;
} }
reloadPageData() { reloadPageData() {

@ -0,0 +1,93 @@
<div class="table-page-wrapper">
<div class="table-control">
<form [formGroup]="addForm">
<mat-form-field>
<input
type="text"
matInput
placeholder="Element hinzufügen"
formControlName="addGroup"
[matAutocomplete]="autoGroup"
/>
<mat-autocomplete #autoGroup="matAutocomplete">
<mat-option
*ngFor="let element of possibleValueOptions"
[value]="nameToShowInSelection(element)"
(click)="addReference(element)"
>
{{ nameToShowInSelection(element) }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
<mat-form-field class="filter">
<mat-label>Tabelle filtern</mat-label>
<input
matInput
(input)="applyTableFilter()"
[(ngModel)]="tableFilterString"
placeholder="Suchbegriff eingeben..."
/>
</mat-form-field>
<mat-paginator
[pageSizeOptions]="[15, 25]"
showFirstLastButtons
></mat-paginator>
</div>
<div class="table-container">
<table mat-table class="mat-elevation-z8" matSort [dataSource]="dataSource">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Other Columns -->
<ng-container
*ngFor="let column of columnInfo"
[matColumnDef]="column.name"
[sticky]="isStickyColumn(column.name)"
>
<th mat-header-cell *matHeaderCellDef mat-sort-header>
{{ column.translation || column.name }}
</th>
<td mat-cell *matCellDef="let element">
<app-cell
*ngIf="column.type === 'Boolean'; else stringValue"
[editable]="false"
[(value)]="element[column.name]"
[inputType]="column.type"
></app-cell>
<ng-template #stringValue>
<span *ngIf="!column.link">{{ element[column.name] }}</span>
<a
mat-button
color="primary"
*ngIf="column.link"
[routerLink]="column.link(element)"
>{{ element[column.name] }}</a
>
</ng-template>
</td>
</ng-container>
<!-- Buttons Column -->
<ng-container matColumnDef="buttons" stickyEnd>
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let element">
<div class="button-wrapper">
<button
mat-icon-button
matTooltip="Entfernen"
(click)="delete(element)"
[disabled]="!editable"
>
<mat-icon>delete</mat-icon>
</button>
</div>
</td>
</ng-container>
<!-- Table Definition -->
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
</div>

@ -0,0 +1,60 @@
.table-page-wrapper {
display: flex;
flex-direction: column;
height: 100%;
.headline {
margin: 0 0.5em;
}
.table-control {
margin: 0.5em;
flex: none;
.table-control-button {
margin: 0.25em;
}
.filter {
margin-right: 0.5em;
}
.mat-paginator {
display: inline-block;
width: 50em;
margin-right: 0.5em;
}
}
.table-container {
flex: 1;
width: auto;
margin-left: 0.5em;
margin-right: 0.5em;
max-width: 100%;
overflow: auto;
table {
max-width: 100%;
margin: 0 auto;
.mat-header-cell,
.mat-footer-cell,
.mat-cell {
min-width: 3em;
box-sizing: border-box;
padding: 0 0.25em;
::ng-deep.mat-form-field-infix {
width: auto !important;
min-width: 50px !important;
}
}
::ng-deep.mat-form-field {
width: 100%;
}
.mat-table-sticky {
filter: brightness(90%);
//opacity: 1;
}
.button-wrapper {
display: flex;
flex-direction: row;
}
}
}
}

@ -0,0 +1,189 @@
import {
Component,
EventEmitter,
Input,
Output,
ViewChild,
} from '@angular/core';
import { flatten } from 'src/app/helperFunctions/flattenObject';
import { SchemaService } from 'src/app/services/schema.service';
import { MatTableDataSource } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-reference-table',
templateUrl: './reference-table.component.html',
styleUrls: ['./reference-table.component.scss'],
})
export class ReferenceTableComponent {
/** this array defines the columns and translations of the table and the order they are displayed */
@Input()
columnInfo: {
name: string;
translation: string;
sticky?: boolean;
type?: string;
link?: (row: any) => string;
}[] = [];
@Input()
dataServiceThatProvidesThePossibleData: any;
@Input()
nameToShowInSelection: any;
@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;
@Input()
set data(newdata) {
if (!newdata) return;
this.dataSource.data = [];
for (const element of newdata) {
this.dataSource.data.push(flatten(element));
}
this.dataSource.data = this.dataSource.data;
this.onReferenceChange();
}
get data(): any {
return this.dataSource.data;
}
@Input()
tableDataGQLType: string;
@Output() referenceIds = new EventEmitter();
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
displayedColumns: string[] = [];
/** data source of the table */
dataSource: MatTableDataSource<any> = new MatTableDataSource([]);
possibleValues: Array<any> = [];
possibleValueOptions: Array<any> = [];
reloadingTable = false;
addForm: FormGroup = new FormGroup({ addGroup: new FormControl() });
tableFilterString: string = '';
constructor(private schemaService: SchemaService) {}
ngOnInit() {
this.addColumnPropertiesFromGQLSchemaToColumnInfo();
this.columnInfo.forEach((column) => {
this.displayedColumns.push(column.name);
});
this.displayedColumns.push('buttons');
this.addForm
.get('addGroup')
.valueChanges.subscribe(() => this.filterPossibleValueOptions());
}
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.dataSource.sortingDataAccessor = (item, columnName) => {
if (typeof item[columnName] === 'string') {
return item[columnName].toLocaleLowerCase();
}
return item[columnName];
};
this.dataServiceThatProvidesThePossibleData.tableData.subscribe((data) => {
this.possibleValues = [];
if (data) {
for (const row of data) {
this.possibleValues.push(flatten(row));
}
}
this.filterPossibleValueOptions();
});
this.dataServiceThatProvidesThePossibleData.loadTableData();
}
addColumnPropertiesFromGQLSchemaToColumnInfo() {
for (const column of this.columnInfo) {
const typeInformation = this.schemaService.getTypeInformation(
this.tableDataGQLType,
column.name
);
column.type = column.type || typeInformation.type;
}
}
isStickyColumn(propertyName: string) {
return (
this.columnInfo.find((column) => column.name === propertyName)?.sticky ||
false
);
}
delete(row: any) {
const index = this.dataSource.data.findIndex(
(element) => element.id === row.id
);
if (index === -1) return;
this.dataSource.data.splice(index, 1);
this.dataSource.data = this.dataSource.data; //needed to trigger update lol
this.filterPossibleValueOptions();
this.onReferenceChange();
}
addReference(row: any) {
this.addForm.get('addGroup').reset();
this.dataSource.data = [row, ...this.dataSource.data];
this.tableFilterString = '';
this.applyTableFilter();
this.filterPossibleValueOptions();
this.onReferenceChange();
}
getRowById(id: string) {
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)
);
}
applyTableFilter() {
this.dataSource.filter = this.tableFilterString;
}
onReferenceChange() {
const ids = [];
for (const element of this.data) {
ids.push(element.id);
}
this.referenceIds.emit(ids);
}
}

@ -1,5 +1,5 @@
<div class="table-page-wrapper"> <div class="table-page-wrapper">
<h1 class="headline"> <h1 class="headline" *ngIf="headline">
{{ headline }} {{ headline }}
</h1> </h1>
<div class="table-control"> <div class="table-control">

@ -24,7 +24,7 @@ import { MatDialog, MatDialogRef } from '@angular/material/dialog';
}) })
export class TableComponent { export class TableComponent {
@Input() @Input()
headline: string = "Keine Überschrift"; headline: string = null;
/** this array defines the columns and translations of the table and the order they are displayed */ /** this array defines the columns and translations of the table and the order they are displayed */
@Input() @Input()
columnInfo: { columnInfo: {

@ -1,21 +1,24 @@
export function deepen(object: Object): any { export function deepen(object: Object): any {
let newObject = {}; let newObject;
for (const prop in object) { if (Array.isArray(object)) {
if (prop.includes('.')) { newObject = new Array();
const splittedProp = prop.split('.'); } else newObject = new Object();
const outerProp = splittedProp[0]; for (const prop in object) {
const innerProp = splittedProp.slice(1).join('.'); if (prop.includes('.')) {
if (!newObject[outerProp]) { const splittedProp = prop.split('.');
newObject[outerProp] = {}; const outerProp = splittedProp[0];
} const innerProp = splittedProp.slice(1).join('.');
newObject[outerProp][innerProp] = object[prop]; if (!newObject[outerProp]) {
} else { newObject[outerProp] = {};
newObject[prop] = object[prop];
} }
newObject[outerProp][innerProp] = object[prop];
} else {
newObject[prop] = object[prop];
} }
for (const prop in newObject) { }
if (typeof newObject[prop] === 'object' && newObject[prop] !== null) for (const prop in newObject) {
newObject[prop] = deepen(newObject[prop]); if (typeof newObject[prop] === 'object' && newObject[prop] !== null)
} newObject[prop] = deepen(newObject[prop]);
return newObject; }
} return newObject;
}

@ -1,16 +1,20 @@
export function flatten(object: Object, prefix: string = ''): any { export function flatten(object: Object, prefix: string = ''): any {
let newObject = {}; let newObject = {};
for (const prop in object) { for (const prop in object) {
let propName = prefix + prop; let propName = prefix + prop;
if (typeof object[prop] === 'object' && object[prop] !== null) { if (Array.isArray(object[prop])) {
const flattenedObject = flatten(object[prop], propName + '.'); newObject[propName] = [];
for (const flattenedProperty in flattenedObject) { for (const arrayElement of object[prop]) {
newObject[flattenedProperty] = newObject[propName].push(flatten(arrayElement));
flattenedObject[flattenedProperty];
}
} else {
newObject[propName] = object[prop];
} }
} else if (typeof object[prop] === 'object' && object[prop] !== null) {
const flattenedObject = flatten(object[prop], propName + '.');
for (const flattenedProperty in flattenedObject) {
newObject[flattenedProperty] = flattenedObject[flattenedProperty];
}
} else {
newObject[propName] = object[prop];
} }
return newObject; }
} return newObject;
}

@ -4,6 +4,7 @@
[headlineDataPath]="headlineDataPath" [headlineDataPath]="headlineDataPath"
[pageDataGQLType]="pageDataGQLType" [pageDataGQLType]="pageDataGQLType"
[pageDataGQLUpdateInputType]="pageDataGQLUpdateInputType" [pageDataGQLUpdateInputType]="pageDataGQLUpdateInputType"
[propertyNameOfUpdateInput]="propertyNameOfUpdateInput"
(lockEvent)="lock($event)" (lockEvent)="lock($event)"
(saveEvent)="save($event)" (saveEvent)="save($event)"
(cancelEvent)="cancel($event)" (cancelEvent)="cancel($event)"

@ -1,5 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { BikesService } from 'src/app/services/bikes.service'; import { BikesService } from 'src/app/services/bikes.service';
import { EquipmentTypeService } from 'src/app/services/equipmentType.service';
@Component({ @Component({
selector: 'app-bike', selector: 'app-bike',
@ -9,17 +10,17 @@ import { BikesService } from 'src/app/services/bikes.service';
export class BikeComponent implements OnInit { export class BikeComponent implements OnInit {
propertiesInfo = [ propertiesInfo = [
{ {
isGroup: true, type: 'Group',
title: 'Allgemein', title: 'Allgemein',
properties: [ properties: [
{ name: 'name', translation: 'Name' }, { name: 'name', translation: 'Name' },
{ name: 'id', translation: 'ID', readonly: true }, { name: 'id', translation: 'ID', readonly: true },
{ name: 'group', translation: 'Gruppe' }, { name: 'Group', translation: 'Gruppe' },
{ name: 'modelName', translation: 'Modell' }, { name: 'modelName', translation: 'Modell' },
], ],
}, },
{ {
isGroup: true, type: 'Group',
title: 'Versicherungsdaten', title: 'Versicherungsdaten',
properties: [ properties: [
{ {
@ -51,7 +52,7 @@ export class BikeComponent implements OnInit {
], ],
}, },
{ {
isGroup: true, type: 'Group',
title: 'Maße und Ladungen', title: 'Maße und Ladungen',
properties: [ properties: [
{ name: 'dimensionsAndLoad.bikeLength', translation: 'Länge' }, { name: 'dimensionsAndLoad.bikeLength', translation: 'Länge' },
@ -85,7 +86,7 @@ export class BikeComponent implements OnInit {
], ],
}, },
{ {
isGroup: true, type: 'Group',
title: 'Sicherheitsinformationen', title: 'Sicherheitsinformationen',
properties: [ properties: [
{ name: 'security.frameNumber', translation: 'Rahmennummer' }, { name: 'security.frameNumber', translation: 'Rahmennummer' },
@ -102,7 +103,7 @@ export class BikeComponent implements OnInit {
], ],
}, },
{ {
isGroup: true, type: 'Group',
title: 'Ausstattung', title: 'Ausstattung',
properties: [ properties: [
{ name: 'technicalEquipment.bicycleShift', translation: 'Schaltung' }, { name: 'technicalEquipment.bicycleShift', translation: 'Schaltung' },
@ -118,7 +119,7 @@ export class BikeComponent implements OnInit {
], ],
}, },
{ {
isGroup: true, type: 'Group',
title: 'Sonstiges', title: 'Sonstiges',
properties: [ properties: [
{ name: 'stickerBikeNameState', translation: 'Aufkleber Status' }, { name: 'stickerBikeNameState', translation: 'Aufkleber Status' },
@ -131,7 +132,7 @@ export class BikeComponent implements OnInit {
], ],
}, },
{ {
isGroup: true, type: 'Group',
title: 'provider', title: 'provider',
properties: [ properties: [
{ name: 'provider.id', translation: '' }, { name: 'provider.id', translation: '' },
@ -147,7 +148,7 @@ export class BikeComponent implements OnInit {
], ],
}, },
{ {
isGroup: true, type: 'Group',
title: 'lendingstation', title: 'lendingstation',
properties: [ properties: [
{ name: 'lendingStation.id', translation: '' }, { name: 'lendingStation.id', translation: '' },
@ -157,6 +158,15 @@ export class BikeComponent implements OnInit {
{ name: 'lendingStation.address.zip', translation: '' }, { name: 'lendingStation.address.zip', translation: '' },
], ],
}, },
{
type: 'ReferenceTable',
title: 'Equipmenttypen',
name: 'equipmentType',
dataService: null,
columnInfo: [{name: 'name', translation: "Name"}, {name: 'description', translation: "Beschreibung"}],
nameToShowInSelection: (element) => {return element.name},
propertyNameOfUpdateInput: "equipmentTypeIds"
},
]; ];
headlineDataPath = 'name'; headlineDataPath = 'name';
@ -165,7 +175,14 @@ export class BikeComponent implements OnInit {
dataService: any; dataService: any;
constructor(private bikesService: BikesService) {} constructor(
private bikesService: BikesService,
private equipmentTypeService: EquipmentTypeService
) {
this.propertiesInfo.find(
(prop) => prop.name === 'equipmentType'
).dataService = this.equipmentTypeService;
}
ngOnInit(): void { ngOnInit(): void {
this.dataService = this.bikesService; this.dataService = this.bikesService;

@ -9,7 +9,7 @@
</mat-grid-list> </mat-grid-list>
<div> <div>
<mat-grid-list cols="4" rowHeight="30px"> <mat-grid-list cols="4" rowHeight="30px">
<mat-grid-tile routerLink = "/table/bikes">Tabelle 5</mat-grid-tile> <mat-grid-tile routerLink = "/table/equipmentTypes">Equipmenttypen</mat-grid-tile>
<mat-grid-tile routerLink = "/table/bikes">Tabelle 7</mat-grid-tile> <mat-grid-tile routerLink = "/table/bikes">Tabelle 7</mat-grid-tile>
<mat-grid-tile routerLink = "/table/bikes">Tabelle 8</mat-grid-tile> <mat-grid-tile routerLink = "/table/bikes">Tabelle 8</mat-grid-tile>
<mat-grid-tile routerLink = "/table/bikes">Tabelle 9</mat-grid-tile> <mat-grid-tile routerLink = "/table/bikes">Tabelle 9</mat-grid-tile>

@ -1,5 +1,6 @@
mat-grid-tile { mat-grid-tile {
background: gray; background: gray;
cursor: pointer;
} }
.grid-list-spacer{ .grid-list-spacer{

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TableOverviewComponent } from './table-overview.component';
describe('TableOverviewComponent', () => {
let component: TableOverviewComponent;
let fixture: ComponentFixture<TableOverviewComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TableOverviewComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TableOverviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -63,7 +63,7 @@ export class BikesService {
loadTableData() { loadTableData() {
this.tableData.next(null); this.tableData.next(null);
this.getCargoBikesGQL.fetch().subscribe((result) => { this.getCargoBikesGQL.fetch().subscribe((result) => {
this.tableData.next(result.data.cargoBikes); this.tableData.next(result.data?.cargoBikes);
}); });
} }
@ -85,7 +85,7 @@ export class BikesService {
this.reloadCargoBikeByIdGQL this.reloadCargoBikeByIdGQL
.fetch(variables) .fetch(variables)
.subscribe((result) => { .subscribe((result) => {
this.updateDataRowFromResponse(result.data.cargoBikeById) this.updateDataRowFromResponse(result.data.cargoBikeById);
}) })
.add(() => { .add(() => {
this.removeLoadingRowId(variables.id); this.removeLoadingRowId(variables.id);
@ -153,11 +153,13 @@ export class BikesService {
} }
private updateDataRowFromResponse(rowFromResponse: any) { private updateDataRowFromResponse(rowFromResponse: any) {
const newTableData = this.tableData.value.map((row) => if (this.tableData.value) {
rowFromResponse.id === row.id ? rowFromResponse : row const newTableData = this.tableData.value.map((row) =>
); rowFromResponse.id === row.id ? rowFromResponse : row
this.tableData.next(newTableData); );
if ((rowFromResponse.id === this.pageData?.value?.id)) { this.tableData.next(newTableData);
}
if (rowFromResponse.id === this.pageData?.value?.id) {
this.pageData.next(rowFromResponse); this.pageData.next(rowFromResponse);
} }
} }

@ -32,7 +32,7 @@ export class EquipmentTypeService {
private updateEquipmentTypeGQL: UpdateEquipmentTypeGQL, private updateEquipmentTypeGQL: UpdateEquipmentTypeGQL,
private lockEquipmentTypeGQL: LockEquipmentTypeGQL, private lockEquipmentTypeGQL: LockEquipmentTypeGQL,
private unlockEquipmentTypeGQL: UnlockEquipmentTypeGQL, private unlockEquipmentTypeGQL: UnlockEquipmentTypeGQL,
private deleteEquipmentTypeGQL: DeleteEquipmentTypeGQL, private deleteEquipmentTypeGQL: DeleteEquipmentTypeGQL
) {} ) {}
addLoadingRowId(id: string) { addLoadingRowId(id: string) {
@ -116,9 +116,11 @@ export class EquipmentTypeService {
} }
private updateDataRowFromResponse(rowFromResponse: any) { private updateDataRowFromResponse(rowFromResponse: any) {
const newTableData = this.tableData.value.map((row) => if (this.tableData.value) {
rowFromResponse.id === row.id ? rowFromResponse : row const newTableData = this.tableData.value.map((row) =>
); rowFromResponse.id === row.id ? rowFromResponse : row
this.tableData.next(newTableData); );
this.tableData.next(newTableData);
}
} }
} }

@ -95,7 +95,12 @@ export class SchemaService {
} }
filterObject(graphQLTypeName: string, object: object): any { filterObject(graphQLTypeName: string, object: object): any {
const filteredObject = {}; let filteredObject;
if (Array.isArray(object)) {
return object;
//TODO: check if array consists of objects?
} else filteredObject = new Object();
for (const prop in object) { for (const prop in object) {
if (typeof object[prop] === 'object' && object[prop] !== null) { if (typeof object[prop] === 'object' && object[prop] !== null) {
const info = this.getTypeInformation(graphQLTypeName, prop); const info = this.getTypeInformation(graphQLTypeName, prop);

Loading…
Cancel
Save