Browse Source

Event und verschiedene Skalare hinzugefügt

tags/v0.9.1
akimmig 4 years ago
parent
commit
f3648647bc
13 changed files with 323 additions and 0 deletions
  1. +20
    -0
      server/schema.gql
  2. +2
    -0
      server/src/app.module.ts
  3. +14
    -0
      server/src/event/event.module.ts
  4. +22
    -0
      server/src/event/event.service.ts
  5. +20
    -0
      server/src/event/models/Event.ts
  6. +12
    -0
      server/src/event/models/Timeslot.ts
  7. +12
    -0
      server/src/event/resolver/event.mutation.ts
  8. +41
    -0
      server/src/event/resolver/event.query.ts
  9. +33
    -0
      server/src/event/resolver/event.ts
  10. +6
    -0
      server/src/global/global.module.ts
  11. +47
    -0
      server/src/global/scalars/Date.ts
  12. +52
    -0
      server/src/global/scalars/DateTime.ts
  13. +42
    -0
      server/src/global/scalars/Time.ts

+ 20
- 0
server/schema.gql View File

@@ -32,6 +32,24 @@ type Organizer {
_organizers: [UUID!]
}

type Timeslot {
_id: UUID!
time: Time!
}

"""A time string HH:MM:SS"""
scalar Time

type Event {
_id: UUID!
date: Date!
timeslots: [Timeslot!]!
_organizer: UUID!
}

"""A date string YYYY-MM-DD"""
scalar Date

