diff --git a/Dockerfile b/Dockerfile index 824906d..42e7f3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node +FROM node AS builder WORKDIR / COPY ./src /src @@ -6,7 +6,12 @@ COPY ./package*.json ./ RUN npm install RUN npm install -g gulp RUN npm install gulp + RUN gulp +FROM node +COPY --from=builder /dist . +COPY --from=builder ./package*.json ./ +RUN npm install --production EXPOSE 4000 CMD ["npm", "start"] diff --git a/src/datasources/db/cargobikeAPI.ts b/src/datasources/db/cargobikeAPI.ts index bd47771..c4c191d 100644 --- a/src/datasources/db/cargobikeAPI.ts +++ b/src/datasources/db/cargobikeAPI.ts @@ -30,10 +30,55 @@ export class CargoBikeAPI extends DataSource { return { success: true, message: 'bla', - bike: { + cargoBike: { id, name } }; } + + async updateCargoBike ({ cargoBike }:{ cargoBike: any }) { + if (cargoBike.id) { + // update bike with given id + const bike = await this.connection.manager.createQueryBuilder() + .select('cargoBike') + .from(CargoBike, 'cargoBike') + .where('cargoBike.id = :id', { id: cargoBike.id }) + .getOne(); + if (bike) { + // bike exists + await this.connection + .createQueryBuilder() + .update(CargoBike) + .set({ name: bike.name }) + .where('id = :id', { id: bike.id }) + .execute(); + return { + success: true + }; + } else { + return { + success: false, + message: 'no bike with given id ' + cargoBike.id + ' found.' + }; + } + } else { + // create new bike + await this.connection.manager.createQueryBuilder() + .insert() + .into(CargoBike) + .values([{ + modelName: cargoBike.modelName, + numberOfWheels: cargoBike.numberOfWheels, + forCargo: cargoBike.forCargo, + forChildren: cargoBike.forChildren + } + ]) + .execute(); + return { + success: true, + message: 'new entry' + }; + } + } } diff --git a/src/model/BikeFeatures.ts b/src/model/BikeFeatures.ts index d912fe5..ef68f04 100644 --- a/src/model/BikeFeatures.ts +++ b/src/model/BikeFeatures.ts @@ -1,14 +1,16 @@ import { Column } from 'typeorm'; export abstract class Bike { - @Column() + @Column({ + nullable: true + }) description: string; @Column() modelName: string; @Column() - numerOfWheels: number; + numberOfWheels: number; @Column() forCargo: boolean; @@ -60,12 +62,18 @@ export abstract class Bike { @Column() bikeLength: number; - @Column() + @Column({ + nullable: true + }) bikeWidth: number; - @Column() + @Column({ + nullable: true + }) bikeHeight: number; - @Column() + @Column({ + nullable: true + }) bikeWeight: number; } diff --git a/src/model/CargoBike.ts b/src/model/CargoBike.ts index 85deab4..884c7d2 100644 --- a/src/model/CargoBike.ts +++ b/src/model/CargoBike.ts @@ -11,14 +11,14 @@ import { Taxes } from './Taxes'; import { Equipment } from './Equipment'; export enum Group { - KL, - LI, - SP, - FK, - MH, - SZ, - TS, - TK + KL = 'KL', + LI = 'LI', + SP = 'SP', + FK = 'FK', + MH = 'MH', + SZ = 'SZ', + TS = 'TS', + TK = 'TK' } export enum StickerBikeNameState { @@ -35,24 +35,25 @@ export class CargoBike extends Bike { @PrimaryGeneratedColumn() id: number; - @Column() + @Column({ + type: 'enum', + enum: Group + }) group: Group; @Column() name: string; - @Column() - serialNo: string; - @OneToMany(type => Equipment, equipment => equipment.cargoBike, { nullable: true }) equipment: Equipment[]; @Column({ + type: 'simple-array', nullable: true }) - otherEquipment: string; + otherEquipment: string[]; @OneToMany(type => ChainSwap, chainSwap => chainSwap.cargoBike, { nullable: true @@ -63,16 +64,24 @@ export class CargoBike extends Bike { @Column() frameNumber: string; - @Column() + @Column({ + nullable: true + }) keyNoFrameLock: string; - @Column() + @Column({ + nullable: true + }) keyNoAXAChain: string; - @Column() + @Column({ + nullable: true + }) policeCodeing: string; - @Column() + @Column({ + nullable: true + }) adfsCoding: string; @Column({ @@ -89,7 +98,9 @@ export class CargoBike extends Bike { }) provider: Provider; - @ManyToOne(type => Participant, participant => participant.cargoBikes) + @ManyToOne(type => Participant, participant => participant.cargoBikes, { + nullable: true + }) coordinator: Participant; @Column(type => InsuranceData) diff --git a/src/resolvers/cargobikeResolver.ts b/src/resolvers/cargobikeResolver.ts index 1d23d5f..a27d9a9 100644 --- a/src/resolvers/cargobikeResolver.ts +++ b/src/resolvers/cargobikeResolver.ts @@ -3,7 +3,7 @@ import { GraphQLError } from 'graphql'; export default { Query: { - CargobikeById: (_: any, { id }:{id: any}, { dataSources, req }:{dataSources: any, req: any }) => { + cargobikeById: (_: any, { id }:{id: any}, { dataSources, req }:{dataSources: any, req: any }) => { if (req.permissions.includes(Permission.ReadBike)) { return dataSources.cargoBikeAPI.findCargoBikeById({ id }); } else { @@ -18,6 +18,13 @@ export default { } else { throw new GraphQLError('Insufficient Permissions'); } + }, + cargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }:{dataSources: any, req: any }) => { + if (req.permissions.includes(Permission.WriteBike)) { + return dataSources.cargoBikeAPI.updateCargoBike({ cargoBike }); + } else { + throw new GraphQLError('Insufficient Permissions'); + } } } }; diff --git a/src/schema/type-defs.ts b/src/schema/type-defs.ts index 7a825ac..64f84ca 100644 --- a/src/schema/type-defs.ts +++ b/src/schema/type-defs.ts @@ -15,7 +15,6 @@ type CargoBike { forCargo: Boolean forChildren: Boolean numberOfChildren: Int - serialNo: String """ Safety is a custom type, that stores information about security features. TODO: Should this be calles Security? @@ -32,7 +31,7 @@ type CargoBike { events: [BikeEvent] equipment: [Equipment] "Refers to equipment that is not unique. See kommentierte info tabelle -> Fragen -> Frage 2" - otherEquipment: String + otherEquipment: [String] chainSwaps: [ChainSwap] "Sticker State" stickerBikeNameState: StickerBikeNameState @@ -181,18 +180,32 @@ enum BikeEventType { WARTUNG } -"How are the dimensions and how much weight can handle a bike." +"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 { - id: ID! - hasCoverBox: Boolean - lockable: Boolean - boxLenght: Float - boxWidth: Float - boxHeight: Float - maxWeightBox: Float - maxWeightLuggageRack: Float - maxWeightTotal: Float - bikeLength: Float + hasCoverBox: Boolean! + lockable: Boolean! + boxLenght: Float! + boxWidth: Float! + boxHeight: Float! + maxWeightBox: Float! + maxWeightLuggageRack: Float! + maxWeightTotal: Float! + bikeLength: Float! + bikeWidth: Float + bikeHeight: Float + bikeWeight: Float +} + +input DimensionsAndLoadInput { + hasCoverBox: Boolean! + lockable: Boolean! + boxLenght: Float! + boxWidth: Float! + boxHeight: Float! + maxWeightBox: Float! + maxWeightLuggageRack: Float! + maxWeightTotal: Float! + bikeLength: Float! bikeWidth: Float bikeHeight: Float bikeWeight: Float @@ -210,13 +223,20 @@ type TechnicalEquipment { specialFeatures: String } +input TechnicalEquipmentInput { + bicycleShift: String + isEBike: Boolean + hasLightingSystem: Boolean + specialFeatures: String +} + """ The Security Info about the bike. his should be 1-1 Relation with the CargoBike. So no id needed for mutation. One Mutation for the CargoBike will be enough. """ type Security { - frameNumber: String + frameNumber: String! keyNumberFrameLock: String keyNumberAXAChain: String policeCoding: String @@ -319,62 +339,70 @@ type Address { } type Query { - CargobikeById(id:ID!): CargoBike - Cargobikes(token:String!): [CargoBike]! - CargobikesByProvider(token:String!,providerId:ID!): [CargoBike]! - ProviderById(token:String!,id:ID!): Provider - Providers(token:String!): [Provider]! - ParticipantById(token:String!,id:ID!): Participant - Participants(token:String!): [ Participant]! - lendingStationById(token:String!, id:ID!): LendingStation - lendingStations(token:String!): [LendingStation]! - contactInformation(token:String!): [ContactInformation]! + cargobikeById(id:ID!): CargoBike + cargobikes: [CargoBike]! + cargobikesByProvider(providerId:ID!): [CargoBike]! + providerById(id:ID!): Provider + providers: [Provider]! + participantById(id:ID!): Participant + participants: [ Participant]! + lendingStationById(id:ID!): LendingStation + lendingStations: [LendingStation]! + contactInformation: [ContactInformation]! } type UpdateBikeResponse { - success: Boolean + success: Boolean! message: String - bike: CargoBike + cargoBike: CargoBike } input CargoBikeInput { - "if null, then new bike will be created, else old bike will be updated" + "if null, then new bike will be created, else old bike will be updated." id: ID "see column A in info tabelle" - group: Group - name: String - modelName: String - numberOfWheels: Int - forCargo: Boolean - forChildren: Boolean - numberOfChildren: Int - serialno: String + group: Group! + name: String! + modelName: String! + numberOfWheels: Int! + forCargo: Boolean! + forChildren: Boolean! + numberOfChildren: Int! """ Safety is a custom type, that stores information about security features. TODO: Should this be calles Security? """ - security: String + security: SecurityInput """ Does not refere to an extra table in the database. """ - technicalEquipment: String + technicalEquipment: TechnicalEquipmentInput """ Does not refere to an extra table in the database. """ - dimensionsAndLoad: String + dimensionsAndLoad: DimensionsAndLoadInput "Refers to equipment that is not unique. See kommentierte info tabelle -> Fragen -> Frage 2" - otherEquipment: String + otherEquipment: [String] "Sticker State" - stickerBikeNameState: String + stickerBikeNameState: StickerBikeNameState note: String provider: String insuranceData: String } + +input SecurityInput { + frameNumber: String! + keyNumberFrameLock: String + keyNumberAXAChain: String + policeCoding: String + adfcCoding: String +} + type Mutation { "for testing" addBike(id: ID!, name: String): UpdateBikeResponse! "if id: null, then new bike will be created, else old bike will be updated" - cargoBike(cargoBike: CargoBikeInput): UpdateBikeResponse! + cargoBike(cargoBike: CargoBikeInput!): UpdateBikeResponse! } `;