Add provider

master
Max Ehrlicher-Schmidt 4 years ago
parent 073de444db
commit 8cec05431d

@ -16,9 +16,10 @@ import { ProfileComponent } from './pages/profile/profile.component';
import { PersonsComponent } from './pages/tables/persons/persons.component'; import { PersonsComponent } from './pages/tables/persons/persons.component';
import { ContactInformationComponent } from './pages/tables/contact-information/contact-information.component'; import { ContactInformationComponent } from './pages/tables/contact-information/contact-information.component';
import { OrganisationsComponent } from './pages/tables/organisations/organisations.component'; import { OrganisationsComponent } from './pages/tables/organisations/organisations.component';
import { ProviderComponent } from './pages/tables/provider/provider.component'; import { ProvidersComponent } from './pages/tables/providers/providers.component';
import { PersonComponent } from './pages/dataPages/person/person.component'; import { PersonComponent } from './pages/dataPages/person/person.component';
import { OrganisationComponent } from './pages/dataPages/organisation/organisation.component'; import { OrganisationComponent } from './pages/dataPages/organisation/organisation.component';
import { ProviderComponent } from './pages/dataPages/provider/provider.component';
const routes: Routes = [ const routes: Routes = [
{ path: 'login', component: LoginComponent }, { path: 'login', component: LoginComponent },
@ -35,9 +36,10 @@ const routes: Routes = [
{ path: 'table/persons', component: PersonsComponent, canActivate: [AuthGuard] }, { path: 'table/persons', component: PersonsComponent, canActivate: [AuthGuard] },
{ path: 'table/contactInformation', component: ContactInformationComponent, canActivate: [AuthGuard] }, { path: 'table/contactInformation', component: ContactInformationComponent, canActivate: [AuthGuard] },
{ path: 'table/organisations', component: OrganisationsComponent, canActivate: [AuthGuard] }, { path: 'table/organisations', component: OrganisationsComponent, canActivate: [AuthGuard] },
{ path: 'table/providers', component: ProviderComponent, canActivate: [AuthGuard] }, { path: 'table/providers', component: ProvidersComponent, canActivate: [AuthGuard] },
{ path: 'lendingStation/:id', component: LendingStationComponent, canActivate: [AuthGuard] }, { path: 'lendingStation/:id', component: LendingStationComponent, canActivate: [AuthGuard] },
{ path: 'person/:id', component: PersonComponent, canActivate: [AuthGuard] }, { path: 'person/:id', component: PersonComponent, canActivate: [AuthGuard] },
{ path: 'provider/:id', component: ProviderComponent, canActivate: [AuthGuard] },
{ path: 'organisation/:id', component: OrganisationComponent, canActivate: [AuthGuard] }, { path: 'organisation/:id', component: OrganisationComponent, canActivate: [AuthGuard] },
{ path: '', redirectTo: 'tableOverview', pathMatch: 'full' }, { path: '', redirectTo: 'tableOverview', pathMatch: 'full' },
{ path: 'table', redirectTo: 'tableOverview', pathMatch: 'full' }, { path: 'table', redirectTo: 'tableOverview', pathMatch: 'full' },

@ -71,9 +71,10 @@ import { HttpLinkModule } from 'apollo-angular-link-http';
import { PersonsComponent } from './pages/tables/persons/persons.component'; import { PersonsComponent } from './pages/tables/persons/persons.component';
import { ContactInformationComponent } from './pages/tables/contact-information/contact-information.component'; import { ContactInformationComponent } from './pages/tables/contact-information/contact-information.component';
import { OrganisationsComponent } from './pages/tables/organisations/organisations.component'; import { OrganisationsComponent } from './pages/tables/organisations/organisations.component';
import { ProviderComponent } from './pages/tables/provider/provider.component'; import { ProvidersComponent } from './pages/tables/providers/providers.component';
import { OrganisationComponent } from './pages/dataPages/organisation/organisation.component'; import { OrganisationComponent } from './pages/dataPages/organisation/organisation.component';
import { PersonComponent } from './pages/dataPages/person/person.component'; import { PersonComponent } from './pages/dataPages/person/person.component';
import { ProviderComponent } from './pages/dataPages/provider/provider.component';
@ -109,9 +110,10 @@ import { PersonComponent } from './pages/dataPages/person/person.component';
PersonsComponent, PersonsComponent,
ContactInformationComponent, ContactInformationComponent,
OrganisationsComponent, OrganisationsComponent,
ProviderComponent, ProvidersComponent,
OrganisationComponent, OrganisationComponent,
PersonComponent PersonComponent,
ProviderComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

@ -9,11 +9,17 @@
<div class="data-page-wrapper" *ngIf="data"> <div class="data-page-wrapper" *ngIf="data">
<h1 class="headline"> <h1 class="headline">
{{ data[headlineDataPath] }} {{ getHeadline !== undefined ? getHeadline(data) : data[headlineDataPath] }}
<mat-icon>{{ headlineIconName }}</mat-icon> <mat-icon>{{ headlineIconName }}</mat-icon>
</h1> </h1>
<ng-container *ngFor="let object of propertiesInfo"> <ng-container *ngFor="let object of propertiesInfo">
<mat-card class="inline-card" *ngIf="object.type === 'Group'"> <mat-card
class="inline-card"
*ngIf="
object.type === 'Group' &&
(!object.hideCondition || !object.hideCondition(data))
"
>
<mat-card-title class="card-header"> <mat-card-title class="card-header">
<h2>{{ object.title }}</h2> <h2>{{ object.title }}</h2>
<button <button
@ -26,7 +32,7 @@
</mat-card-title> </mat-card-title>
<ng-container *ngFor="let prop of object.properties"> <ng-container *ngFor="let prop of object.properties">
<app-cell <app-cell
*ngIf="prop.type !== 'NumRange'" *ngIf="prop.type !== 'NumRange' && prop.type !== 'Link'"
[editable]="data.isLockedByMe && prop.acceptedForUpdating" [editable]="data.isLockedByMe && prop.acceptedForUpdating"
[required]="prop.requiredForUpdating && data.isLockedByMe" [required]="prop.requiredForUpdating && data.isLockedByMe"
(validityChange)="validityChange(prop.dataPath, $event)" (validityChange)="validityChange(prop.dataPath, $event)"
@ -41,11 +47,25 @@
[(min)]="data[prop.dataPath + '.min']" [(min)]="data[prop.dataPath + '.min']"
[(max)]="data[prop.dataPath + '.max']" [(max)]="data[prop.dataPath + '.max']"
[label]="prop.translation || prop.dataPath" [label]="prop.translation || prop.dataPath"
></app-number-range-cell ></app-number-range-cell>
></ng-container> <a
mat-button
class="link-button"
color="primary"
*ngIf="prop.type === 'Link'"
[routerLink]="prop.link(data)"
>{{ prop.linkText }}
</a>
</ng-container>
</mat-card> </mat-card>
<mat-card class="inline-card" *ngIf="object.type === 'ReferenceTable'"> <mat-card
class="inline-card"
*ngIf="
object.type === 'ReferenceTable' &&
(!object.hideCondition || !object.hideCondition(data))
"
>
<mat-card-title <mat-card-title
><h2>{{ object.title }}</h2> ><h2>{{ object.title }}</h2>
<a <a

@ -10,6 +10,10 @@
display: inline-table; display: inline-table;
min-width: 20em; min-width: 20em;
margin: 1em; margin: 1em;
.link-button {
padding: 0;
margin-top: -16px;
}
} }
} }
#floating-fab-button-box { #floating-fab-button-box {

