From d83533375fe66dede759fb28d30e022bfd907e92 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Wed, 25 Nov 2020 23:52:33 +0100 Subject: [PATCH 01/11] src/dataSource/ds/utils.ts: corrected comment --- src/datasources/db/utils.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/datasources/db/utils.ts b/src/datasources/db/utils.ts index be8fbf1..995905c 100644 --- a/src/datasources/db/utils.ts +++ b/src/datasources/db/utils.ts @@ -36,7 +36,7 @@ export function genDateRange (struct: any) { } /** - * This function prepares the cargoBike struct, to be used in an update or create. + * This function helps prepare the cargoBike struct, to be used in an update or create. * It creates the numrange attributes than can be understood by postgres. * @param from * @param to @@ -50,6 +50,11 @@ function genNumRange (from: number, to: number) { return from ? '[' + from + ',' + to + ']' : null; } +/** + * This function prepares the cargoBike struct, to be used in an update or create. + * It creates the numrange attributes than can be understood by postgres. + * @param cargoBike + */ export function genBoxDimensions (cargoBike: any) { cargoBike.dimensionsAndLoad.boxLengthRange = genNumRange(cargoBike.dimensionsAndLoad.minBoxLength, cargoBike.dimensionsAndLoad.maxBoxLength); cargoBike.dimensionsAndLoad.boxWidthRange = genNumRange(cargoBike.dimensionsAndLoad.minBoxWidth, cargoBike.dimensionsAndLoad.maxBoxWidth); From 1edf15ca2402c76ff2b733a984934fc1b8a041c0 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Thu, 26 Nov 2020 10:47:53 +0100 Subject: [PATCH 02/11] src/model/cargoBike.ts: fixed data type of bikeWidth --- src/datasources/db/utils.ts | 1 + src/model/CargoBike.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/datasources/db/utils.ts b/src/datasources/db/utils.ts index 995905c..0f62e60 100644 --- a/src/datasources/db/utils.ts +++ b/src/datasources/db/utils.ts @@ -67,6 +67,7 @@ export function genBoxDimensions (cargoBike: any) { delete cargoBike.dimensionsAndLoad.minBoxHeight; delete cargoBike.dimensionsAndLoad.maxBoxHeight; } + /** * Can be used in resolvers to specify, if entry is locked by other user. * Returns true if locked by other user. diff --git a/src/model/CargoBike.ts b/src/model/CargoBike.ts index 4193a41..10b2d78 100644 --- a/src/model/CargoBike.ts +++ b/src/model/CargoBike.ts @@ -156,7 +156,7 @@ export class DimensionsAndLoad { @Column({ nullable: true, - type: 'numrange' + type: 'decimal' }) bikeWidth: number; From 2c8a5ea6b7b6c87563abcb77228ddfa52f5e18d3 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Fri, 27 Nov 2020 10:39:33 +0100 Subject: [PATCH 03/11] src/model + src/schema: removed mandatory fields --- src/model/CargoBike.ts | 20 +++++++--- src/model/ContactInformation.ts | 4 +- src/model/InsuranceData.ts | 24 +++++++++--- src/model/Taxes.ts | 4 +- src/schema/type-defs.ts | 66 ++++++++++++++++----------------- 5 files changed, 70 insertions(+), 48 deletions(-) diff --git a/src/model/CargoBike.ts b/src/model/CargoBike.ts index 10b2d78..cbd1073 100644 --- a/src/model/CargoBike.ts +++ b/src/model/CargoBike.ts @@ -90,13 +90,19 @@ export class Security { adfcCoding: string; } export class TechnicalEquipment { - @Column() + @Column({ + nullable: true + }) bicycleShift: string; - @Column() + @Column({ + nullable: true + }) isEBike: boolean; - @Column() + @Column({ + nullable: true + }) hasLightSystem: boolean; @Column({ @@ -106,10 +112,14 @@ export class TechnicalEquipment { } export class DimensionsAndLoad { - @Column() + @Column({ + nullable: true + }) hasCoverBox: boolean; - @Column() + @Column({ + nullable: true + }) lockable:boolean; @Column({ diff --git a/src/model/ContactInformation.ts b/src/model/ContactInformation.ts index 0e80f27..64e17aa 100644 --- a/src/model/ContactInformation.ts +++ b/src/model/ContactInformation.ts @@ -42,9 +42,7 @@ export class ContactInformation implements Lockable { }) participantId: number; - @Column(type => { - return Address; - }) + @Column(type => { return Address; }) address: Address; @Column({ diff --git a/src/model/InsuranceData.ts b/src/model/InsuranceData.ts index ef7c0fd..27fe256 100644 --- a/src/model/InsuranceData.ts +++ b/src/model/InsuranceData.ts @@ -20,22 +20,34 @@ This file is part of fLotte-API-Server. import { Column } from 'typeorm'; export class InsuranceData { - @Column() + @Column({ + nullable: true + }) name: string; - @Column() + @Column({ + nullable: true + }) benefactor: string; - @Column() + @Column({ + nullable: true + }) billing: string; - @Column() + @Column({ + nullable: true + }) noPnP: string; - @Column() + @Column({ + nullable: true + }) maintenanceResponsible: string; - @Column() + @Column({ + nullable: true + }) maintenanceBenefactor: string; @Column({ diff --git a/src/model/Taxes.ts b/src/model/Taxes.ts index 3c0f033..449cf27 100644 --- a/src/model/Taxes.ts +++ b/src/model/Taxes.ts @@ -25,7 +25,9 @@ export enum OrganisationArea { ZB = 'ZB' } export class Taxes { - @Column() + @Column({ + nullable: true + }) costCenter: string; @Column({ diff --git a/src/schema/type-defs.ts b/src/schema/type-defs.ts index d92729d..557f3f8 100644 --- a/src/schema/type-defs.ts +++ b/src/schema/type-defs.ts @@ -56,7 +56,7 @@ export default gql` """ Does not refer to an extra table in the database. """ - dimensionsAndLoad: DimensionsAndLoad! + dimensionsAndLoad: DimensionsAndLoad "If offset or limit is not provided, both values are ignored" bikeEvents(offset: Int, limit: Int): [BikeEvent] "If offset or limit is not provided, both values are ignored" @@ -69,7 +69,7 @@ export default gql` provider: Provider "all participants currently engaged with the cargoBike" participants: [Participant] - insuranceData: InsuranceData! + insuranceData: InsuranceData lendingStation: LendingStation taxes: Taxes currentEngagements: [Engagement] @@ -102,11 +102,11 @@ export default gql` """ Does not refer to an extra table in the database. """ - technicalEquipment: TechnicalEquipmentCreateInput! + technicalEquipment: TechnicalEquipmentCreateInput """ Does not refer to an extra table in the database. """ - dimensionsAndLoad: DimensionsAndLoadCreateInput! + dimensionsAndLoad: DimensionsAndLoadCreateInput """ Refers to equipment that is not unique. See kommentierte info tabelle -> Fragen -> Frage 2 When set to null or [], no relations will be added. @@ -122,8 +122,8 @@ export default gql` stickerBikeNameState: StickerBikeNameState note: String providerId: ID - insuranceData: InsuranceDataCreateInput! - taxes: TaxesCreateInput! + insuranceData: InsuranceDataCreateInput + taxes: TaxesCreateInput } """ @@ -180,15 +180,15 @@ export default gql` """ Eventually, this field will become an enum or a separate data table and user can choose from a pool of insurance companies. """ - name: String! - benefactor: String! - billing: String! - noPnP: String! + name: String + benefactor: String + billing: String + noPnP: String "eg. Anbieter, flotte, eigenleistung" - maintenanceResponsible: String! - maintenanceBenefactor: String! + maintenanceResponsible: String + maintenanceBenefactor: String maintenanceAgreement: String - hasFixedRate: Boolean! + hasFixedRate: Boolean fixedRate: Float """ Projektzuschuss: @@ -206,15 +206,15 @@ export default gql` """ Eventually, this field will become an enum or a separate data table and user can choose from a pool of insurance companies. """ - name: String! - benefactor: String! - billing: String! - noPnP: String! + name: String + benefactor: String + billing: String + noPnP: String "eg. Anbieter, flotte, eigenleistung" - maintenanceResponsible: String! - maintenanceBenefactor: String! + maintenanceResponsible: String + maintenanceBenefactor: String maintenanceAgreement: String - hasFixedRate: Boolean! + hasFixedRate: Boolean fixedRate: Float """ Projektzuschuss: @@ -256,9 +256,9 @@ export default gql` "How are the dimensions and how much weight can handle a bike. This data is merged in the CargoBike table and the BikeModel table." type DimensionsAndLoad { - hasCoverBox: Boolean! + hasCoverBox: Boolean "cover box can be locked" - lockable: Boolean! + lockable: Boolean minBoxLength: Float maxBoxLength: Float minBoxWidth: Float @@ -275,8 +275,8 @@ export default gql` } input DimensionsAndLoadCreateInput { - hasCoverBox: Boolean! - lockable: Boolean! + hasCoverBox: Boolean + lockable: Boolean minBoxLength: Float maxBoxLength: Float minBoxWidth: Float @@ -316,16 +316,16 @@ export default gql` So no id needed for mutation. One Mutation for the CargoBike will be enough. """ type TechnicalEquipment { - bicycleShift: String! - isEBike: Boolean! - hasLightSystem: Boolean! + bicycleShift: String + isEBike: Boolean + hasLightSystem: Boolean specialFeatures: String } input TechnicalEquipmentCreateInput { - bicycleShift: String! - isEBike: Boolean! - hasLightSystem: Boolean! + bicycleShift: String + isEBike: Boolean + hasLightSystem: Boolean specialFeatures: String } @@ -563,12 +563,12 @@ export default gql` } type Taxes { - costCenter: String! + costCenter: String organisationArea: OrganisationArea } input TaxesCreateInput { - costCenter: String! + costCenter: String organisationArea: OrganisationArea } @@ -643,7 +643,7 @@ export default gql` keepLock: Boolean } - "An Event is a point in time, when the state of the bike somehow changed." + "An Event is a point in time concerning one cargo bike of an event type. For example a chain swap." type BikeEvent { id: ID! bikeEventType: BikeEventType! From 321dc72123e6eff0607b105382f601ff1bfe174d Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Sat, 28 Nov 2020 20:29:28 +0100 Subject: [PATCH 04/11] src/model schema: added bike Status --- src/model/CargoBike.ts | 6 +++++- src/schema/type-defs.ts | 14 +++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/model/CargoBike.ts b/src/model/CargoBike.ts index cbd1073..965651a 100644 --- a/src/model/CargoBike.ts +++ b/src/model/CargoBike.ts @@ -30,7 +30,6 @@ import { DeleteDateColumn } from 'typeorm'; import { Provider } from './Provider'; -import { Participant } from './Participant'; import { InsuranceData } from './InsuranceData'; import { TimeFrame } from './TimeFrame'; import { Taxes } from './Taxes'; @@ -205,6 +204,11 @@ export class CargoBike implements Lockable { }) name: string; + @Column({ + nullable: true + }) + state: string; + @OneToMany(type => Equipment, equipment => equipment.cargoBikeId, { nullable: true, eager: true diff --git a/src/schema/type-defs.ts b/src/schema/type-defs.ts index 557f3f8..e5847cc 100644 --- a/src/schema/type-defs.ts +++ b/src/schema/type-defs.ts @@ -38,7 +38,8 @@ export default gql` id: ID! "see column A in info tabelle" group: Group - name: String + name: String! + state: BikeState modelName: String numberOfWheels: Int forCargo: Boolean @@ -83,6 +84,15 @@ export default gql` lockedUntil: Date } + """ + Status of the CargoBike. More fields will be added, or removed. + """ + enum BikeState { + ACTIVE + INACTIVE + INPREPARATION + } + """ if you want to add bike to a lending station, create a new timeFrame with to: Date = null """ @@ -90,6 +100,7 @@ export default gql` "see column A in info tabelle" group: Group! name: String! + state: BikeState modelName: String! numberOfWheels: Int! forCargo: Boolean! @@ -134,6 +145,7 @@ export default gql` "see column A in info tabelle" group: Group name: String + state: BikeState modelName: String numberOfWheels: Int forCargo: Boolean From 0754fd5f74e7b18bbffe1114c5b967bedec38f1a Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Sat, 28 Nov 2020 21:56:09 +0100 Subject: [PATCH 05/11] src/*: use type daterange for timeframes Instead of to and from, no type dataRange is used. Type DateRange still has to and from. --- src/datasources/db/lendingstationAPI.ts | 5 +---- src/datasources/db/utils.ts | 15 ++++++------- src/resolvers/lendingStationResolvers.ts | 12 ++++++----- src/schema/type-defs.ts | 27 +++++++++++++++++------- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/datasources/db/lendingstationAPI.ts b/src/datasources/db/lendingstationAPI.ts index a0f84c6..52c08ad 100644 --- a/src/datasources/db/lendingstationAPI.ts +++ b/src/datasources/db/lendingstationAPI.ts @@ -183,10 +183,7 @@ export class LendingStationAPI extends DataSource { async createTimeFrame (timeFrame: any) { return await this.connection.transaction(async (entityManager: EntityManager) => { - if (timeFrame.to === undefined) { - timeFrame.to = ''; - } - timeFrame.dateRange = '[' + timeFrame.from + ',' + timeFrame.to + ')'; + genDateRange(timeFrame); // checking for overlapping time frames const overlapping = await entityManager.getRepository(TimeFrame) .createQueryBuilder('timeframe') diff --git a/src/datasources/db/utils.ts b/src/datasources/db/utils.ts index 0f62e60..69318dc 100644 --- a/src/datasources/db/utils.ts +++ b/src/datasources/db/utils.ts @@ -23,16 +23,15 @@ import { ActionLog, Actions } from '../../model/ActionLog'; import { UserInputError } from 'apollo-server-express'; export function genDateRange (struct: any) { - if (struct.to === undefined) { - struct.to = ''; - } - struct.dateRange = '[' + struct.from + ',' + struct.to + ')'; - if (struct.from === undefined) { + if (!struct.dateRange || !struct.dateRange.from) { delete struct.dateRange; + return; + } else if (!struct.dateRange?.to) { + struct.dateRange.to = ''; + } else if (struct.dateRange.to === struct.dateRange.from) { + throw new UserInputError('Date Range can not be empty, provide different dates.'); } - // delete these keys, so the struct can be used to update the engagement entity - delete struct.from; - delete struct.to; + struct.dateRange = '[' + struct.dateRange.from + ',' + struct.dateRange.to + ')'; } /** diff --git a/src/resolvers/lendingStationResolvers.ts b/src/resolvers/lendingStationResolvers.ts index eb26f62..8cc3467 100644 --- a/src/resolvers/lendingStationResolvers.ts +++ b/src/resolvers/lendingStationResolvers.ts @@ -104,14 +104,16 @@ export default { return parent.loanTimes ? parent.loanTimes : []; } }, - TimeFrame: { + DateRange: { from (parent: any) { - return (parent.dateRange as string).split(',')[0].replace('[', ''); + return (parent as string).split(',')[0].replace('[', ''); }, - to (parent: any) { - const str = (parent.dateRange as string).split(',')[1].replace(')', ''); + to (parent: string) { + const str = (parent as string).split(',')[1].replace(')', ''); return (str.length > 0) ? str : null; - }, + } + }, + TimeFrame: { cargoBike (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { if (req.permissions.includes(Permission.ReadBike)) { return dataSources.cargoBikeAPI.cargoBikeByTimeFrameId(parent.id); diff --git a/src/schema/type-defs.ts b/src/schema/type-defs.ts index e5847cc..ff66e76 100644 --- a/src/schema/type-defs.ts +++ b/src/schema/type-defs.ts @@ -935,13 +935,26 @@ export default gql` loanTimes: [String!] } - "(dt. Zeitscheibe) When was a bike where" - type TimeFrame { - id: ID! - "format YYYY-MM-dd" + type DateRange{ from: Date! + "will be infinity of not omitted" + to: Date + } + + input DateRangeInput { "format YYYY-MM-dd" + from: Date! + """ + format YYYY-MM-dd + will be infinity of not omitted + """ to: Date + } + + "(dt. Zeitscheibe) When was a bike where" + type TimeFrame { + id: ID! + dateRange: DateRange! note: String lendingStation: LendingStation! cargoBike: CargoBike! @@ -953,8 +966,7 @@ export default gql` } input TimeFrameCreateInput { - from: Date! - to: Date + dateRange: DateRangeInput! note: String lendingStationId: ID! cargoBikeId: ID! @@ -962,8 +974,7 @@ export default gql` input TimeFrameUpdateInput { id: ID! - from: Date - to: Date + dateRange: DateRangeInput note: String lendingStationId: ID cargoBikeId: ID From b0fc6cabe39780c8b49e3f55e605d88a5f321551 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Sun, 29 Nov 2020 00:39:24 +0100 Subject: [PATCH 06/11] src/* : use numRange for box dimensions instead of minBoxWidth, etc, use range type NumRange --- src/datasources/db/utils.ts | 46 +++++++++++++++++++----------- src/resolvers/cargoBikeResolver.ts | 43 ++++------------------------ src/schema/type-defs.ts | 42 +++++++++++++++------------ 3 files changed, 59 insertions(+), 72 deletions(-) diff --git a/src/datasources/db/utils.ts b/src/datasources/db/utils.ts index 69318dc..443c9d3 100644 --- a/src/datasources/db/utils.ts +++ b/src/datasources/db/utils.ts @@ -40,13 +40,33 @@ export function genDateRange (struct: any) { * @param from * @param to */ -function genNumRange (from: number, to: number) { - if (from === null || from === undefined) { - from = to; - } else if (to === null || to === undefined) { - to = from; +function genNumRange (range: { min: number, max: number}) :string { + if (!range || (!range.max && !range.min)) { + return null; + } else if (range.min === null || range.min === undefined) { + range.min = range.max; + } else if (range.max === null || range.max === undefined) { + range.max = range.min; } - return from ? '[' + from + ',' + to + ']' : null; + if (range.min < 0) { + throw new UserInputError('Minimal value must be greater or equal to 0'); + } + return range.min ? '[' + range.min + ',' + range.max + ']' : null; +} + +export function minNumRange (parent: string) { + if (!parent || parent === 'empty') { + return null; + } + return (parent).split(',')[0].replace('[', ''); +} + +export function maxNumRange (parent: string) { + if (!parent || parent === 'empty') { + return null; + } + const str = (parent).split(',')[1].replace(']', ''); + return (str.length > 0) ? str : null; } /** @@ -55,16 +75,10 @@ function genNumRange (from: number, to: number) { * @param cargoBike */ export function genBoxDimensions (cargoBike: any) { - cargoBike.dimensionsAndLoad.boxLengthRange = genNumRange(cargoBike.dimensionsAndLoad.minBoxLength, cargoBike.dimensionsAndLoad.maxBoxLength); - cargoBike.dimensionsAndLoad.boxWidthRange = genNumRange(cargoBike.dimensionsAndLoad.minBoxWidth, cargoBike.dimensionsAndLoad.maxBoxWidth); - cargoBike.dimensionsAndLoad.boxHeightRange = genNumRange(cargoBike.dimensionsAndLoad.minBoxHeight, cargoBike.dimensionsAndLoad.maxBoxHeight); - // delete this so update cargo bike works - delete cargoBike.dimensionsAndLoad.minBoxLength; - delete cargoBike.dimensionsAndLoad.maxBoxLength; - delete cargoBike.dimensionsAndLoad.minBoxWidth; - delete cargoBike.dimensionsAndLoad.maxBoxWidth; - delete cargoBike.dimensionsAndLoad.minBoxHeight; - delete cargoBike.dimensionsAndLoad.maxBoxHeight; + if (!cargoBike.dimensionsAndLoad) { return; } + cargoBike.dimensionsAndLoad.boxLengthRange = genNumRange(cargoBike.dimensionsAndLoad.boxLengthRange); + cargoBike.dimensionsAndLoad.boxWidthRange = genNumRange(cargoBike.dimensionsAndLoad.boxWidthRange); + cargoBike.dimensionsAndLoad.boxHeightRange = genNumRange(cargoBike.dimensionsAndLoad.boxHeightRange); } /** diff --git a/src/resolvers/cargoBikeResolver.ts b/src/resolvers/cargoBikeResolver.ts index 502f181..27542dd 100644 --- a/src/resolvers/cargoBikeResolver.ts +++ b/src/resolvers/cargoBikeResolver.ts @@ -161,45 +161,12 @@ export default { isLockedByMe: (parent: any, __: any, { req }: { req: any }) => isLockedByMe(parent, { req }), isLocked: (parent: any, __: any, { req }: { req: any }) => isLocked(parent, { req }) }, - DimensionsAndLoad: { - minBoxLength: (parent: any) => { - if (!parent.boxLengthRange || parent.boxLengthRange === 'empty') { - return null; - } - return parent.boxLengthRange ? (parent.boxLengthRange as string).split(',')[0].replace('[', '') : null; - }, - maxBoxLength: (parent: any) => { - if (!parent.boxLengthRange || parent.boxLengthRange === 'empty') { - return null; - } - const str = (parent.boxLengthRange as string).split(',')[1].replace(']', ''); - return (str.length > 0) ? str : null; - }, - minBoxWidth: (parent: any) => { - if (!parent.boxWidthRange || parent.boxWidthRange === 'empty') { - return null; - } - return parent.boxWidthRange ? (parent.boxWidthRange as string).split(',')[0].replace('[', '') : null; + NumRange: { + min: (parent: string) => { + return parent.split(',')[0].replace('[', ''); }, - maxBoxWidth: (parent: any) => { - if (!parent.boxWidthRange || parent.boxWidthRange === 'empty') { - return null; - } - const str = (parent.boxWidthRange as string).split(',')[1].replace(']', ''); - return (str.length > 0) ? str : null; - }, - minBoxHeight: (parent: any) => { - if (!parent.boxHeightRange || parent.boxHeightRange === 'empty') { - return null; - } - return parent.boxHeightRange ? (parent.boxHeightRange as string).split(',')[0].replace('[', '') : null; - }, - maxBoxHeight: (parent: any) => { - if (!parent.boxHeightRange || parent.boxHeightRange === 'empty') { - return null; - } - const str = (parent.boxHeightRange as string).split(',')[1].replace(']', ''); - return (str.length > 0) ? str : null; + max: (parent: string) => { + return parent.split(',')[1].replace(']', ''); } }, Equipment: { diff --git a/src/schema/type-defs.ts b/src/schema/type-defs.ts index ff66e76..af19618 100644 --- a/src/schema/type-defs.ts +++ b/src/schema/type-defs.ts @@ -33,6 +33,7 @@ export default gql` The kind of currency depends on the database. """ scalar Money + "The CargoBike type is central to the graph. You could call it the root." type CargoBike { id: ID! @@ -266,17 +267,28 @@ export default gql` notes: String } + type NumRange { + min: Float + max: Float + } + + """ + If min or max is omitted, the omitted value will be the same as the other given value + So if you pass one as null, both values with be over written with null. + """ + input NumRangeInput { + min: Float + max: Float + } + "How are the dimensions and how much weight can handle a bike. This data is merged in the CargoBike table and the BikeModel table." type DimensionsAndLoad { hasCoverBox: Boolean "cover box can be locked" lockable: Boolean - minBoxLength: Float - maxBoxLength: Float - minBoxWidth: Float - maxBoxWidth: Float - minBoxHeight: Float - maxBoxHeight: Float + boxLengthRange: NumRange + boxWidthRange: NumRange + boxHeightRange: NumRange maxWeightBox: Float maxWeightLuggageRack: Float maxWeightTotal: Float @@ -289,12 +301,9 @@ export default gql` input DimensionsAndLoadCreateInput { hasCoverBox: Boolean lockable: Boolean - minBoxLength: Float - maxBoxLength: Float - minBoxWidth: Float - maxBoxWidth: Float - minBoxHeight: Float - maxBoxHeight: Float + boxLengthRange: NumRangeInput + boxWidthRange: NumRangeInput + boxHeightRange: NumRangeInput maxWeightBox: Float maxWeightLuggageRack: Float maxWeightTotal: Float @@ -307,12 +316,9 @@ export default gql` input DimensionsAndLoadUpdateInput { hasCoverBox: Boolean lockable: Boolean - minBoxLength: Float - maxBoxLength: Float - minBoxWidth: Float - maxBoxWidth: Float - minBoxHeight: Float - maxBoxHeight: Float + boxLengthRange: NumRangeInput + boxWidthRange: NumRangeInput + boxHeightRange: NumRangeInput maxWeightBox: Float maxWeightLuggageRack: Float maxWeightTotal: Float From f3acf1e3d8eb5c9bc0a9bd9b0f109541959b9c26 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Sun, 29 Nov 2020 00:51:05 +0100 Subject: [PATCH 07/11] src/datasources/db/utils.ts: clean up clean some unused functions --- src/datasources/db/utils.ts | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/datasources/db/utils.ts b/src/datasources/db/utils.ts index 443c9d3..4e9d38b 100644 --- a/src/datasources/db/utils.ts +++ b/src/datasources/db/utils.ts @@ -5,7 +5,20 @@ This file is part of fLotte-API-Server. fLotte-API-Server is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Soexport function minNumRange (parent: string) { + if (!parent || parent === 'empty') { + return null; + } + return (parent).split(',')[0].replace('[', ''); +} + +export function maxNumRange (parent: string) { + if (!parent || parent === 'empty') { + return null; + } + const str = (parent).split(',')[1].replace(']', ''); + return (str.length > 0) ? str : null; +}ftware Foundation, either version 3 of the License, or (at your option) any later version. fLotte-API-Server is distributed in the hope that it will be useful, @@ -54,21 +67,6 @@ function genNumRange (range: { min: number, max: number}) :string { return range.min ? '[' + range.min + ',' + range.max + ']' : null; } -export function minNumRange (parent: string) { - if (!parent || parent === 'empty') { - return null; - } - return (parent).split(',')[0].replace('[', ''); -} - -export function maxNumRange (parent: string) { - if (!parent || parent === 'empty') { - return null; - } - const str = (parent).split(',')[1].replace(']', ''); - return (str.length > 0) ? str : null; -} - /** * This function prepares the cargoBike struct, to be used in an update or create. * It creates the numrange attributes than can be understood by postgres. From 9f032ab0a109bbe3e291f2560218697005cc2d4a Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Sun, 29 Nov 2020 00:57:42 +0100 Subject: [PATCH 08/11] src/datasource/db/utils.ts: code clean up --- src/datasources/db/utils.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/datasources/db/utils.ts b/src/datasources/db/utils.ts index 4e9d38b..8e6bd96 100644 --- a/src/datasources/db/utils.ts +++ b/src/datasources/db/utils.ts @@ -5,20 +5,7 @@ This file is part of fLotte-API-Server. fLotte-API-Server is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Soexport function minNumRange (parent: string) { - if (!parent || parent === 'empty') { - return null; - } - return (parent).split(',')[0].replace('[', ''); -} - -export function maxNumRange (parent: string) { - if (!parent || parent === 'empty') { - return null; - } - const str = (parent).split(',')[1].replace(']', ''); - return (str.length > 0) ? str : null; -}ftware Foundation, either version 3 of the License, or + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. fLotte-API-Server is distributed in the hope that it will be useful, From 4a89b758de931dea02b794576d489353e879bc39 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Sun, 29 Nov 2020 13:56:06 +0100 Subject: [PATCH 09/11] src/dataSource/db/utils.ts: use template strings --- src/datasources/db/utils.ts | 11 +++++------ src/resolvers/lendingStationResolvers.ts | 6 +++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/datasources/db/utils.ts b/src/datasources/db/utils.ts index 8e6bd96..7262417 100644 --- a/src/datasources/db/utils.ts +++ b/src/datasources/db/utils.ts @@ -31,14 +31,13 @@ export function genDateRange (struct: any) { } else if (struct.dateRange.to === struct.dateRange.from) { throw new UserInputError('Date Range can not be empty, provide different dates.'); } - struct.dateRange = '[' + struct.dateRange.from + ',' + struct.dateRange.to + ')'; + struct.dateRange = `[${struct.dateRange.from},${struct.dateRange.to})`; } /** * This function helps prepare the cargoBike struct, to be used in an update or create. * It creates the numrange attributes than can be understood by postgres. - * @param from - * @param to + * @param range */ function genNumRange (range: { min: number, max: number}) :string { if (!range || (!range.max && !range.min)) { @@ -51,7 +50,7 @@ function genNumRange (range: { min: number, max: number}) :string { if (range.min < 0) { throw new UserInputError('Minimal value must be greater or equal to 0'); } - return range.min ? '[' + range.min + ',' + range.max + ']' : null; + return `[${range.min},${range.max}]`; } /** @@ -277,10 +276,10 @@ export class ActionLogger { // sometimes updates[value] is an array, e.g. timePeriods that are saved as a simple array in postgres if (updates[value] && typeof updates[value] === 'object' && !Array.isArray(updates[value])) { Object.keys(updates[value]).forEach(subValue => { - ret.push(alias + '."' + value + subValue[0].toUpperCase() + subValue.substr(1).toLowerCase() + '"'); + ret.push(`${alias}."${value}${subValue[0].toUpperCase()}${subValue.substr(1).toLowerCase()}"`); }); } else { - ret.push(alias + '."' + value + '"'); + ret.push(`${alias}."${value}"`); } }); return ret; diff --git a/src/resolvers/lendingStationResolvers.ts b/src/resolvers/lendingStationResolvers.ts index 8cc3467..f17d87f 100644 --- a/src/resolvers/lendingStationResolvers.ts +++ b/src/resolvers/lendingStationResolvers.ts @@ -105,11 +105,11 @@ export default { } }, DateRange: { - from (parent: any) { - return (parent as string).split(',')[0].replace('[', ''); + from (parent: string) { + return parent.split(',')[0].replace('[', ''); }, to (parent: string) { - const str = (parent as string).split(',')[1].replace(')', ''); + const str = parent.split(',')[1].replace(')', ''); return (str.length > 0) ? str : null; } }, From 8dfa429e227f543d85c2f74656e0bdda6b2cd799 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Sun, 29 Nov 2020 16:14:40 +0100 Subject: [PATCH 10/11] src/resolvers/*: use reg ex --- src/resolvers/cargoBikeResolver.ts | 4 ++-- src/resolvers/lendingStationResolvers.ts | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/resolvers/cargoBikeResolver.ts b/src/resolvers/cargoBikeResolver.ts index 27542dd..b90b372 100644 --- a/src/resolvers/cargoBikeResolver.ts +++ b/src/resolvers/cargoBikeResolver.ts @@ -163,10 +163,10 @@ export default { }, NumRange: { min: (parent: string) => { - return parent.split(',')[0].replace('[', ''); + return parent.replace(/^\[(.*),.*]$/, '$1'); }, max: (parent: string) => { - return parent.split(',')[1].replace(']', ''); + return parent.replace(/^\[.*,(.*)]$/, '$1'); } }, Equipment: { diff --git a/src/resolvers/lendingStationResolvers.ts b/src/resolvers/lendingStationResolvers.ts index f17d87f..91d25bb 100644 --- a/src/resolvers/lendingStationResolvers.ts +++ b/src/resolvers/lendingStationResolvers.ts @@ -106,11 +106,10 @@ export default { }, DateRange: { from (parent: string) { - return parent.split(',')[0].replace('[', ''); + return parent.replace(/^\[(.*),.*\)$/, '$1'); }, to (parent: string) { - const str = parent.split(',')[1].replace(')', ''); - return (str.length > 0) ? str : null; + return parent.replace(/^\[.*,(.*)\)$/, '$1'); } }, TimeFrame: { From fadf128fa5bb0012b7c9b879571e07e311642404 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Sun, 29 Nov 2020 16:37:31 +0100 Subject: [PATCH 11/11] README.md: update --- README.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6a46ead..682dd5f 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,16 @@ Apollo server written in typescript that handles business logic. [![Build Status](https://travis-ci.com/fLotte-meets-HWR-DB/apollo-server.svg?token=YfRmpHAXqyUafCgSEexw&branch=main)](https://travis-ci.com/fLotte-meets-HWR-DB/apollo-server) ## Assumptions -Userserver and postgres are running e.g. with Julius' Docker Compose. +The [flotte-user-management server](https://github.com/fLotte-meets-HWR-DB/flotte-user-management) and postgres are running. Set the [environment variables](#Environment-Variables) accordingly. ## Usage ### Docker +You can build and run a docker image with ```bash docker build -t . -docker run --rm -p 4000:4000 +docker run --rm -p 4000:4000 -e ... ``` -### Compile and run +Don't forget to pass all the [environment variables](#Environment-Variables) with the -e option. +### Compile and Run Install gulp if not installed ```bash npm -g gulp @@ -21,25 +23,28 @@ npm install gulp npm start ``` +You can set the [environment variables](#Environment-Variables) in a _.env_ file. ### For Development Install node\_modules and gulp ```bash npm -g gulp npm install ``` -And start gulp in watch mode +Start gulp in watch mode to recompile the type script ```bash -gulp watch +gulp watchTs ``` -This will watch *.ts files in _./src_ and recompile to _./dist_ and finally restart the server. +This will watch *.ts files in _./src_ and recompile to _./dist_. You will have to restart the server yourself. ## Environment Variables The following environment variables can be used to configure the server: ```bash RPC_HOST=host:port -NODE_ENV=development/porduction +NODE_ENV=develop/production POSTGRES_CONNECTION_URL=postgres://username:password@host:port/database_name ``` -- __RPC_HOST__ is used for the connection with the userserver. +- __RPC_HOST__ is used for the connection with the [flotte-user-management server](https://github.com/fLotte-meets-HWR-DB/flotte-user-management). - __NODE_ENV__ will not check authentication if set to development - __POSTGRES_CONNECTION_URL__ for connection with the postgres database + +If the API server cannot connect to the [flotte-user-management server](https://github.com/fLotte-meets-HWR-DB/flotte-user-management) or the postgres data base. It will try to reconnect in an endless loop.