type Query {
Person(id: UUID!): Person
PersonFind(offset: Int, limit: Int, email: String, familyName: String, givenName: String): [Person!]
@@ -39,6 +57,8 @@ type Query {
ApparatusFind(offset: Int, limit: Int, name: String): [Apparatus!]
Organizer(id: UUID!): Organizer
OrganizerFind(offset: Int, limit: Int, name: String): [Organizer!]
Event(id: UUID!): Event
EventFind(offset: Int, limit: Int, organizer: UUID, date: Date): [Event!]
}

type Mutation {

+ 2
- 0
server/src/app.module.ts View File

@@ -10,6 +10,7 @@ import { GlobalModule } from './global/global.module';
import { PersonModule } from './person/person.module';
import { ApparatusModule } from './apparatus/apparatus.module';
import { OrganizerModule } from './organizer/organizer.module'
import { EventModule } from './event/event.module'

@Module({
imports: [
@@ -17,6 +18,7 @@ import { OrganizerModule } from './organizer/organizer.module'
PersonModule,
ApparatusModule,
OrganizerModule,
EventModule,
GraphQLModule.forRoot({
installSubscriptionHandlers: true,
autoSchemaFile: 'schema.gql',

+ 14
- 0
server/src/event/event.module.ts View File

@@ -0,0 +1,14 @@
import { Module } from '@nestjs/common';
import {EventResolver} from './resolver/event'
import {EventService} from './event.service'
import {EventResolverQ} from './resolver/event.query'
import {EventResolverM} from './resolver/event.mutation'

@Module({
providers: [
EventResolverQ, EventResolverM,
EventService,
EventResolver,
],
})
export class EventModule {}

+ 22
- 0
server/src/event/event.service.ts View File

@@ -0,0 +1,22 @@
import { Injectable } from '@nestjs/common';
import { db } from '../db';
import { Event } from './models/Event';
import { Client } from '../client';
import { UUID } from '../global/scalars/UUID';

@Injectable()
export class EventService {
async findOneById(id: UUID): Promise<Event> {
const data = await db.fetch('event', { _id: id });

return data?.[0] || null as Event;
}

async find(filter: any, limit?: number, offset?: number): Promise<Event[]> {
return db.fetch('event', filter, limit, offset);
}

async update(id: UUID, ops: any, filter: any, client: Client): Promise<Event> {
return db.doOps('event', id, ops, filter, client)
}
}

+ 20
- 0
server/src/event/models/Event.ts View File

@@ -0,0 +1,20 @@
import { Field, ObjectType } from '@nestjs/graphql';
import { UUID } from '../../global/scalars/UUID';
import { Date } from '../../global/scalars/Date'
import { Timeslot } from './Timeslot'
import { Organizer } from '../../organizer/models/Organizer'

@ObjectType()
export class Event {
@Field(() => UUID,{ nullable: false })
_id: UUID

@Field(() => Date, { nullable: false })
date: Date

@Field(() => [Timeslot], { nullable: false })
timeslots: Timeslot[]

@Field(() => UUID, { nullable: false })
_organizer: Organizer
}

+ 12
- 0
server/src/event/models/Timeslot.ts View File

@@ -0,0 +1,12 @@
import { Field, ObjectType } from '@nestjs/graphql';
import { UUID } from '../../global/scalars/UUID';
import { Time } from '../../global/scalars/Time'

@ObjectType()
export class Timeslot {
@Field(() => UUID,{ nullable: false })
_id: UUID

@Field(() => Time, { nullable: false })
time: Time
}

+ 12
- 0
server/src/event/resolver/event.mutation.ts View File

@@ -0,0 +1,12 @@
import { Args, Context, Mutation, Resolver } from '@nestjs/graphql';
import { Event } from '../models/Event';
import { Client } from '../../client';
import { EventService } from '../event.service';
import { HttpException } from '@nestjs/common';

@Resolver(() => Event)
export class EventResolverM {
constructor(
private readonly service: EventService,
) {}
}

+ 41
- 0
server/src/event/resolver/event.query.ts View File

@@ -0,0 +1,41 @@
import { Args, Context, Int, Query, Resolver } from '@nestjs/graphql';
import { Event } from '../models/Event';
import { EventService } from '../event.service';
import { Client } from '../../client';
import { HttpException } from '@nestjs/common';
import { UUID } from '../../global/scalars/UUID';
import { Date } from '../../global/scalars/Date';

@Resolver(() => Event)
export class EventResolverQ {
constructor(
private readonly service: EventService,
) {}

@Query(() => Event, { nullable: true })
async Event(
@Context('client') client: Client,
@Args('id') id: UUID,
): Promise<Event> {
return await this.service.findOneById(id) as Event;
}

@Query(() => [Event], { nullable: true })
async EventFind(
@Context('client') client: Client,
@Args('date', { nullable: true }) date?: Date,
@Args('organizer', { nullable: true }) organizer?: UUID,
@Args('limit', { type: () => Int, nullable: true }) limit?: number,
@Args('offset', { type: () => Int, nullable: true }) offset?: number,
): Promise<Event[]> {
const filter: any = {}

if (date) filter.date = date;
if (organizer) filter._organizer = organizer;

let tmp = await this.service.find(filter, limit, offset);
if (tmp.length > 1000) throw new HttpException('too many results', 413);

return tmp
}
}

+ 33
- 0
server/src/event/resolver/event.ts View File

@@ -0,0 +1,33 @@
import { Context, Parent, ResolveField, Resolver } from '@nestjs/graphql';
import { Event } from '../models/Event';
import { Client } from '../../client';
import { UUID } from '../../global/scalars/UUID';
import {Date} from '../../global/scalars/Date'
import {Timeslot} from '../models/Timeslot'

@Resolver(() => Event)
export class EventResolver {
@ResolveField(() => UUID, { nullable: false })
async _id(
@Context('client') client: Client,
@Parent() parent: Event
): Promise<UUID> {
return parent._id as UUID;
}

@ResolveField(() => Date, { nullable: false })
async date(
@Context('client') client: Client,
@Parent() parent: Event
): Promise<Date> {
return parent.date;
}

@ResolveField(() => [Timeslot], { nullable: true })
async timeslots(
@Context('client') client: Client,
@Parent() parent: Event
): Promise<Timeslot[]> {
return parent.timeslots;
}
}

+ 6
- 0
server/src/global/global.module.ts View File

@@ -1,11 +1,17 @@
import { Module } from '@nestjs/common';
import { UUID } from './scalars/UUID';
import { EmailAddress } from './scalars/EmailAddress';
import { Date } from './scalars/Date'
import { DateTime } from './scalars/DateTime'
import { Time } from './scalars/Time'

@Module({
providers: [
UUID,
EmailAddress,
Date,
// DateTime,
Time,
]
})
export class GlobalModule {}

+ 47
- 0
server/src/global/scalars/Date.ts View File

@@ -0,0 +1,47 @@
import { CustomScalar, Scalar } from '@nestjs/graphql';
import { GraphQLError, Kind, ValueNode } from 'graphql';

const validate = (value: string): string => {
const DATE_REGEX = /^(18|19|20)\d{2}-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[01])$/;

if (typeof value !== 'string') {
throw new TypeError(`Value is not string: ${value}`);
}

if (!DATE_REGEX.test(value)) {
throw new TypeError(`Value is not a valid date: ${value}`);
}

const tmp = value.split('-');
if (tmp[1].length === 1) {
tmp[1] = '0' + tmp[1];
}
if (tmp[2].length === 1) {
tmp[2] = '0' + tmp[2];
}
value = tmp.join('-');

return value;
};

@Scalar('Date', () => Date)
export class Date implements CustomScalar<string, string> {
description = 'A date string YYYY-MM-DD'

parseValue(value: string): string {
return validate(value)
}

serialize(value: string): string {
return validate(value)
}

parseLiteral(ast: ValueNode): string {
if (ast.kind !== Kind.STRING) {
throw new GraphQLError(
`Can only validate strings as date but got a: ${ast.kind}`,
);
}
return validate(ast.value)
}
}

+ 52
- 0
server/src/global/scalars/DateTime.ts View File

@@ -0,0 +1,52 @@
import { CustomScalar, Scalar } from '@nestjs/graphql';
import { GraphQLError, Kind, ValueNode } from 'graphql';

const validate = (value: string): string => {
const DATE_REGEX = /^(18|19|20)\d{2}-(0?[1-9]|1[0-2])-(0?[1-9]|[12]\d|3[01])( (0?[0-9]|1[0-9]|2[0-3]):(0?[0-9]|[1-5][0-9]):(0?[0-9]|[1-5][0-9]))?$/;

if (typeof value !== 'string') {
throw new TypeError(`Value is not string: ${value}`);
}

if (!DATE_REGEX.test(value)) {
throw new TypeError(`Value is not a valid datetime: ${value}`);
}

const split = value.split(' ');
if (split.length === 1) split.push('00:00:00');

const tmp = split[0].split('-');
if (tmp[1].length === 1) tmp[1] = '0' + tmp[1];
if (tmp[2].length === 1) tmp[2] = '0' + tmp[2];
split[0] = tmp.join('-');

const time = split[1].split(':');
if(time[0].length === 1) time[0] = '0' + time[0];
if(time[1].length === 1) time[1] = '0' + time[1];
if(time[2].length === 1) time[2] = '0' + time[2];
split[1] = time.join(':');

return split.join(' ');
};

@Scalar('DateTime', () => DateTime)
export class DateTime implements CustomScalar<string, string> {
description = 'A datetime string YYYY-MM-DD HH:MM:SS'

parseValue(value: string): string {
return validate(value)
}

serialize(value: string): string {
return validate(value)
}

parseLiteral(ast: ValueNode): string {
if (ast.kind !== Kind.STRING) {
throw new GraphQLError(
`Can only validate strings as date but got a: ${ast.kind}`,
);
}
return validate(ast.value)
}
}

+ 42
- 0
server/src/global/scalars/Time.ts View File

@@ -0,0 +1,42 @@
import { CustomScalar, Scalar } from '@nestjs/graphql';
import { GraphQLError, Kind, ValueNode } from 'graphql';

const validate = (value: string): string => {
const DATE_REGEX = /^(0?[0-9]|1[0-9]|2[0-3]):(0?[0-9]|[1-5][0-9]):(0?[0-9]|[1-5][0-9])?$/;

if (typeof value !== 'string') {
throw new TypeError(`Value is not string: ${value}`);
}

if (!DATE_REGEX.test(value)) {
throw new TypeError(`Value is not a valid time: ${value}`);
}

const time = value.split(':');
if(time[0].length === 1) time[0] = '0' + time[0];
if(time[1].length === 1) time[1] = '0' + time[1];
if(time[2].length === 1) time[2] = '0' + time[2];
return time.join(':');
};

@Scalar('Time', () => Time)
export class Time implements CustomScalar<string, string> {
description = 'A time string HH:MM:SS'

parseValue(value: string): string {
return validate(value)
}

serialize(value: string): string {
return validate(value)
}

parseLiteral(ast: ValueNode): string {
if (ast.kind !== Kind.STRING) {
throw new GraphQLError(
`Can only validate strings as time but got a: ${ast.kind}`,
);
}
return validate(ast.value)
}
}

Loading…
Cancel
Save