@ -53,6 +53,9 @@ export class DataPageComponent implements OnInit, OnDestroy {
/** specifies which property should be shown in the headline */ /** specifies which property should be shown in the headline */
@Input() @Input()
headlineDataPath: string; headlineDataPath: string;
/** specifies which string should be shown in the headline. If this is provided headlineDataPath is ignored*/
@Input()
getHeadline: (any) => string;
@Input() @Input()
headlineIconName: string = 'help_outline'; headlineIconName: string = 'help_outline';
@Input() @Input()
@ -112,6 +115,9 @@ export class DataPageComponent implements OnInit, OnDestroy {
addPropertiesFromGQLSchemaToObject(infoObject: any) { addPropertiesFromGQLSchemaToObject(infoObject: any) {
for (const prop of infoObject) { for (const prop of infoObject) {
if (prop.type === 'Link') {
continue;
}
if (prop.type === 'Group') { if (prop.type === 'Group') {
this.addPropertiesFromGQLSchemaToObject(prop.properties); this.addPropertiesFromGQLSchemaToObject(prop.properties);
} else if (prop.type === 'ReferenceTable') { } else if (prop.type === 'ReferenceTable') {

@ -102,6 +102,7 @@ export class TableComponent implements AfterViewInit {
ngAfterViewInit(): void { ngAfterViewInit(): void {
this.addColumnPropertiesFromGQLSchemaToColumnInfo(); this.addColumnPropertiesFromGQLSchemaToColumnInfo();
console.log(this.columnInfo)
this.data.paginator = this.paginator; this.data.paginator = this.paginator;
this.data.sortingDataAccessor = (item, columnName) => { this.data.sortingDataAccessor = (item, columnName) => {
if (typeof item[columnName] === 'string') { if (typeof item[columnName] === 'string') {

@ -26,7 +26,7 @@ fragment OrganisationFieldsForPage on Organisation {
name name
} }
provider { provider {
...ProviderFieldsGeneral ...ProviderFieldsForPage
} }
} }

@ -0,0 +1,45 @@
query GetProviders {
providers {
...ProviderFieldsForTable
}
}
query GetProviderById($id: ID!) {
providerById(id: $id) {
...ProviderFieldsForPage
}
}
query ReloadProviderById($id: ID!) {
providerById(id: $id) {
...ProviderFieldsForTable
}
}
mutation CreateProvider($provider: ProviderCreateInput!) {
createProvider(provider: $provider) {
...ProviderFieldsForTable
}
}
mutation UpdateProvider($provider: ProviderUpdateInput!) {
updateProvider(provider: $provider) {
...ProviderFieldsForPage
}
}
mutation LockProvider($id: ID!) {
lockProvider(id: $id) {
...ProviderFieldsForPage
}
}
mutation UnlockProvider($id: ID!) {
unlockProvider(id: $id) {
...ProviderFieldsForPage
}
}
mutation DeleteProvider($id: ID!) {
deleteProvider(id: $id)
}

@ -155,26 +155,62 @@ export class BikeComponent implements OnInit {
}, },
{ {
type: 'Group', type: 'Group',
title: 'provider', title: 'Anbieter (Person)',
hideCondition: (data) => data['provider.privatePerson.person.id'] == null,
properties: [ properties: [
{ dataPath: 'provider.id', translation: '' }, {
{ dataPath: 'provider.formName', translation: '' }, type: 'Link',
{ dataPath: 'provider.privatePerson.id', translation: '' }, linkText: 'Zum Anbieter',
{ dataPath: 'provider.privatePerson.person.id', translation: '' }, link: (data) => {
{ dataPath: 'provider.privatePerson.person.name', translation: '' }, return '/provider/' + data['provider.id'];
},
},
{ dataPath: 'provider.formName', translation: 'Formular Name' },
{ {
dataPath: 'provider.privatePerson.person.firstName', dataPath: 'provider.privatePerson.person.firstName',
translation: '', translation: 'Vorname',
},
{ dataPath: 'provider.privatePerson.person.name', translation: 'Nachname' },
{
dataPath: 'provider.privatePerson.email',
translation: 'Email',
},
{
dataPath: 'provider.privatePerson.phone',
translation: 'Telefonnummer',
},
],
},
{
type: 'Group',
title: 'Anbieter (Unternehmen)',
hideCondition: (data) => data['provider.organisation.id'] == null,
properties: [
{
type: 'Link',
linkText: 'Zum Anbieter',
link: (data) => {
return '/provider/' + data['provider.id'];
},
},
{ dataPath: 'provider.organisation.name', translation: 'Name' },
{
dataPath: 'provider.organisation.address.street',
translation: 'Straße',
},
{
dataPath: 'provider.organisation.address.number',
translation: 'Hausnummer',
}, },
{ {
dataPath: 'provider.privatePerson.person.contactInformation.email', dataPath: 'provider.organisation.address.zip',
translation: '', translation: 'Postleitzahl',
}, },
], ],
}, },
{ {
type: 'Group', type: 'Group',
title: 'lendingstation', title: 'Standort',
properties: [ properties: [
{ dataPath: 'lendingStation.id', translation: '' }, { dataPath: 'lendingStation.id', translation: '' },
{ dataPath: 'lendingStation.name', translation: '' }, { dataPath: 'lendingStation.name', translation: '' },
@ -211,7 +247,15 @@ export class BikeComponent implements OnInit {
{ dataPath: 'description', translation: 'Beschreibung' }, { dataPath: 'description', translation: 'Beschreibung' },
], ],
nameToShowInSelection: (element) => { nameToShowInSelection: (element) => {
return element.title + ' (' + element.serialNo + ')' + (element.cargoBike ? " [aktuell Teil von "+element.cargoBike.name+']' : ''); return (
element.title +
' (' +
element.serialNo +
')' +
(element.cargoBike
? ' [aktuell Teil von ' + element.cargoBike.name + ']'
: '')
);
}, },
linkToTable: (element) => '/table/equipment', linkToTable: (element) => '/table/equipment',
linkToTableParams: (bike) => { linkToTableParams: (bike) => {
@ -229,7 +273,7 @@ export class BikeComponent implements OnInit {
{ {
dataPath: 'lendingStation.name', dataPath: 'lendingStation.name',
translation: 'Standort', translation: 'Standort',
link: (row) => '/lendingStation/' + row["lendingStation.id"], link: (row) => '/lendingStation/' + row['lendingStation.id'],
}, },
], ],
editableReferences: false, editableReferences: false,

@ -43,7 +43,11 @@ export class LendingStationComponent implements OnInit {
type: 'Group', type: 'Group',
title: 'Organisation', title: 'Organisation',
properties: [ properties: [
{ dataPath: 'organisation.name', translation: 'Name', link: (data)=> "/organisation/" + data["organisation.id"] }, {
dataPath: 'organisation.name',
translation: 'Name',
link: (data) => '/organisation/' + data['organisation.id'],
},
{ dataPath: 'organisation.address.street', translation: 'Straße' }, { dataPath: 'organisation.address.street', translation: 'Straße' },
{ dataPath: 'organisation.address.number', translation: 'Hausnummer' }, { dataPath: 'organisation.address.number', translation: 'Hausnummer' },
{ dataPath: 'organisation.address.zip', translation: 'Postleitzahl' }, { dataPath: 'organisation.address.zip', translation: 'Postleitzahl' },
@ -56,15 +60,15 @@ export class LendingStationComponent implements OnInit {
possibleObjects: [], possibleObjects: [],
nameToShowInSelection: (contact) => { nameToShowInSelection: (contact) => {
return ( return (
contact.person.firstName + (contact.person.firstName || '') +
' ' + ' ' +
contact.person.name + (contact.person.name || '') +
' ' + ' ' +
contact.email + (contact.email || '') +
' ' + ' ' +
contact.phone + (contact.phone || '') +
' ' + ' ' +
contact.note (contact.note || '')
); );
}, },
propertyPrefixToOverwrite: 'contactInformationIntern', propertyPrefixToOverwrite: 'contactInformationIntern',
@ -100,15 +104,15 @@ export class LendingStationComponent implements OnInit {
possibleObjects: [], possibleObjects: [],
nameToShowInSelection: (contact) => { nameToShowInSelection: (contact) => {
return ( return (
contact.person.firstName + (contact.person.firstName || '') +
' ' + ' ' +
contact.person.name + (contact.person.name || '') +
' ' + ' ' +
contact.email + (contact.email || '') +
' ' + ' ' +
contact.phone + (contact.phone || '') +
' ' + ' ' +
contact.note (contact.note || '')
); );
}, },
propertyPrefixToOverwrite: 'contactInformationExtern', propertyPrefixToOverwrite: 'contactInformationExtern',

@ -14,8 +14,8 @@ export class OrganisationComponent implements OnInit {
title: 'Allgemein', title: 'Allgemein',
properties: [ properties: [
{ dataPath: 'name', translation: 'Name' }, { dataPath: 'name', translation: 'Name' },
{ dataPath: 'address.number', translation: 'Hausnummer' },
{ dataPath: 'address.street', translation: 'Straße' }, { dataPath: 'address.street', translation: 'Straße' },
{ dataPath: 'address.number', translation: 'Hausnummer' },
{ dataPath: 'address.zip', translation: 'Postleitzahl' }, { dataPath: 'address.zip', translation: 'Postleitzahl' },
{ dataPath: 'associationNo', translation: 'Vereinsnummer' }, { dataPath: 'associationNo', translation: 'Vereinsnummer' },
@ -66,8 +66,24 @@ export class OrganisationComponent implements OnInit {
{ dataPath: 'contactInformation.note', translation: 'Anmerkung' }, { dataPath: 'contactInformation.note', translation: 'Anmerkung' },
], ],
}, },
{
type: 'Group',
title: 'Anbieterinformationen',
hideCondition: (data) => data.provider === null,
properties: [
{ dataPath: 'provider.formName', translation: 'Formularname' },
{
type: 'Link',
linkText: "Zur Anbieterseite",
link: (data) => {
return '/provider/' + data['provider.id'];
},
},
],
},
{ {
type: 'ReferenceTable', type: 'ReferenceTable',
hideCondition: (data) => data.provider === null,
title: 'Bereitgestellte Lastenräder', title: 'Bereitgestellte Lastenräder',
dataPath: 'provider.cargoBikes', dataPath: 'provider.cargoBikes',
dataService: null, dataService: null,
@ -75,31 +91,16 @@ export class OrganisationComponent implements OnInit {
{ {
dataPath: 'name', dataPath: 'name',
translation: 'Lastenrad', translation: 'Lastenrad',
link: (row) => '/bike/' + row['cargoBike.id'], link: (row) => '/bike/' + row['id'],
}, },
], ],
editableReferences: false, editableReferences: false,
linkToTable: () => '/table/provider', linkToTable: () => '/table/provider',
}, },
/*{
type: 'ReferenceTable',
title: 'Fahrräder',
dataPath: 'contactInformation',
dataService: null,
columnInfo: [
{ dataPath: 'email', translation: 'Email' },
{ dataPath: 'email2', translation: 'Email 2' },
{ dataPath: 'phone', translation: 'Telefonnummer' },
{ dataPath: 'phone2', translation: 'Telefonnummer 2' },
{ dataPath: 'note', translation: 'Anmerkung' },
],
editableReferences: false,
linkToTable: () => '/table/contactInformation',
},*/
]; ];
headlineDataPath = 'name'; headlineDataPath = 'name';
headlineIconName = 'organisation'; headlineIconName = 'business';
pageDataGQLType: string = 'Organisation'; pageDataGQLType: string = 'Organisation';
pageDataGQLUpdateInputType: string = 'OrganisationUpdateInput'; pageDataGQLUpdateInputType: string = 'OrganisationUpdateInput';

@ -1 +1,12 @@
<p>provider works!</p> <app-data-page
[dataService]="dataService"
[propertiesInfo]="propertiesInfo"
[headlineDataPath]="headlineDataPath"
[getHeadline]="getHeadline"
[headlineIconName]="headlineIconName"
[pageDataGQLType]="pageDataGQLType"
[pageDataGQLUpdateInputType]="pageDataGQLUpdateInputType"
(lockEvent)="lock($event)"
(saveEvent)="save($event)"
(cancelEvent)="cancel($event)"
></app-data-page>

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

@ -1,15 +1,123 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { bindNodeCallback } from 'rxjs';
import { BikesService } from 'src/app/services/bikes.service';
import { OrganisationsService } from 'src/app/services/organisation.service';
import { PersonsService } from 'src/app/services/person.service';
import { ProvidersService } from 'src/app/services/provider.service';
@Component({ @Component({
selector: 'app-provider', selector: 'app-provider',
templateUrl: './provider.component.html', templateUrl: './provider.component.html',
styleUrls: ['./provider.component.scss'] styleUrls: ['./provider.component.scss'],
}) })
export class ProviderComponent implements OnInit { export class ProviderComponent implements OnInit {
propertiesInfo = [
{
type: 'Group',
title: 'Allgemein',
hideCondition: (data) => data.privatePerson === null,
properties: [
{
type: 'Link',
linkText: "Zur Person",
link: (data) => {
return '/person/' + data['privatePerson.person.id'];
},
},
{ dataPath: 'privatePerson.person.firstName', translation: 'Vorname' },
{
dataPath: 'privatePerson.person.name',
translation: 'Nachname',
},
{
dataPath: 'privatePerson.phone',
translation: 'Telefonnummer',
},
{
dataPath: 'privatePerson.phone2',
translation: 'Telefonnummer 2',
},
{ dataPath: 'privatePerson.email', translation: 'Email' },
{ dataPath: 'privatePerson.email2', translation: 'Email 2' },
{ dataPath: 'privatePerson.note', translation: 'Anmerkung' },
],
},
{
type: 'Group',
title: 'Allgemein',
hideCondition: (data) => data.organisation === null,
properties: [
{
type: 'Link',
linkText: "Zum Unternehmen",
link: (data) => {
return '/organisation/' + data['organisation.id'];
},
},
{ dataPath: 'organisation.name', translation: 'Name' },
{ dataPath: 'organisation.address.street', translation: 'Straße' },
{ dataPath: 'organisation.address.number', translation: 'Hausnummer' },
{ dataPath: 'organisation.address.zip', translation: 'Postleitzahl' },
],
},
{
type: 'ReferenceTable',
title: 'Bereitgestellte Lastenräder',
dataPath: 'cargoBikes',
dataService: null,
columnInfo: [
{
dataPath: 'name',
translation: 'Name',
link: (row) => '/bike/' + row.id,
},
],
nameToShowInSelection: (bike) => {
return bike.name;
},
linkToTable: (element) => '/table/bikes',
propertyNameOfUpdateInput: 'cargoBikeIds',
},
];
constructor() { } getHeadline = (pageData) => {
return (
(pageData['privatePerson.person.firstName']
? pageData['privatePerson.person.firstName'] +
' ' +
pageData['privatePerson.person.name']
: pageData['organisation.name']) + ' (Anbieter)'
);
};
headlineDataPath = '';
headlineIconName = 'person';
pageDataGQLType: string = 'Provider';
pageDataGQLUpdateInputType: string = 'ProviderUpdateInput';
dataService: any;
constructor(
private providersService: ProvidersService,
private bikesService: BikesService
) {
this.propertiesInfo.find(
(prop) => prop.dataPath === 'cargoBikes'
).dataService = this.bikesService;
}
ngOnInit(): void { ngOnInit(): void {
this.dataService = this.providersService;
}
lock(row: any) {
this.providersService.lockProvider({ id: row.id });
}
save(row: any) {
this.providersService.updateProvider({ provider: row });
} }
cancel(row: any) {
this.providersService.unlockProvider({ id: row.id });
}
} }

@ -14,7 +14,7 @@
<mat-grid-tile class="mat-elevation-z4" routerLink = "/table/timeFrames">Zeitscheiben</mat-grid-tile> <mat-grid-tile class="mat-elevation-z4" routerLink = "/table/timeFrames">Zeitscheiben</mat-grid-tile>
<mat-grid-tile class="mat-elevation-z4" routerLink = "/table/organisations">Unternehmen</mat-grid-tile> <mat-grid-tile class="mat-elevation-z4" routerLink = "/table/organisations">Unternehmen</mat-grid-tile>
<mat-grid-tile class="mat-elevation-z4" routerLink = "/table/contactInformation">Kontaktinformation</mat-grid-tile> <mat-grid-tile class="mat-elevation-z4" routerLink = "/table/contactInformation">Kontaktinformation</mat-grid-tile>
<mat-grid-tile class="mat-elevation-z4" routerLink = "/table/bikes">Tabelle 11</mat-grid-tile> <mat-grid-tile class="mat-elevation-z4" routerLink = "/table/providers">Anbieter</mat-grid-tile>
<mat-grid-tile class="mat-elevation-z4" routerLink = "/table/bikes">Tabelle 12</mat-grid-tile> <mat-grid-tile class="mat-elevation-z4" routerLink = "/table/bikes">Tabelle 12</mat-grid-tile>
<mat-grid-tile class="mat-elevation-z4" routerLink = "/table/bikes">Tabelle 13</mat-grid-tile> <mat-grid-tile class="mat-elevation-z4" routerLink = "/table/bikes">Tabelle 13</mat-grid-tile>
<mat-grid-tile class="mat-elevation-z4" routerLink = "/table/bikes">Tabelle 14</mat-grid-tile> <mat-grid-tile class="mat-elevation-z4" routerLink = "/table/bikes">Tabelle 14</mat-grid-tile>

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

@ -1,15 +0,0 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-provider',
templateUrl: './provider.component.html',
styleUrls: ['./provider.component.scss']
})
export class ProviderComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

@ -0,0 +1,14 @@
<app-table
[headline]="headline"
[headlineIconName]="headlineIconName"
[columnInfo]="columnInfo"
[dataService]="dataService"
[tableDataGQLType]="tableDataGQLType"
[tableDataGQLCreateInputType]="tableDataGQLCreateInputType"
[tableDataGQLUpdateInputType]="tableDataGQLUpdateInputType"
(createEvent)="create($event)"
(lockEvent)="lock($event)"
(saveEvent)="save($event)"
(cancelEvent)="cancel($event)"
(deleteEvent)="delete($event)"
></app-table>

@ -0,0 +1,131 @@
import { Component, OnInit } from '@angular/core';
import { ContactInformationService } from 'src/app/services/contactInformation.service';
import { OrganisationsService } from 'src/app/services/organisation.service';
import { PersonsService } from 'src/app/services/person.service';
import { ProvidersService } from 'src/app/services/provider.service';
@Component({
selector: 'app-providers',
templateUrl: './providers.component.html',
styleUrls: ['./providers.component.scss'],
})
export class ProvidersComponent implements OnInit {
columnInfo = [
{
dataPath: 'formName',
translation: 'Formular Name',
},
{
dataPath: 'organisation.name',
translation: 'Anbieter (Unternehmen)',
link: (row: any) => {
return '/provider/' + row['id'];
},
possibleObjects: [],
nameToShowInSelection: (o) => o.name,
propertyPrefixToOverwrite: 'organisation',
currentlySelectedObjectId: (provider) => {
return provider['organisation.id'];
},
propertyNameOfReferenceId: 'organisationId',
},
{
dataPath: 'privatePerson.person.firstName',
translation: 'Anbieter (Person) Vorname',
},
{
dataPath: 'privatePerson.person.name',
translation: 'Anbieter (Person) Nachname',
link: (row: any) => {
return '/provider/' + row['id'];
},
possibleObjects: [],
nameToShowInSelection: (contact) => {
return (
(contact.person.firstName || '') +
' ' +
(contact.person.name || '') +
' ' +
(contact.email || '') +
' ' +
(contact.phone || '') +
' ' +
(contact.note || '')
);
},
propertyPrefixToOverwrite: 'privatePerson',
currentlySelectedObjectId: (provider) => {
return provider['privatePerson.id'];
},
propertyNameOfReferenceId: 'privatePersonId',
},
{
dataPath: 'privatePerson.email',
translation: 'Anbieter (Person) Email',
},
{
dataPath: 'privatePerson.phone',
translation: 'Anbieter (Person) Telefonnummer',
},
{
dataPath: 'privatePerson.note',
translation: 'Anbieter (Person) Anmerkung',
},
];
dataService: any;
tableDataGQLType: string = 'Provider';
tableDataGQLCreateInputType: string = 'ProviderCreateInput';
tableDataGQLUpdateInputType: string = 'ProviderUpdateInput';
headline = 'Anbieter';
headlineIconName = 'people';
loadingRowIds: string[] = [];
constructor(
private providersService: ProvidersService,
private contactInformationService: ContactInformationService,
private organisationsService: OrganisationsService
) {
this.organisationsService.loadTableData();
this.organisationsService.tableData.subscribe((data) => {
this.columnInfo.find(
(column) => column.propertyPrefixToOverwrite === 'organisation'
).possibleObjects = data;
});
this.contactInformationService.loadTableData();
this.contactInformationService.tableData.subscribe((data) => {
this.columnInfo.find(
(column) => column.propertyPrefixToOverwrite === 'privatePerson'
).possibleObjects = data;
});
}
ngOnInit() {
this.dataService = this.providersService;
}
create(object: { currentId: string; row: any }) {
this.providersService.createProvider(object.currentId, {
provider: object.row,
});
}
lock(row: any) {
this.providersService.lockProvider({ id: row.id });
}
save(row: any) {
this.providersService.updateProvider({ provider: row });
}
cancel(row: any) {
this.providersService.unlockProvider({ id: row.id });
}
delete(row: any) {
this.providersService.deleteProvider({ id: row.id });
}
}

@ -0,0 +1,160 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
import {
GetProvidersGQL,
ReloadProviderByIdGQL,
ReloadProviderByIdQueryVariables,
UpdateProviderGQL,
UpdateProviderMutationVariables,
LockProviderGQL,
LockProviderMutationVariables,
UnlockProviderGQL,
UnlockProviderMutationVariables,
CreateProviderGQL,
CreateProviderMutationVariables,
DeleteProviderGQL,
DeleteProviderMutationVariables,
GetProviderByIdGQL,
GetProviderByIdQueryVariables,
} from '../../generated/graphql';
@Injectable({
providedIn: 'root',
})
export class ProvidersService {
/** Providers Array */
tableData: BehaviorSubject<any[]> = new BehaviorSubject(null);
loadingRowIds: BehaviorSubject<string[]> = new BehaviorSubject([]);
successfullyCreatedRowWithId: Subject<string> = new Subject();
pageData: BehaviorSubject<any> = new BehaviorSubject(null);
isLoadingPageData: BehaviorSubject<boolean> = new BehaviorSubject(false);
constructor(
private getProvidersGQL: GetProvidersGQL,
private getProviderByIdGQL: GetProviderByIdGQL,
private reloadProviderByIdGQL: ReloadProviderByIdGQL,
private updateProviderGQL: UpdateProviderGQL,
private lockProviderGQL: LockProviderGQL,
private unlockProviderGQL: UnlockProviderGQL,
private createProviderGQL: CreateProviderGQL,
private deleteProviderGQL: DeleteProviderGQL
) {}
addLoadingRowId(id: string) {
this.loadingRowIds.next([...this.loadingRowIds.value, id]);
}
removeLoadingRowId(id: string) {
this.loadingRowIds.value.forEach((item, index) => {
if (item === id) {
this.loadingRowIds.value.splice(index, 1);
}
});
this.loadingRowIds.next(this.loadingRowIds.value);
}
loadTableData() {
this.tableData.next(null);
this.getProvidersGQL.fetch().subscribe((result) => {
this.tableData.next(result.data?.providers);
});
}
loadPageData(variables: GetProviderByIdQueryVariables) {
this.pageData.next(null);
this.isLoadingPageData.next(true);
this.getProviderByIdGQL
.fetch(variables)
.subscribe((result) => {
this.pageData.next(result.data.providerById);
})
.add(() => {
this.isLoadingPageData.next(false);
});
}
reloadProvider(variables: ReloadProviderByIdQueryVariables) {
this.addLoadingRowId(variables.id);
this.reloadProviderByIdGQL
.fetch(variables)
.subscribe((result) => {
this.updateDataRowFromResponse(result.data.providerById);
})
.add(() => {
this.removeLoadingRowId(variables.id);
});
}
createProvider(currentId: string, variables: CreateProviderMutationVariables) {
this.createProviderGQL.mutate(variables).subscribe((result) => {
const newProvider = result.data.createProvider;
this.tableData.next([newProvider, ...this.tableData.value]);
this.successfullyCreatedRowWithId.next(currentId);
});
}
updateProvider(variables: UpdateProviderMutationVariables) {
this.addLoadingRowId(variables.provider.id);
this.updateProviderGQL
.mutate(variables)
.subscribe((result) => {
this.updateDataRowFromResponse(result.data.updateProvider);
})
.add(() => {
this.removeLoadingRowId(variables.provider.id);
});
}
lockProvider(variables: LockProviderMutationVariables) {
this.addLoadingRowId(variables.id);
this.lockProviderGQL
.mutate(variables)
.subscribe((result) => {
this.updateDataRowFromResponse(result.data.lockProvider);
})
.add(() => {
this.removeLoadingRowId(variables.id);
});
}
unlockProvider(variables: UnlockProviderMutationVariables) {
this.addLoadingRowId(variables.id);
this.unlockProviderGQL
.mutate(variables)
.subscribe((result) => {
this.updateDataRowFromResponse(result.data.unlockProvider);
})
.add(() => {
this.removeLoadingRowId(variables.id);
});
}
deleteProvider(variables: DeleteProviderMutationVariables) {
this.addLoadingRowId(variables.id);
this.deleteProviderGQL
.mutate(variables)
.subscribe((result) => {
if (result.data) {
this.tableData.next(
[...this.tableData.value].filter((provider) => provider.id !== variables.id)
);
}
})
.add(() => {
this.removeLoadingRowId(variables.id);
});
}
private updateDataRowFromResponse(rowFromResponse: any) {
if (this.tableData.value) {
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.pageData.next(rowFromResponse);
}
}
}

@ -5183,13 +5183,9 @@
"name": "formName", "name": "formName",
"description": null, "description": null,
"type": { "type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
"ofType": null "ofType": null
}
}, },
"defaultValue": null "defaultValue": null
}, },
@ -5990,18 +5986,6 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "otherData",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "isLocked", "name": "isLocked",
"description": null, "description": null,
@ -6102,13 +6086,9 @@
"name": "associationNo", "name": "associationNo",
"description": "registration number of association", "description": "registration number of association",
"type": { "type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
"ofType": null "ofType": null
}
}, },
"defaultValue": null "defaultValue": null
}, },
@ -6131,16 +6111,6 @@
"ofType": null "ofType": null
}, },
"defaultValue": null "defaultValue": null
},
{
"name": "otherData",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
} }
], ],
"interfaces": null, "interfaces": null,
@ -6217,16 +6187,6 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "otherData",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "keepLock", "name": "keepLock",
"description": null, "description": null,

@ -736,7 +736,7 @@ export type Provider = {
/** (dt. Anbieter) */ /** (dt. Anbieter) */
export type ProviderCreateInput = { export type ProviderCreateInput = {
formName: Scalars['String']; formName?: Maybe<Scalars['String']>;
privatePersonId?: Maybe<Scalars['ID']>; privatePersonId?: Maybe<Scalars['ID']>;
organisationId?: Maybe<Scalars['ID']>; organisationId?: Maybe<Scalars['ID']>;
cargoBikeIds?: Maybe<Array<Scalars['ID']>>; cargoBikeIds?: Maybe<Array<Scalars['ID']>>;
@ -830,7 +830,6 @@ export type Organisation = {
registeredAt?: Maybe<Scalars['String']>; registeredAt?: Maybe<Scalars['String']>;
provider?: Maybe<Provider>; provider?: Maybe<Provider>;
contactInformation?: Maybe<ContactInformation>; contactInformation?: Maybe<ContactInformation>;
otherData?: Maybe<Scalars['String']>;
isLocked: Scalars['Boolean']; isLocked: Scalars['Boolean'];
isLockedByMe: Scalars['Boolean']; isLockedByMe: Scalars['Boolean'];
/** null if not locked by other user */ /** null if not locked by other user */
@ -842,11 +841,10 @@ export type OrganisationCreateInput = {
address: AddressCreateInput; address: AddressCreateInput;
name: Scalars['String']; name: Scalars['String'];
/** registration number of association */ /** registration number of association */
associationNo: Scalars['String']; associationNo?: Maybe<Scalars['String']>;
/** If Club, at what court registered */ /** If Club, at what court registered */
registeredAt?: Maybe<Scalars['String']>; registeredAt?: Maybe<Scalars['String']>;
contactInformationId?: Maybe<Scalars['ID']>; contactInformationId?: Maybe<Scalars['ID']>;
otherData?: Maybe<Scalars['String']>;
}; };
export type OrganisationUpdateInput = { export type OrganisationUpdateInput = {
@ -858,7 +856,6 @@ export type OrganisationUpdateInput = {
/** If Club, at what court registered */ /** If Club, at what court registered */
registeredAt?: Maybe<Scalars['String']>; registeredAt?: Maybe<Scalars['String']>;
contactInformationId?: Maybe<Scalars['ID']>; contactInformationId?: Maybe<Scalars['ID']>;
otherData?: Maybe<Scalars['String']>;
keepLock?: Maybe<Scalars['Boolean']>; keepLock?: Maybe<Scalars['Boolean']>;
}; };
@ -2123,7 +2120,7 @@ export type OrganisationFieldsForTableFragment = (
export type OrganisationFieldsForPageFragment = ( export type OrganisationFieldsForPageFragment = (
{ __typename?: 'Organisation', lendingStations?: Maybe<Array<{ __typename?: 'LendingStation', id: string, name: string }>>, provider?: Maybe<( { __typename?: 'Organisation', lendingStations?: Maybe<Array<{ __typename?: 'LendingStation', id: string, name: string }>>, provider?: Maybe<(
{ __typename?: 'Provider' } { __typename?: 'Provider' }
& ProviderFieldsGeneralFragment & ProviderFieldsForPageFragment
)> } )> }
& OrganisationFieldsForTableFragment & OrganisationFieldsForTableFragment
); );
@ -2397,6 +2394,81 @@ export type DeletePersonMutationVariables = Exact<{
export type DeletePersonMutation = { __typename?: 'Mutation', deletePerson: boolean }; export type DeletePersonMutation = { __typename?: 'Mutation', deletePerson: boolean };
export type GetProvidersQueryVariables = Exact<{ [key: string]: never; }>;
export type GetProvidersQuery = { __typename?: 'Query', providers: Array<(
{ __typename?: 'Provider' }
& ProviderFieldsForTableFragment
)> };
export type GetProviderByIdQueryVariables = Exact<{
id: Scalars['ID'];
}>;
export type GetProviderByIdQuery = { __typename?: 'Query', providerById?: Maybe<(
{ __typename?: 'Provider' }
& ProviderFieldsForPageFragment
)> };
export type ReloadProviderByIdQueryVariables = Exact<{
id: Scalars['ID'];
}>;
export type ReloadProviderByIdQuery = { __typename?: 'Query', providerById?: Maybe<(
{ __typename?: 'Provider' }
& ProviderFieldsForTableFragment
)> };
export type CreateProviderMutationVariables = Exact<{
provider: ProviderCreateInput;
}>;
export type CreateProviderMutation = { __typename?: 'Mutation', createProvider: (
{ __typename?: 'Provider' }
& ProviderFieldsForTableFragment
) };
export type UpdateProviderMutationVariables = Exact<{
provider: ProviderUpdateInput;
}>;
export type UpdateProviderMutation = { __typename?: 'Mutation', updateProvider: (
{ __typename?: 'Provider' }
& ProviderFieldsForPageFragment
) };
export type LockProviderMutationVariables = Exact<{
id: Scalars['ID'];
}>;
export type LockProviderMutation = { __typename?: 'Mutation', lockProvider: (
{ __typename?: 'Provider' }
& ProviderFieldsForPageFragment
) };
export type UnlockProviderMutationVariables = Exact<{
id: Scalars['ID'];
}>;
export type UnlockProviderMutation = { __typename?: 'Mutation', unlockProvider: (
{ __typename?: 'Provider' }
& ProviderFieldsForPageFragment
) };
export type DeleteProviderMutationVariables = Exact<{
id: Scalars['ID'];
}>;
export type DeleteProviderMutation = { __typename?: 'Mutation', deleteProvider: boolean };
export type GetTimeFramesQueryVariables = Exact<{ [key: string]: never; }>; export type GetTimeFramesQueryVariables = Exact<{ [key: string]: never; }>;
@ -2870,6 +2942,24 @@ export const OrganisationFieldsForTableFragmentDoc = gql`
} }
${OrganisationFieldsGeneralFragmentDoc} ${OrganisationFieldsGeneralFragmentDoc}
${ContactInformationFieldsGeneralFragmentDoc}`; ${ContactInformationFieldsGeneralFragmentDoc}`;
export const ProviderFieldsForTableFragmentDoc = gql`
fragment ProviderFieldsForTable on Provider {
...ProviderFieldsGeneral
isLocked
isLockedByMe
lockedBy
lockedUntil
}
${ProviderFieldsGeneralFragmentDoc}`;
export const ProviderFieldsForPageFragmentDoc = gql`
fragment ProviderFieldsForPage on Provider {
...ProviderFieldsForTable
cargoBikes {
id
name
}
}
${ProviderFieldsForTableFragmentDoc}`;
export const OrganisationFieldsForPageFragmentDoc = gql` export const OrganisationFieldsForPageFragmentDoc = gql`
fragment OrganisationFieldsForPage on Organisation { fragment OrganisationFieldsForPage on Organisation {
...OrganisationFieldsForTable ...OrganisationFieldsForTable
@ -2878,11 +2968,11 @@ export const OrganisationFieldsForPageFragmentDoc = gql`
name name
} }
provider { provider {
...ProviderFieldsGeneral ...ProviderFieldsForPage
} }
} }
${OrganisationFieldsForTableFragmentDoc} ${OrganisationFieldsForTableFragmentDoc}
${ProviderFieldsGeneralFragmentDoc}`; ${ProviderFieldsForPageFragmentDoc}`;
export const PersonFieldsForTableFragmentDoc = gql` export const PersonFieldsForTableFragmentDoc = gql`
fragment PersonFieldsForTable on Person { fragment PersonFieldsForTable on Person {
id id
@ -2903,24 +2993,6 @@ export const PersonFieldsForPageFragmentDoc = gql`
} }
${PersonFieldsForTableFragmentDoc} ${PersonFieldsForTableFragmentDoc}
${ContactInformationFieldsGeneralFragmentDoc}`; ${ContactInformationFieldsGeneralFragmentDoc}`;
export const ProviderFieldsForTableFragmentDoc = gql`
fragment ProviderFieldsForTable on Provider {
...ProviderFieldsGeneral
isLocked
isLockedByMe
lockedBy
lockedUntil
}
${ProviderFieldsGeneralFragmentDoc}`;
export const ProviderFieldsForPageFragmentDoc = gql`
fragment ProviderFieldsForPage on Provider {
...ProviderFieldsForTable
cargoBikes {
id
name
}
}
${ProviderFieldsForTableFragmentDoc}`;
export const TimeFrameFieldsFragmentDoc = gql` export const TimeFrameFieldsFragmentDoc = gql`
fragment TimeFrameFields on TimeFrame { fragment TimeFrameFields on TimeFrame {
id id
@ -3825,6 +3897,148 @@ export const DeletePersonDocument = gql`
export class DeletePersonGQL extends Apollo.Mutation<DeletePersonMutation, DeletePersonMutationVariables> { export class DeletePersonGQL extends Apollo.Mutation<DeletePersonMutation, DeletePersonMutationVariables> {
document = DeletePersonDocument; document = DeletePersonDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const GetProvidersDocument = gql`
query GetProviders {
providers {
...ProviderFieldsForTable
}
}
${ProviderFieldsForTableFragmentDoc}`;
@Injectable({
providedIn: 'root'
})
export class GetProvidersGQL extends Apollo.Query<GetProvidersQuery, GetProvidersQueryVariables> {
document = GetProvidersDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const GetProviderByIdDocument = gql`
query GetProviderById($id: ID!) {
providerById(id: $id) {
...ProviderFieldsForPage
}
}
${ProviderFieldsForPageFragmentDoc}`;
@Injectable({
providedIn: 'root'
})
export class GetProviderByIdGQL extends Apollo.Query<GetProviderByIdQuery, GetProviderByIdQueryVariables> {
document = GetProviderByIdDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const ReloadProviderByIdDocument = gql`
query ReloadProviderById($id: ID!) {
providerById(id: $id) {
...ProviderFieldsForTable
}
}
${ProviderFieldsForTableFragmentDoc}`;
@Injectable({
providedIn: 'root'
})
export class ReloadProviderByIdGQL extends Apollo.Query<ReloadProviderByIdQuery, ReloadProviderByIdQueryVariables> {
document = ReloadProviderByIdDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const CreateProviderDocument = gql`
mutation CreateProvider($provider: ProviderCreateInput!) {
createProvider(provider: $provider) {
...ProviderFieldsForTable
}
}
${ProviderFieldsForTableFragmentDoc}`;
@Injectable({
providedIn: 'root'
})
export class CreateProviderGQL extends Apollo.Mutation<CreateProviderMutation, CreateProviderMutationVariables> {
document = CreateProviderDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const UpdateProviderDocument = gql`
mutation UpdateProvider($provider: ProviderUpdateInput!) {
updateProvider(provider: $provider) {
...ProviderFieldsForPage
}
}
${ProviderFieldsForPageFragmentDoc}`;
@Injectable({
providedIn: 'root'
})
export class UpdateProviderGQL extends Apollo.Mutation<UpdateProviderMutation, UpdateProviderMutationVariables> {
document = UpdateProviderDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const LockProviderDocument = gql`
mutation LockProvider($id: ID!) {
lockProvider(id: $id) {
...ProviderFieldsForPage
}
}
${ProviderFieldsForPageFragmentDoc}`;
@Injectable({
providedIn: 'root'
})
export class LockProviderGQL extends Apollo.Mutation<LockProviderMutation, LockProviderMutationVariables> {
document = LockProviderDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const UnlockProviderDocument = gql`
mutation UnlockProvider($id: ID!) {
unlockProvider(id: $id) {
...ProviderFieldsForPage
}
}
${ProviderFieldsForPageFragmentDoc}`;
@Injectable({
providedIn: 'root'
})
export class UnlockProviderGQL extends Apollo.Mutation<UnlockProviderMutation, UnlockProviderMutationVariables> {
document = UnlockProviderDocument;
constructor(apollo: Apollo.Apollo) {
super(apollo);
}
}
export const DeleteProviderDocument = gql`
mutation DeleteProvider($id: ID!) {
deleteProvider(id: $id)
}
`;
@Injectable({
providedIn: 'root'
})
export class DeleteProviderGQL extends Apollo.Mutation<DeleteProviderMutation, DeleteProviderMutationVariables> {
document = DeleteProviderDocument;
constructor(apollo: Apollo.Apollo) { constructor(apollo: Apollo.Apollo) {
super(apollo); super(apollo);
} }

Loading…
Cancel
Save