Add reference table
parent
80771eded3
commit
260e105504
@ -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,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();
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in New Issue