Browse Source

added a lot of stuff

Tomi Cvetic 4 years ago
parent
commit
009c488cfe
61 changed files with 8513 additions and 1485 deletions
  1. 1 0
      .gitignore
  2. 1 1
      backend/Dockerfile
  3. 566 273
      backend/database/generated/prisma-client/index.ts
  4. 443 87
      backend/database/generated/prisma-client/prisma-schema.ts
  5. 526 300
      backend/database/generated/prisma.graphql
  6. 41 20
      backend/datamodel.prisma
  7. 357 235
      backend/package-lock.json
  8. 16 11
      backend/package.json
  9. 22 0
      backend/schema.graphql
  10. 2 5
      backend/src/db.ts
  11. 2 2
      backend/src/file/constants.ts
  12. 24 11
      backend/src/file/resolvers.ts
  13. 4204 0
      backend/src/gql/resolvers.ts
  14. 7 13
      backend/src/index.ts
  15. 140 96
      backend/src/training/resolvers.ts
  16. 1 0
      backend/src/user/resolvers.ts
  17. 3 7
      backend/tsconfig.json
  18. 8 0
      codegen.yml
  19. 2 0
      docker-compose.yml
  20. 62 0
      frontend/package-lock.json
  21. 2 0
      frontend/package.json
  22. 0 0
      frontend/pages/admin/block/[id].tsx
  23. 25 0
      frontend/pages/admin/block/index.tsx
  24. 0 0
      frontend/pages/admin/exercise/[id].tsx
  25. 25 0
      frontend/pages/admin/exercise/index.tsx
  26. 0 0
      frontend/pages/admin/file/[id].tsx
  27. 12 0
      frontend/pages/admin/file/index.tsx
  28. 74 37
      frontend/pages/admin/training/index.tsx
  29. 7 8
      frontend/pages/index.tsx
  30. 127 0
      frontend/src/app/components/AdminList.tsx
  31. 17 2
      frontend/src/app/components/AdminSideBar.tsx
  32. 1 1
      frontend/src/app/components/Logo.tsx
  33. 18 1
      frontend/src/app/components/Nav.tsx
  34. 10 1
      frontend/src/app/components/Search.tsx
  35. 2 1
      frontend/src/app/index.tsx
  36. 113 0
      frontend/src/file/components/UploadFile.tsx
  37. 27 0
      frontend/src/file/file.graphql
  38. 3 0
      frontend/src/file/index.ts
  39. 9 0
      frontend/src/file/utils.ts
  40. 21 0
      frontend/src/form/components/Form.tsx
  41. 0 1
      frontend/src/form/components/TextInput.tsx
  42. 7 8
      frontend/src/form/hooks/useForm.tsx
  43. 400 114
      frontend/src/gql/index.tsx
  44. 5 11
      frontend/src/lib/apollo.ts
  45. 1 0
      frontend/src/styles/global.ts
  46. 82 46
      frontend/src/styles/theme.ts
  47. 1 1
      frontend/src/training/components/BlockInstanceInputs.tsx
  48. 3 4
      frontend/src/training/components/EditTraining.tsx
  49. 0 1
      frontend/src/training/components/RegistrationButton.tsx
  50. 1 0
      frontend/src/training/components/Registrations.tsx
  51. 8 9
      frontend/src/training/components/TrainingArchive.tsx
  52. 6 2
      frontend/src/training/components/TrainingHint.tsx
  53. 0 99
      frontend/src/training/components/TrainingType.tsx
  54. 60 0
      frontend/src/training/components/TrainingTypeButton.tsx
  55. 68 22
      frontend/src/training/training.graphql
  56. 9 25
      frontend/src/training/types.ts
  57. 10 6
      frontend/src/user/components/UserNav.tsx
  58. 1 8
      frontend/tsconfig.json
  59. 909 0
      package-lock.json
  60. 3 1
      package.json
  61. 18 15
      proxy/nginx.conf

+ 1 - 0
.gitignore

@@ -30,6 +30,7 @@ yarn-error.log*
 
 # media
 media/
+upload_files/
 
 # database backup
 dbBackup/

+ 1 - 1
backend/Dockerfile

@@ -1,4 +1,4 @@
-FROM node:alpine
+FROM node:lts-alpine
 
 WORKDIR /app
 

File diff suppressed because it is too large
+ 566 - 273
backend/database/generated/prisma-client/index.ts


File diff suppressed because it is too large
+ 443 - 87
backend/database/generated/prisma-client/prisma-schema.ts


File diff suppressed because it is too large
+ 526 - 300
backend/database/generated/prisma.graphql


+ 41 - 20
backend/datamodel.prisma

@@ -10,6 +10,7 @@ type User {
     ratings: [Rating!]!
     permissions: [Permission!]!  @scalarList(strategy: RELATION)
     interests: [String!]!  @scalarList(strategy: RELATION)
+    avatar: Picture
 }
 
 enum Permission {
@@ -17,20 +18,6 @@ enum Permission {
     INSTRUCTOR
 }
 
-type File {
-    id: ID! @id
-    createdAt: DateTime! @createdAt
-    updatedAt: DateTime! @updatedAt
-    path: String!
-    mimetype: String!
-    user: User!
-    thumbnail: String
-    filename: String!
-    encoding: String!
-    size: Int!
-    comment: String
-}
-
 type Training {
     id: ID! @id
     title: String!
@@ -55,15 +42,15 @@ type Block {
     id: ID! @id
     title: String!
     description: String
-    videos: [String!]! @scalarList(strategy: RELATION)
-    pictures: [String!]! @scalarList(strategy: RELATION)
     duration: Int
     format: Format!
     rest: Int
     tracks: [Track!]!
+    videos: [String!]! @scalarList(strategy: RELATION)
+    pictures: [String!]! @scalarList(strategy: RELATION)
     blocks: [BlockInstance!] @relation(name: "Instances", onDelete: CASCADE)
-    links: [BlockInstance!]! @relation(name: "ParentChild", onDelete: CASCADE)
-    exercises: [ExerciseInstance!]! @relation(onDelete: CASCADE)
+    parentBlockInstances: [BlockInstance!]! @relation(name: "ParentChild", onDelete: CASCADE)
+    exercises: [ExerciseInstance!]! @relation(name: "BlockExercises", onDelete: CASCADE)
 }
 
 type BlockInstance {
@@ -82,12 +69,44 @@ type Format {
     description: String!
 }
 
+type File {
+    id: ID! @id
+    createdAt: DateTime! @createdAt
+    updatedAt: DateTime! @updatedAt
+    path: String!
+    mimetype: String!
+    user: User!
+    thumbnail: String
+    filename: String!
+    encoding: String!
+    size: Int!
+    comment: String
+}
+
 type Track {
     id: ID! @id
     title: String!
     artist: String!
     duration: Int!
-    link: String!
+    file: File
+    link: String
+}
+
+type Video {
+    id: ID! @id
+    title: String!
+    description: String!
+    duration: Int!
+    file: File
+    link: String
+}
+
+type Picture {
+    id: ID! @id
+    title: String!
+    description: String!
+    file: File
+    link: String
 }
 
 type Exercise {
@@ -98,14 +117,16 @@ type Exercise {
     pictures: [String!]! @scalarList(strategy: RELATION)
     targets: [String!]! @scalarList(strategy: RELATION)
     baseExercise: [String!]! @scalarList(strategy: RELATION)
+    parentExerciseInstances: [ExerciseInstance!]! 
 }
 
 type ExerciseInstance {
     id: ID! @id
-    exercise: Exercise! @relation(link: INLINE)
+    exercise: Exercise! @relation(link: TABLE)
     order: Int!
     repetitions: Int
     variation: String
+    parentBlockInstances: Block! @relation(name: "BlockExercises")
 }
 
 type Rating {

File diff suppressed because it is too large
+ 357 - 235
backend/package-lock.json


+ 16 - 11
backend/package.json

@@ -9,18 +9,18 @@
     "start": "concurrently -k -p \"[{name}]\" -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch-ts\" \"npm run server\"",
     "dev": "nodemon -e ts,js,graphql -x node --inspect index.ts",
     "deploy": "prisma deploy",
-    "test": "jest --watch"
+    "test": "jest --watch",
+    "preinstall": "npx npm-force-resolutions"
   },
   "author": "Tomi Cvetic <tomi.cvetic@gmail.com>",
   "license": "GPL-3.0",
   "dependencies": {
     "@types/bcryptjs": "^2.4.2",
     "@types/cookie-parser": "^1.4.2",
-    "@types/jsonwebtoken": "^8.3.8",
-    "@types/lodash": "^4.14.149",
+    "@types/jsonwebtoken": "^8.3.9",
     "@types/randombytes": "^2.0.0",
     "@types/sharp": "^0.24.0",
-    "apollo-server-express": "2.11.0",
+    "apollo-server-express": "^2.12.0",
     "bcryptjs": "^2.4.3",
     "body-parser": "1.19.0",
     "cookie-parser": "1.4.4",
@@ -28,26 +28,31 @@
     "date-fns": "2.11.1",
     "dotenv": "8.2.0",
     "graphql": "^14.6.0",
-    "graphql-yoga": "1.18.3",
     "jsonwebtoken": "^8.5.1",
     "nodemailer": "^6.4.6",
     "prisma": "^1.34.10",
     "prisma-binding": "2.3.16",
     "promisify": "0.0.3",
     "randombytes": "^2.1.0",
-    "sharp": "^0.25.2",
-    "standard": "14.3.1"
+    "sharp": "^0.25.2"
   },
   "devDependencies": {
     "@babel/preset-typescript": "^7.9.0",
-    "@typescript-eslint/eslint-plugin": "^2.26.0",
-    "@typescript-eslint/parser": "^2.26.0",
+    "@typescript-eslint/eslint-plugin": "^2.29.0",
+    "@typescript-eslint/parser": "^2.29.0",
     "babel-plugin-module-resolver": "^4.0.0",
     "concurrently": "^5.1.0",
     "graphql-cli": "3.0.14",
-    "jest": "^25.2.4",
+    "jest": "^25.4.0",
     "nodemon": "1.19.4",
-    "ts-jest": "^25.3.0",
+    "ts-jest": "^25.4.0",
     "typescript": "^3.8.3"
+  },
+  "resolutions": {
+    "**/graphql-upload": "^9.0.0",
+    "**/**/graphql-upload": "^9.0.0",
+    "**/**/**/graphql-upload": "^9.0.0",
+    "**/**/**/**/graphql-upload": "^9.0.0",
+    "**/**/**/**/**/graphql-upload": "^9.0.0"
   }
 }

+ 22 - 0
backend/schema.graphql

@@ -10,8 +10,26 @@ type FsFile {
   mtime: DateTime!
 }
 
+type TrainingArchiveItem {
+  id: ID!
+  title: String!
+  type: TrainingType!
+  trainingDate: DateTime!
+  location: String!
+  attendance: Int
+  ratings: Float
+  blocks: [String!]!
+  duration: Int
+}
+
+type TrainingArchive {
+  trainings: [TrainingArchiveItem!]!
+  totalCount: Int!
+}
+
 type Query {
   # Training module
+  trainingArchive(skip: Int, first: Int): TrainingArchive!
   publishedTrainings(
     where: TrainingWhereInput
     orderBy: TrainingOrderByInput
@@ -90,9 +108,12 @@ type Mutation {
   # File module
   uploadFile(file: Upload!, comment: String): File!
 
+  # User module
   createUser(data: UserCreateInput!): User!
   updateUser(email: String!, data: UserUpdateInput!): User
   deleteUser(email: String!): User
+
+  # Training module
   createTraining(
     title: String!
     type: TrainingTypeCreateOneInput!
@@ -102,6 +123,7 @@ type Mutation {
     published: Boolean!
     blocks: BlockInstanceCreateManyWithoutParentTrainingInput
   ): Training!
+  deleteTraining(id: ID!): Training!
   updateTraining(where: TrainingWhereUniqueInput!, data: TrainingUpdateInput!): Training!
   createTrainingType(name: String!, description: String!): TrainingType!
   # createBlock(

+ 2 - 5
backend/src/db.ts

@@ -10,15 +10,12 @@ export const db = new Prisma({
   typeDefs,
   endpoint: process.env.PRISMA_ENDPOINT,
   secret: process.env.PRISMA_SECRET,
-  debug: false
+  debug: false,
 })
 
 export const populateUser = async (req: any, res: any, next: any) => {
   if (!req.userId) return next()
-  const user = await db.query.user(
-    { where: { id: req.userId } },
-    '{id, email, name, permissions}'
-  )
+  const user = await db.query.user({ where: { id: req.userId } }, '{id, email, name, permissions}')
   req.user = user
   next()
 }

+ 2 - 2
backend/src/file/constants.ts

@@ -1,3 +1,3 @@
-export const tmpDir = 'tmp'
+export const tmpDir = 'upload_files/tmp'
 export const uploadDir = 'upload_files'
-export const thumbnails = 'thumbnails'
+export const thumbnails = 'thumbnails'

+ 24 - 11
backend/src/file/resolvers.ts

@@ -15,7 +15,7 @@ export const resolvers: IResolvers = {
     files: (parent, args, context, info) => {
       user.checkPermission(context, 'ADMIN')
       return context.db.query.files(args, info)
-    }
+    },
   },
   Mutation: {
     uploadFile: async (parent, { comment, file }, context, info) => {
@@ -27,19 +27,19 @@ export const resolvers: IResolvers = {
           data: {
             ...fileInfo,
             comment,
-            user: { connect: { id: context.req.userId } }
-          }
+            user: { connect: { id: context.req.userId } },
+          },
         },
         info
       )
-    }
-  }
+    },
+  },
 }
 
 async function fsFiles(directory: string) {
   const fileList = await fs.promises.readdir(directory)
   return Promise.all(
-    fileList.map(async filename => {
+    fileList.map(async (filename) => {
       const path = `${directory}/${filename}`
       const { size, ctime, mtime } = await fs.promises.stat(path)
       return {
@@ -47,7 +47,7 @@ async function fsFiles(directory: string) {
         path,
         size,
         ctime,
-        mtime
+        mtime,
       }
     })
   )
@@ -64,7 +64,7 @@ async function uploadFile(file: any) {
   await new Promise((resolve, reject) => {
     const file = fs.createWriteStream(tmpPath)
     file.on('finish', resolve)
-    file.on('error', error => {
+    file.on('error', (error) => {
       fs.unlink(tmpPath, () => {
         reject(error)
       })
@@ -74,6 +74,7 @@ async function uploadFile(file: any) {
   })
 
   if (mimetype.startsWith('image/')) {
+    console.log('image')
     try {
       await processImage(tmpPath, path)
       await createThumbnail(tmpPath, thumbnailPath)
@@ -85,6 +86,18 @@ async function uploadFile(file: any) {
       } catch (ignore) {}
       throw error
     }
+  } else {
+    console.log('no image')
+    try {
+      console.log(tmpPath)
+      await fs.promises.rename(tmpPath, path)
+    } catch (error) {
+      try {
+        await fs.promises.unlink(tmpPath)
+        await fs.promises.unlink(path)
+      } catch (ignore) {}
+      throw error
+    }
   }
 
   const { size } = await fs.promises.stat(path)
@@ -94,7 +107,7 @@ async function uploadFile(file: any) {
     path,
     mimetype,
     encoding,
-    size
+    size,
   }
 }
 
@@ -102,7 +115,7 @@ function processImage(tmpFile: string, outputFile: string) {
   return sharp(tmpFile)
     .resize(1600, 1600, {
       fit: sharp.fit.inside,
-      withoutEnlargement: true
+      withoutEnlargement: true,
     })
     .jpeg()
     .toFile(outputFile)
@@ -111,7 +124,7 @@ function processImage(tmpFile: string, outputFile: string) {
 function createThumbnail(tmpFile: string, thumbnail: string) {
   return sharp(tmpFile)
     .resize(200, 200, {
-      fit: sharp.fit.inside
+      fit: sharp.fit.inside,
     })
     .jpeg()
     .toFile(thumbnail)

+ 4204 - 0
backend/src/gql/resolvers.ts

@@ -0,0 +1,4204 @@
+import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql';
+export type Maybe<T> = T | null;
+export type RequireFields<T, K extends keyof T> = { [X in Exclude<keyof T, K>]?: T[X] } & { [P in K]-?: NonNullable<T[P]> };
+/** All built-in and custom scalars, mapped to their actual values */
+export type Scalars = {
+  ID: string,
+  String: string,
+  Boolean: boolean,
+  Int: number,
+  Float: number,
+  DateTime: any,
+  Upload: any,
+};
+
+export type AggregateTraining = {
+   __typename?: 'AggregateTraining',
+  count: Scalars['Int'],
+};
+
+export type Block = Node & {
+   __typename?: 'Block',
+  id: Scalars['ID'],
+  title: Scalars['String'],
+  description?: Maybe<Scalars['String']>,
+  videos: Array<Scalars['String']>,
+  pictures: Array<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  format: Format,
+  rest?: Maybe<Scalars['Int']>,
+  tracks?: Maybe<Array<Track>>,
+  blocks?: Maybe<Array<BlockInstance>>,
+  parentBlockInstances?: Maybe<Array<BlockInstance>>,
+  exercises?: Maybe<Array<ExerciseInstance>>,
+};
+
+
+export type BlockTracksArgs = {
+  where?: Maybe<TrackWhereInput>,
+  orderBy?: Maybe<TrackOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type BlockBlocksArgs = {
+  where?: Maybe<BlockInstanceWhereInput>,
+  orderBy?: Maybe<BlockInstanceOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type BlockParentBlockInstancesArgs = {
+  where?: Maybe<BlockInstanceWhereInput>,
+  orderBy?: Maybe<BlockInstanceOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type BlockExercisesArgs = {
+  where?: Maybe<ExerciseInstanceWhereInput>,
+  orderBy?: Maybe<ExerciseInstanceOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+export type BlockCreateOneWithoutBlocksInput = {
+  create?: Maybe<BlockCreateWithoutBlocksInput>,
+  connect?: Maybe<BlockWhereUniqueInput>,
+};
+
+export type BlockCreateOneWithoutParentBlockInstancesInput = {
+  create?: Maybe<BlockCreateWithoutParentBlockInstancesInput>,
+  connect?: Maybe<BlockWhereUniqueInput>,
+};
+
+export type BlockCreatepicturesInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type BlockCreatevideosInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type BlockCreateWithoutBlocksInput = {
+  id?: Maybe<Scalars['ID']>,
+  title: Scalars['String'],
+  description?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  rest?: Maybe<Scalars['Int']>,
+  videos?: Maybe<BlockCreatevideosInput>,
+  pictures?: Maybe<BlockCreatepicturesInput>,
+  format: FormatCreateOneInput,
+  tracks?: Maybe<TrackCreateManyInput>,
+  parentBlockInstances?: Maybe<BlockInstanceCreateManyWithoutBlockInput>,
+  exercises?: Maybe<ExerciseInstanceCreateManyWithoutParentBlockInstancesInput>,
+};
+
+export type BlockCreateWithoutParentBlockInstancesInput = {
+  id?: Maybe<Scalars['ID']>,
+  title: Scalars['String'],
+  description?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  rest?: Maybe<Scalars['Int']>,
+  videos?: Maybe<BlockCreatevideosInput>,
+  pictures?: Maybe<BlockCreatepicturesInput>,
+  format: FormatCreateOneInput,
+  tracks?: Maybe<TrackCreateManyInput>,
+  blocks?: Maybe<BlockInstanceCreateManyWithoutParentBlockInput>,
+  exercises?: Maybe<ExerciseInstanceCreateManyWithoutParentBlockInstancesInput>,
+};
+
+export type BlockInstance = Node & {
+   __typename?: 'BlockInstance',
+  id: Scalars['ID'],
+  block: Block,
+  parentBlock?: Maybe<Block>,
+  parentTraining?: Maybe<Training>,
+  order: Scalars['Int'],
+  rounds?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+};
+
+export type BlockInstanceCreateManyWithoutBlockInput = {
+  create?: Maybe<Array<BlockInstanceCreateWithoutBlockInput>>,
+  connect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+};
+
+export type BlockInstanceCreateManyWithoutParentBlockInput = {
+  create?: Maybe<Array<BlockInstanceCreateWithoutParentBlockInput>>,
+  connect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+};
+
+export type BlockInstanceCreateManyWithoutParentTrainingInput = {
+  create?: Maybe<Array<BlockInstanceCreateWithoutParentTrainingInput>>,
+  connect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+};
+
+export type BlockInstanceCreateWithoutBlockInput = {
+  id?: Maybe<Scalars['ID']>,
+  order: Scalars['Int'],
+  rounds?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  parentBlock?: Maybe<BlockCreateOneWithoutBlocksInput>,
+  parentTraining?: Maybe<TrainingCreateOneWithoutBlocksInput>,
+};
+
+export type BlockInstanceCreateWithoutParentBlockInput = {
+  id?: Maybe<Scalars['ID']>,
+  order: Scalars['Int'],
+  rounds?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  block: BlockCreateOneWithoutParentBlockInstancesInput,
+  parentTraining?: Maybe<TrainingCreateOneWithoutBlocksInput>,
+};
+
+export type BlockInstanceCreateWithoutParentTrainingInput = {
+  id?: Maybe<Scalars['ID']>,
+  order: Scalars['Int'],
+  rounds?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  block: BlockCreateOneWithoutParentBlockInstancesInput,
+  parentBlock?: Maybe<BlockCreateOneWithoutBlocksInput>,
+};
+
+export enum BlockInstanceOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  OrderAsc = 'order_ASC',
+  OrderDesc = 'order_DESC',
+  RoundsAsc = 'rounds_ASC',
+  RoundsDesc = 'rounds_DESC',
+  VariationAsc = 'variation_ASC',
+  VariationDesc = 'variation_DESC'
+}
+
+export type BlockInstanceScalarWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<BlockInstanceScalarWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<BlockInstanceScalarWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<BlockInstanceScalarWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  order?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  order_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  order_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  order_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  order_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  order_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  order_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  order_gte?: Maybe<Scalars['Int']>,
+  rounds?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  rounds_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  rounds_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  rounds_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  rounds_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  rounds_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  rounds_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  rounds_gte?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  variation_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  variation_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  variation_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  variation_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  variation_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  variation_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  variation_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  variation_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  variation_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  variation_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  variation_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  variation_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  variation_not_ends_with?: Maybe<Scalars['String']>,
+};
+
+export type BlockInstanceUpdateManyDataInput = {
+  order?: Maybe<Scalars['Int']>,
+  rounds?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+};
+
+export type BlockInstanceUpdateManyWithoutBlockInput = {
+  create?: Maybe<Array<BlockInstanceCreateWithoutBlockInput>>,
+  connect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  set?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  disconnect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  delete?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  update?: Maybe<Array<BlockInstanceUpdateWithWhereUniqueWithoutBlockInput>>,
+  updateMany?: Maybe<Array<BlockInstanceUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<BlockInstanceScalarWhereInput>>,
+  upsert?: Maybe<Array<BlockInstanceUpsertWithWhereUniqueWithoutBlockInput>>,
+};
+
+export type BlockInstanceUpdateManyWithoutParentBlockInput = {
+  create?: Maybe<Array<BlockInstanceCreateWithoutParentBlockInput>>,
+  connect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  set?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  disconnect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  delete?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  update?: Maybe<Array<BlockInstanceUpdateWithWhereUniqueWithoutParentBlockInput>>,
+  updateMany?: Maybe<Array<BlockInstanceUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<BlockInstanceScalarWhereInput>>,
+  upsert?: Maybe<Array<BlockInstanceUpsertWithWhereUniqueWithoutParentBlockInput>>,
+};
+
+export type BlockInstanceUpdateManyWithoutParentTrainingInput = {
+  create?: Maybe<Array<BlockInstanceCreateWithoutParentTrainingInput>>,
+  connect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  set?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  disconnect?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  delete?: Maybe<Array<BlockInstanceWhereUniqueInput>>,
+  update?: Maybe<Array<BlockInstanceUpdateWithWhereUniqueWithoutParentTrainingInput>>,
+  updateMany?: Maybe<Array<BlockInstanceUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<BlockInstanceScalarWhereInput>>,
+  upsert?: Maybe<Array<BlockInstanceUpsertWithWhereUniqueWithoutParentTrainingInput>>,
+};
+
+export type BlockInstanceUpdateManyWithWhereNestedInput = {
+  where: BlockInstanceScalarWhereInput,
+  data: BlockInstanceUpdateManyDataInput,
+};
+
+export type BlockInstanceUpdateWithoutBlockDataInput = {
+  order?: Maybe<Scalars['Int']>,
+  rounds?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  parentBlock?: Maybe<BlockUpdateOneWithoutBlocksInput>,
+  parentTraining?: Maybe<TrainingUpdateOneWithoutBlocksInput>,
+};
+
+export type BlockInstanceUpdateWithoutParentBlockDataInput = {
+  order?: Maybe<Scalars['Int']>,
+  rounds?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  block?: Maybe<BlockUpdateOneRequiredWithoutParentBlockInstancesInput>,
+  parentTraining?: Maybe<TrainingUpdateOneWithoutBlocksInput>,
+};
+
+export type BlockInstanceUpdateWithoutParentTrainingDataInput = {
+  order?: Maybe<Scalars['Int']>,
+  rounds?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  block?: Maybe<BlockUpdateOneRequiredWithoutParentBlockInstancesInput>,
+  parentBlock?: Maybe<BlockUpdateOneWithoutBlocksInput>,
+};
+
+export type BlockInstanceUpdateWithWhereUniqueWithoutBlockInput = {
+  where: BlockInstanceWhereUniqueInput,
+  data: BlockInstanceUpdateWithoutBlockDataInput,
+};
+
+export type BlockInstanceUpdateWithWhereUniqueWithoutParentBlockInput = {
+  where: BlockInstanceWhereUniqueInput,
+  data: BlockInstanceUpdateWithoutParentBlockDataInput,
+};
+
+export type BlockInstanceUpdateWithWhereUniqueWithoutParentTrainingInput = {
+  where: BlockInstanceWhereUniqueInput,
+  data: BlockInstanceUpdateWithoutParentTrainingDataInput,
+};
+
+export type BlockInstanceUpsertWithWhereUniqueWithoutBlockInput = {
+  where: BlockInstanceWhereUniqueInput,
+  update: BlockInstanceUpdateWithoutBlockDataInput,
+  create: BlockInstanceCreateWithoutBlockInput,
+};
+
+export type BlockInstanceUpsertWithWhereUniqueWithoutParentBlockInput = {
+  where: BlockInstanceWhereUniqueInput,
+  update: BlockInstanceUpdateWithoutParentBlockDataInput,
+  create: BlockInstanceCreateWithoutParentBlockInput,
+};
+
+export type BlockInstanceUpsertWithWhereUniqueWithoutParentTrainingInput = {
+  where: BlockInstanceWhereUniqueInput,
+  update: BlockInstanceUpdateWithoutParentTrainingDataInput,
+  create: BlockInstanceCreateWithoutParentTrainingInput,
+};
+
+export type BlockInstanceWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<BlockInstanceWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<BlockInstanceWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<BlockInstanceWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  order?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  order_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  order_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  order_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  order_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  order_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  order_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  order_gte?: Maybe<Scalars['Int']>,
+  rounds?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  rounds_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  rounds_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  rounds_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  rounds_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  rounds_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  rounds_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  rounds_gte?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  variation_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  variation_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  variation_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  variation_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  variation_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  variation_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  variation_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  variation_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  variation_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  variation_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  variation_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  variation_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  variation_not_ends_with?: Maybe<Scalars['String']>,
+  block?: Maybe<BlockWhereInput>,
+  parentBlock?: Maybe<BlockWhereInput>,
+  parentTraining?: Maybe<TrainingWhereInput>,
+};
+
+export type BlockInstanceWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+export enum BlockOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  TitleAsc = 'title_ASC',
+  TitleDesc = 'title_DESC',
+  DescriptionAsc = 'description_ASC',
+  DescriptionDesc = 'description_DESC',
+  DurationAsc = 'duration_ASC',
+  DurationDesc = 'duration_DESC',
+  RestAsc = 'rest_ASC',
+  RestDesc = 'rest_DESC'
+}
+
+export type BlockUpdateOneRequiredWithoutParentBlockInstancesInput = {
+  create?: Maybe<BlockCreateWithoutParentBlockInstancesInput>,
+  connect?: Maybe<BlockWhereUniqueInput>,
+  update?: Maybe<BlockUpdateWithoutParentBlockInstancesDataInput>,
+  upsert?: Maybe<BlockUpsertWithoutParentBlockInstancesInput>,
+};
+
+export type BlockUpdateOneWithoutBlocksInput = {
+  create?: Maybe<BlockCreateWithoutBlocksInput>,
+  connect?: Maybe<BlockWhereUniqueInput>,
+  disconnect?: Maybe<Scalars['Boolean']>,
+  delete?: Maybe<Scalars['Boolean']>,
+  update?: Maybe<BlockUpdateWithoutBlocksDataInput>,
+  upsert?: Maybe<BlockUpsertWithoutBlocksInput>,
+};
+
+export type BlockUpdatepicturesInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type BlockUpdatevideosInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type BlockUpdateWithoutBlocksDataInput = {
+  title?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  rest?: Maybe<Scalars['Int']>,
+  videos?: Maybe<BlockUpdatevideosInput>,
+  pictures?: Maybe<BlockUpdatepicturesInput>,
+  format?: Maybe<FormatUpdateOneRequiredInput>,
+  tracks?: Maybe<TrackUpdateManyInput>,
+  parentBlockInstances?: Maybe<BlockInstanceUpdateManyWithoutBlockInput>,
+  exercises?: Maybe<ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput>,
+};
+
+export type BlockUpdateWithoutParentBlockInstancesDataInput = {
+  title?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  rest?: Maybe<Scalars['Int']>,
+  videos?: Maybe<BlockUpdatevideosInput>,
+  pictures?: Maybe<BlockUpdatepicturesInput>,
+  format?: Maybe<FormatUpdateOneRequiredInput>,
+  tracks?: Maybe<TrackUpdateManyInput>,
+  blocks?: Maybe<BlockInstanceUpdateManyWithoutParentBlockInput>,
+  exercises?: Maybe<ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput>,
+};
+
+export type BlockUpsertWithoutBlocksInput = {
+  update: BlockUpdateWithoutBlocksDataInput,
+  create: BlockCreateWithoutBlocksInput,
+};
+
+export type BlockUpsertWithoutParentBlockInstancesInput = {
+  update: BlockUpdateWithoutParentBlockInstancesDataInput,
+  create: BlockCreateWithoutParentBlockInstancesInput,
+};
+
+export type BlockWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<BlockWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<BlockWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<BlockWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  title?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  title_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  title_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  title_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  title_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  title_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  title_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  title_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  title_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  title_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  title_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  title_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  title_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  title_not_ends_with?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  description_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  description_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  description_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  description_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  description_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  description_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  description_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  description_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  description_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  description_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  description_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  description_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  description_not_ends_with?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  duration_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  duration_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  duration_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  duration_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  duration_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  duration_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  duration_gte?: Maybe<Scalars['Int']>,
+  rest?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  rest_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  rest_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  rest_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  rest_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  rest_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  rest_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  rest_gte?: Maybe<Scalars['Int']>,
+  format?: Maybe<FormatWhereInput>,
+  tracks_every?: Maybe<TrackWhereInput>,
+  tracks_some?: Maybe<TrackWhereInput>,
+  tracks_none?: Maybe<TrackWhereInput>,
+  blocks_every?: Maybe<BlockInstanceWhereInput>,
+  blocks_some?: Maybe<BlockInstanceWhereInput>,
+  blocks_none?: Maybe<BlockInstanceWhereInput>,
+  parentBlockInstances_every?: Maybe<BlockInstanceWhereInput>,
+  parentBlockInstances_some?: Maybe<BlockInstanceWhereInput>,
+  parentBlockInstances_none?: Maybe<BlockInstanceWhereInput>,
+  exercises_every?: Maybe<ExerciseInstanceWhereInput>,
+  exercises_some?: Maybe<ExerciseInstanceWhereInput>,
+  exercises_none?: Maybe<ExerciseInstanceWhereInput>,
+};
+
+export type BlockWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+export type Comment = Node & {
+   __typename?: 'Comment',
+  id: Scalars['ID'],
+  text: Scalars['String'],
+  author: User,
+  createdAt: Scalars['DateTime'],
+};
+
+export type CommentCreateManyWithoutAuthorInput = {
+  create?: Maybe<Array<CommentCreateWithoutAuthorInput>>,
+  connect?: Maybe<Array<CommentWhereUniqueInput>>,
+};
+
+export type CommentCreateWithoutAuthorInput = {
+  id?: Maybe<Scalars['ID']>,
+  text: Scalars['String'],
+};
+
+export enum CommentOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  TextAsc = 'text_ASC',
+  TextDesc = 'text_DESC',
+  CreatedAtAsc = 'createdAt_ASC',
+  CreatedAtDesc = 'createdAt_DESC'
+}
+
+export type CommentScalarWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<CommentScalarWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<CommentScalarWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<CommentScalarWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  text?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  text_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  text_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  text_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  text_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  text_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  text_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  text_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  text_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  text_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  text_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  text_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  text_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  text_not_ends_with?: Maybe<Scalars['String']>,
+  createdAt?: Maybe<Scalars['DateTime']>,
+  /** All values that are not equal to given value. */
+  createdAt_not?: Maybe<Scalars['DateTime']>,
+  /** All values that are contained in given list. */
+  createdAt_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values that are not contained in given list. */
+  createdAt_not_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values less than the given value. */
+  createdAt_lt?: Maybe<Scalars['DateTime']>,
+  /** All values less than or equal the given value. */
+  createdAt_lte?: Maybe<Scalars['DateTime']>,
+  /** All values greater than the given value. */
+  createdAt_gt?: Maybe<Scalars['DateTime']>,
+  /** All values greater than or equal the given value. */
+  createdAt_gte?: Maybe<Scalars['DateTime']>,
+};
+
+export type CommentUpdateManyDataInput = {
+  text?: Maybe<Scalars['String']>,
+};
+
+export type CommentUpdateManyWithoutAuthorInput = {
+  create?: Maybe<Array<CommentCreateWithoutAuthorInput>>,
+  connect?: Maybe<Array<CommentWhereUniqueInput>>,
+  set?: Maybe<Array<CommentWhereUniqueInput>>,
+  disconnect?: Maybe<Array<CommentWhereUniqueInput>>,
+  delete?: Maybe<Array<CommentWhereUniqueInput>>,
+  update?: Maybe<Array<CommentUpdateWithWhereUniqueWithoutAuthorInput>>,
+  updateMany?: Maybe<Array<CommentUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<CommentScalarWhereInput>>,
+  upsert?: Maybe<Array<CommentUpsertWithWhereUniqueWithoutAuthorInput>>,
+};
+
+export type CommentUpdateManyWithWhereNestedInput = {
+  where: CommentScalarWhereInput,
+  data: CommentUpdateManyDataInput,
+};
+
+export type CommentUpdateWithoutAuthorDataInput = {
+  text?: Maybe<Scalars['String']>,
+};
+
+export type CommentUpdateWithWhereUniqueWithoutAuthorInput = {
+  where: CommentWhereUniqueInput,
+  data: CommentUpdateWithoutAuthorDataInput,
+};
+
+export type CommentUpsertWithWhereUniqueWithoutAuthorInput = {
+  where: CommentWhereUniqueInput,
+  update: CommentUpdateWithoutAuthorDataInput,
+  create: CommentCreateWithoutAuthorInput,
+};
+
+export type CommentWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<CommentWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<CommentWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<CommentWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  text?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  text_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  text_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  text_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  text_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  text_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  text_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  text_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  text_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  text_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  text_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  text_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  text_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  text_not_ends_with?: Maybe<Scalars['String']>,
+  createdAt?: Maybe<Scalars['DateTime']>,
+  /** All values that are not equal to given value. */
+  createdAt_not?: Maybe<Scalars['DateTime']>,
+  /** All values that are contained in given list. */
+  createdAt_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values that are not contained in given list. */
+  createdAt_not_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values less than the given value. */
+  createdAt_lt?: Maybe<Scalars['DateTime']>,
+  /** All values less than or equal the given value. */
+  createdAt_lte?: Maybe<Scalars['DateTime']>,
+  /** All values greater than the given value. */
+  createdAt_gt?: Maybe<Scalars['DateTime']>,
+  /** All values greater than or equal the given value. */
+  createdAt_gte?: Maybe<Scalars['DateTime']>,
+  author?: Maybe<UserWhereInput>,
+};
+
+export type CommentWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+
+export type Exercise = Node & {
+   __typename?: 'Exercise',
+  id: Scalars['ID'],
+  name: Scalars['String'],
+  description?: Maybe<Scalars['String']>,
+  videos: Array<Scalars['String']>,
+  pictures: Array<Scalars['String']>,
+  targets: Array<Scalars['String']>,
+  baseExercise: Array<Scalars['String']>,
+  parentExerciseInstances?: Maybe<Array<ExerciseInstance>>,
+};
+
+
+export type ExerciseParentExerciseInstancesArgs = {
+  where?: Maybe<ExerciseInstanceWhereInput>,
+  orderBy?: Maybe<ExerciseInstanceOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+export type ExerciseCreatebaseExerciseInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type ExerciseCreateOneWithoutParentExerciseInstancesInput = {
+  create?: Maybe<ExerciseCreateWithoutParentExerciseInstancesInput>,
+  connect?: Maybe<ExerciseWhereUniqueInput>,
+};
+
+export type ExerciseCreatepicturesInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type ExerciseCreatetargetsInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type ExerciseCreatevideosInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type ExerciseCreateWithoutParentExerciseInstancesInput = {
+  id?: Maybe<Scalars['ID']>,
+  name: Scalars['String'],
+  description?: Maybe<Scalars['String']>,
+  videos?: Maybe<ExerciseCreatevideosInput>,
+  pictures?: Maybe<ExerciseCreatepicturesInput>,
+  targets?: Maybe<ExerciseCreatetargetsInput>,
+  baseExercise?: Maybe<ExerciseCreatebaseExerciseInput>,
+};
+
+export type ExerciseInstance = Node & {
+   __typename?: 'ExerciseInstance',
+  id: Scalars['ID'],
+  exercise: Exercise,
+  order: Scalars['Int'],
+  repetitions?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  parentBlockInstances: Block,
+};
+
+export type ExerciseInstanceCreateManyWithoutParentBlockInstancesInput = {
+  create?: Maybe<Array<ExerciseInstanceCreateWithoutParentBlockInstancesInput>>,
+  connect?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
+};
+
+export type ExerciseInstanceCreateWithoutParentBlockInstancesInput = {
+  id?: Maybe<Scalars['ID']>,
+  order: Scalars['Int'],
+  repetitions?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  exercise: ExerciseCreateOneWithoutParentExerciseInstancesInput,
+};
+
+export enum ExerciseInstanceOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  OrderAsc = 'order_ASC',
+  OrderDesc = 'order_DESC',
+  RepetitionsAsc = 'repetitions_ASC',
+  RepetitionsDesc = 'repetitions_DESC',
+  VariationAsc = 'variation_ASC',
+  VariationDesc = 'variation_DESC'
+}
+
+export type ExerciseInstanceScalarWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<ExerciseInstanceScalarWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<ExerciseInstanceScalarWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<ExerciseInstanceScalarWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  order?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  order_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  order_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  order_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  order_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  order_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  order_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  order_gte?: Maybe<Scalars['Int']>,
+  repetitions?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  repetitions_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  repetitions_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  repetitions_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  repetitions_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  repetitions_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  repetitions_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  repetitions_gte?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  variation_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  variation_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  variation_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  variation_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  variation_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  variation_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  variation_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  variation_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  variation_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  variation_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  variation_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  variation_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  variation_not_ends_with?: Maybe<Scalars['String']>,
+};
+
+export type ExerciseInstanceUpdateManyDataInput = {
+  order?: Maybe<Scalars['Int']>,
+  repetitions?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+};
+
+export type ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput = {
+  create?: Maybe<Array<ExerciseInstanceCreateWithoutParentBlockInstancesInput>>,
+  connect?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
+  set?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
+  disconnect?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
+  delete?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
+  update?: Maybe<Array<ExerciseInstanceUpdateWithWhereUniqueWithoutParentBlockInstancesInput>>,
+  updateMany?: Maybe<Array<ExerciseInstanceUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<ExerciseInstanceScalarWhereInput>>,
+  upsert?: Maybe<Array<ExerciseInstanceUpsertWithWhereUniqueWithoutParentBlockInstancesInput>>,
+};
+
+export type ExerciseInstanceUpdateManyWithWhereNestedInput = {
+  where: ExerciseInstanceScalarWhereInput,
+  data: ExerciseInstanceUpdateManyDataInput,
+};
+
+export type ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput = {
+  order?: Maybe<Scalars['Int']>,
+  repetitions?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  exercise?: Maybe<ExerciseUpdateOneRequiredWithoutParentExerciseInstancesInput>,
+};
+
+export type ExerciseInstanceUpdateWithWhereUniqueWithoutParentBlockInstancesInput = {
+  where: ExerciseInstanceWhereUniqueInput,
+  data: ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput,
+};
+
+export type ExerciseInstanceUpsertWithWhereUniqueWithoutParentBlockInstancesInput = {
+  where: ExerciseInstanceWhereUniqueInput,
+  update: ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput,
+  create: ExerciseInstanceCreateWithoutParentBlockInstancesInput,
+};
+
+export type ExerciseInstanceWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<ExerciseInstanceWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<ExerciseInstanceWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<ExerciseInstanceWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  order?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  order_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  order_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  order_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  order_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  order_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  order_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  order_gte?: Maybe<Scalars['Int']>,
+  repetitions?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  repetitions_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  repetitions_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  repetitions_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  repetitions_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  repetitions_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  repetitions_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  repetitions_gte?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  variation_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  variation_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  variation_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  variation_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  variation_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  variation_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  variation_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  variation_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  variation_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  variation_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  variation_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  variation_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  variation_not_ends_with?: Maybe<Scalars['String']>,
+  exercise?: Maybe<ExerciseWhereInput>,
+  parentBlockInstances?: Maybe<BlockWhereInput>,
+};
+
+export type ExerciseInstanceWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+export enum ExerciseOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  NameAsc = 'name_ASC',
+  NameDesc = 'name_DESC',
+  DescriptionAsc = 'description_ASC',
+  DescriptionDesc = 'description_DESC'
+}
+
+export type ExerciseUpdatebaseExerciseInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type ExerciseUpdateOneRequiredWithoutParentExerciseInstancesInput = {
+  create?: Maybe<ExerciseCreateWithoutParentExerciseInstancesInput>,
+  connect?: Maybe<ExerciseWhereUniqueInput>,
+  update?: Maybe<ExerciseUpdateWithoutParentExerciseInstancesDataInput>,
+  upsert?: Maybe<ExerciseUpsertWithoutParentExerciseInstancesInput>,
+};
+
+export type ExerciseUpdatepicturesInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type ExerciseUpdatetargetsInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type ExerciseUpdatevideosInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type ExerciseUpdateWithoutParentExerciseInstancesDataInput = {
+  name?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+  videos?: Maybe<ExerciseUpdatevideosInput>,
+  pictures?: Maybe<ExerciseUpdatepicturesInput>,
+  targets?: Maybe<ExerciseUpdatetargetsInput>,
+  baseExercise?: Maybe<ExerciseUpdatebaseExerciseInput>,
+};
+
+export type ExerciseUpsertWithoutParentExerciseInstancesInput = {
+  update: ExerciseUpdateWithoutParentExerciseInstancesDataInput,
+  create: ExerciseCreateWithoutParentExerciseInstancesInput,
+};
+
+export type ExerciseWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<ExerciseWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<ExerciseWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<ExerciseWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  name?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  name_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  name_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  name_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  name_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  name_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  name_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  name_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  name_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  name_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  name_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  name_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  name_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  name_not_ends_with?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  description_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  description_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  description_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  description_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  description_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  description_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  description_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  description_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  description_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  description_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  description_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  description_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  description_not_ends_with?: Maybe<Scalars['String']>,
+  parentExerciseInstances_every?: Maybe<ExerciseInstanceWhereInput>,
+  parentExerciseInstances_some?: Maybe<ExerciseInstanceWhereInput>,
+  parentExerciseInstances_none?: Maybe<ExerciseInstanceWhereInput>,
+};
+
+export type ExerciseWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+export type File = Node & {
+   __typename?: 'File',
+  id: Scalars['ID'],
+  createdAt: Scalars['DateTime'],
+  updatedAt: Scalars['DateTime'],
+  path: Scalars['String'],
+  mimetype: Scalars['String'],
+  user: User,
+  thumbnail?: Maybe<Scalars['String']>,
+  filename: Scalars['String'],
+  encoding: Scalars['String'],
+  size: Scalars['Int'],
+  comment?: Maybe<Scalars['String']>,
+};
+
+export type Format = Node & {
+   __typename?: 'Format',
+  id: Scalars['ID'],
+  name: Scalars['String'],
+  description: Scalars['String'],
+};
+
+export type FormatCreateInput = {
+  id?: Maybe<Scalars['ID']>,
+  name: Scalars['String'],
+  description: Scalars['String'],
+};
+
+export type FormatCreateOneInput = {
+  create?: Maybe<FormatCreateInput>,
+  connect?: Maybe<FormatWhereUniqueInput>,
+};
+
+export enum FormatOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  NameAsc = 'name_ASC',
+  NameDesc = 'name_DESC',
+  DescriptionAsc = 'description_ASC',
+  DescriptionDesc = 'description_DESC'
+}
+
+export type FormatUpdateDataInput = {
+  name?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+};
+
+export type FormatUpdateOneRequiredInput = {
+  create?: Maybe<FormatCreateInput>,
+  connect?: Maybe<FormatWhereUniqueInput>,
+  update?: Maybe<FormatUpdateDataInput>,
+  upsert?: Maybe<FormatUpsertNestedInput>,
+};
+
+export type FormatUpsertNestedInput = {
+  update: FormatUpdateDataInput,
+  create: FormatCreateInput,
+};
+
+export type FormatWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<FormatWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<FormatWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<FormatWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  name?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  name_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  name_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  name_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  name_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  name_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  name_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  name_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  name_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  name_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  name_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  name_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  name_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  name_not_ends_with?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  description_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  description_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  description_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  description_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  description_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  description_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  description_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  description_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  description_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  description_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  description_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  description_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  description_not_ends_with?: Maybe<Scalars['String']>,
+};
+
+export type FormatWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+export type FsFile = {
+   __typename?: 'FsFile',
+  filename: Scalars['String'],
+  path: Scalars['String'],
+  size: Scalars['Int'],
+  ctime: Scalars['DateTime'],
+  mtime: Scalars['DateTime'],
+};
+
+export type Mutation = {
+   __typename?: 'Mutation',
+  uploadFile: File,
+  createUser: User,
+  updateUser?: Maybe<User>,
+  deleteUser?: Maybe<User>,
+  createTraining: Training,
+  deleteTraining: Training,
+  updateTraining: Training,
+  createTrainingType: TrainingType,
+  createFormat: Format,
+  userLogin: User,
+  userLogout: Scalars['String'],
+  userSignup: User,
+  requestReset: Scalars['String'],
+  resetPassword: User,
+  register: Training,
+  deregister: Training,
+  publish: Training,
+};
+
+
+export type MutationUploadFileArgs = {
+  file: Scalars['Upload'],
+  comment?: Maybe<Scalars['String']>
+};
+
+
+export type MutationCreateUserArgs = {
+  data: UserCreateInput
+};
+
+
+export type MutationUpdateUserArgs = {
+  email: Scalars['String'],
+  data: UserUpdateInput
+};
+
+
+export type MutationDeleteUserArgs = {
+  email: Scalars['String']
+};
+
+
+export type MutationCreateTrainingArgs = {
+  title: Scalars['String'],
+  type: TrainingTypeCreateOneInput,
+  trainingDate: Scalars['DateTime'],
+  location: Scalars['String'],
+  attendance?: Maybe<Scalars['Int']>,
+  published: Scalars['Boolean'],
+  blocks?: Maybe<BlockInstanceCreateManyWithoutParentTrainingInput>
+};
+
+
+export type MutationDeleteTrainingArgs = {
+  id: Scalars['ID']
+};
+
+
+export type MutationUpdateTrainingArgs = {
+  where: TrainingWhereUniqueInput,
+  data: TrainingUpdateInput
+};
+
+
+export type MutationCreateTrainingTypeArgs = {
+  name: Scalars['String'],
+  description: Scalars['String']
+};
+
+
+export type MutationCreateFormatArgs = {
+  name: Scalars['String'],
+  description: Scalars['String']
+};
+
+
+export type MutationUserLoginArgs = {
+  email: Scalars['String'],
+  password: Scalars['String']
+};
+
+
+export type MutationUserSignupArgs = {
+  name: Scalars['String'],
+  email: Scalars['String'],
+  password: Scalars['String']
+};
+
+
+export type MutationRequestResetArgs = {
+  email: Scalars['String']
+};
+
+
+export type MutationResetPasswordArgs = {
+  token: Scalars['String'],
+  password: Scalars['String']
+};
+
+
+export type MutationRegisterArgs = {
+  training: Scalars['ID']
+};
+
+
+export type MutationDeregisterArgs = {
+  training: Scalars['ID']
+};
+
+
+export type MutationPublishArgs = {
+  training: Scalars['ID'],
+  status?: Maybe<Scalars['Boolean']>
+};
+
+/** An object with an ID */
+export type Node = {
+  /** The id of the object. */
+  id: Scalars['ID'],
+};
+
+/** Information about pagination in a connection. */
+export type PageInfo = {
+   __typename?: 'PageInfo',
+  /** When paginating forwards, are there more items? */
+  hasNextPage: Scalars['Boolean'],
+  /** When paginating backwards, are there more items? */
+  hasPreviousPage: Scalars['Boolean'],
+  /** When paginating backwards, the cursor to continue. */
+  startCursor?: Maybe<Scalars['String']>,
+  /** When paginating forwards, the cursor to continue. */
+  endCursor?: Maybe<Scalars['String']>,
+};
+
+export enum Permission {
+  Admin = 'ADMIN',
+  Instructor = 'INSTRUCTOR'
+}
+
+export type Query = {
+   __typename?: 'Query',
+  trainingArchive: TrainingArchive,
+  publishedTrainings: Array<Training>,
+  training: Training,
+  trainings: Array<Training>,
+  trainingsCount: TrainingConnection,
+  fsFiles: Array<FsFile>,
+  files: Array<File>,
+  currentUser: User,
+  user?: Maybe<User>,
+  users: Array<User>,
+  trainingType?: Maybe<TrainingType>,
+  trainingTypes: Array<TrainingType>,
+  block?: Maybe<Block>,
+  blocks: Array<Block>,
+  format?: Maybe<Format>,
+  formats: Array<Format>,
+  exercise?: Maybe<Exercise>,
+  exercises: Array<Exercise>,
+};
+
+
+export type QueryTrainingArchiveArgs = {
+  skip?: Maybe<Scalars['Int']>,
+  first?: Maybe<Scalars['Int']>
+};
+
+
+export type QueryPublishedTrainingsArgs = {
+  where?: Maybe<TrainingWhereInput>,
+  orderBy?: Maybe<TrainingOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  first?: Maybe<Scalars['Int']>
+};
+
+
+export type QueryTrainingArgs = {
+  id?: Maybe<Scalars['ID']>
+};
+
+
+export type QueryTrainingsArgs = {
+  where?: Maybe<TrainingWhereInput>,
+  orderBy?: Maybe<TrainingOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type QueryTrainingsCountArgs = {
+  where?: Maybe<TrainingWhereInput>
+};
+
+
+export type QueryFsFilesArgs = {
+  directory: Scalars['String']
+};
+
+
+export type QueryUserArgs = {
+  where: UserWhereUniqueInput
+};
+
+
+export type QueryUsersArgs = {
+  where?: Maybe<UserWhereInput>,
+  orderBy?: Maybe<UserOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type QueryTrainingTypeArgs = {
+  where: TrainingTypeWhereUniqueInput
+};
+
+
+export type QueryTrainingTypesArgs = {
+  where?: Maybe<TrainingTypeWhereInput>,
+  orderBy?: Maybe<TrainingTypeOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type QueryBlockArgs = {
+  where: BlockWhereUniqueInput
+};
+
+
+export type QueryBlocksArgs = {
+  where?: Maybe<BlockWhereInput>,
+  orderBy?: Maybe<BlockOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type QueryFormatArgs = {
+  where: FormatWhereUniqueInput
+};
+
+
+export type QueryFormatsArgs = {
+  where?: Maybe<FormatWhereInput>,
+  orderBy?: Maybe<FormatOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type QueryExerciseArgs = {
+  where: ExerciseWhereUniqueInput
+};
+
+
+export type QueryExercisesArgs = {
+  where?: Maybe<ExerciseWhereInput>,
+  orderBy?: Maybe<ExerciseOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+export type Rating = Node & {
+   __typename?: 'Rating',
+  id: Scalars['ID'],
+  user: User,
+  value: Scalars['Int'],
+  comment: Scalars['String'],
+  createdAt: Scalars['DateTime'],
+};
+
+export type RatingCreateInput = {
+  id?: Maybe<Scalars['ID']>,
+  value: Scalars['Int'],
+  comment: Scalars['String'],
+  user: UserCreateOneWithoutRatingsInput,
+};
+
+export type RatingCreateManyInput = {
+  create?: Maybe<Array<RatingCreateInput>>,
+  connect?: Maybe<Array<RatingWhereUniqueInput>>,
+};
+
+export type RatingCreateManyWithoutUserInput = {
+  create?: Maybe<Array<RatingCreateWithoutUserInput>>,
+  connect?: Maybe<Array<RatingWhereUniqueInput>>,
+};
+
+export type RatingCreateWithoutUserInput = {
+  id?: Maybe<Scalars['ID']>,
+  value: Scalars['Int'],
+  comment: Scalars['String'],
+};
+
+export enum RatingOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  ValueAsc = 'value_ASC',
+  ValueDesc = 'value_DESC',
+  CommentAsc = 'comment_ASC',
+  CommentDesc = 'comment_DESC',
+  CreatedAtAsc = 'createdAt_ASC',
+  CreatedAtDesc = 'createdAt_DESC'
+}
+
+export type RatingScalarWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<RatingScalarWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<RatingScalarWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<RatingScalarWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  value?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  value_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  value_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  value_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  value_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  value_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  value_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  value_gte?: Maybe<Scalars['Int']>,
+  comment?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  comment_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  comment_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  comment_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  comment_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  comment_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  comment_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  comment_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  comment_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  comment_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  comment_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  comment_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  comment_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  comment_not_ends_with?: Maybe<Scalars['String']>,
+  createdAt?: Maybe<Scalars['DateTime']>,
+  /** All values that are not equal to given value. */
+  createdAt_not?: Maybe<Scalars['DateTime']>,
+  /** All values that are contained in given list. */
+  createdAt_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values that are not contained in given list. */
+  createdAt_not_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values less than the given value. */
+  createdAt_lt?: Maybe<Scalars['DateTime']>,
+  /** All values less than or equal the given value. */
+  createdAt_lte?: Maybe<Scalars['DateTime']>,
+  /** All values greater than the given value. */
+  createdAt_gt?: Maybe<Scalars['DateTime']>,
+  /** All values greater than or equal the given value. */
+  createdAt_gte?: Maybe<Scalars['DateTime']>,
+};
+
+export type RatingUpdateDataInput = {
+  value?: Maybe<Scalars['Int']>,
+  comment?: Maybe<Scalars['String']>,
+  user?: Maybe<UserUpdateOneRequiredWithoutRatingsInput>,
+};
+
+export type RatingUpdateManyDataInput = {
+  value?: Maybe<Scalars['Int']>,
+  comment?: Maybe<Scalars['String']>,
+};
+
+export type RatingUpdateManyInput = {
+  create?: Maybe<Array<RatingCreateInput>>,
+  connect?: Maybe<Array<RatingWhereUniqueInput>>,
+  set?: Maybe<Array<RatingWhereUniqueInput>>,
+  disconnect?: Maybe<Array<RatingWhereUniqueInput>>,
+  delete?: Maybe<Array<RatingWhereUniqueInput>>,
+  update?: Maybe<Array<RatingUpdateWithWhereUniqueNestedInput>>,
+  updateMany?: Maybe<Array<RatingUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<RatingScalarWhereInput>>,
+  upsert?: Maybe<Array<RatingUpsertWithWhereUniqueNestedInput>>,
+};
+
+export type RatingUpdateManyWithoutUserInput = {
+  create?: Maybe<Array<RatingCreateWithoutUserInput>>,
+  connect?: Maybe<Array<RatingWhereUniqueInput>>,
+  set?: Maybe<Array<RatingWhereUniqueInput>>,
+  disconnect?: Maybe<Array<RatingWhereUniqueInput>>,
+  delete?: Maybe<Array<RatingWhereUniqueInput>>,
+  update?: Maybe<Array<RatingUpdateWithWhereUniqueWithoutUserInput>>,
+  updateMany?: Maybe<Array<RatingUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<RatingScalarWhereInput>>,
+  upsert?: Maybe<Array<RatingUpsertWithWhereUniqueWithoutUserInput>>,
+};
+
+export type RatingUpdateManyWithWhereNestedInput = {
+  where: RatingScalarWhereInput,
+  data: RatingUpdateManyDataInput,
+};
+
+export type RatingUpdateWithoutUserDataInput = {
+  value?: Maybe<Scalars['Int']>,
+  comment?: Maybe<Scalars['String']>,
+};
+
+export type RatingUpdateWithWhereUniqueNestedInput = {
+  where: RatingWhereUniqueInput,
+  data: RatingUpdateDataInput,
+};
+
+export type RatingUpdateWithWhereUniqueWithoutUserInput = {
+  where: RatingWhereUniqueInput,
+  data: RatingUpdateWithoutUserDataInput,
+};
+
+export type RatingUpsertWithWhereUniqueNestedInput = {
+  where: RatingWhereUniqueInput,
+  update: RatingUpdateDataInput,
+  create: RatingCreateInput,
+};
+
+export type RatingUpsertWithWhereUniqueWithoutUserInput = {
+  where: RatingWhereUniqueInput,
+  update: RatingUpdateWithoutUserDataInput,
+  create: RatingCreateWithoutUserInput,
+};
+
+export type RatingWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<RatingWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<RatingWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<RatingWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  value?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  value_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  value_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  value_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  value_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  value_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  value_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  value_gte?: Maybe<Scalars['Int']>,
+  comment?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  comment_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  comment_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  comment_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  comment_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  comment_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  comment_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  comment_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  comment_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  comment_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  comment_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  comment_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  comment_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  comment_not_ends_with?: Maybe<Scalars['String']>,
+  createdAt?: Maybe<Scalars['DateTime']>,
+  /** All values that are not equal to given value. */
+  createdAt_not?: Maybe<Scalars['DateTime']>,
+  /** All values that are contained in given list. */
+  createdAt_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values that are not contained in given list. */
+  createdAt_not_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values less than the given value. */
+  createdAt_lt?: Maybe<Scalars['DateTime']>,
+  /** All values less than or equal the given value. */
+  createdAt_lte?: Maybe<Scalars['DateTime']>,
+  /** All values greater than the given value. */
+  createdAt_gt?: Maybe<Scalars['DateTime']>,
+  /** All values greater than or equal the given value. */
+  createdAt_gte?: Maybe<Scalars['DateTime']>,
+  user?: Maybe<UserWhereInput>,
+};
+
+export type RatingWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+export type Track = Node & {
+   __typename?: 'Track',
+  id: Scalars['ID'],
+  title: Scalars['String'],
+  artist: Scalars['String'],
+  duration: Scalars['Int'],
+  link: Scalars['String'],
+};
+
+export type TrackCreateInput = {
+  id?: Maybe<Scalars['ID']>,
+  title: Scalars['String'],
+  artist: Scalars['String'],
+  duration: Scalars['Int'],
+  link: Scalars['String'],
+};
+
+export type TrackCreateManyInput = {
+  create?: Maybe<Array<TrackCreateInput>>,
+  connect?: Maybe<Array<TrackWhereUniqueInput>>,
+};
+
+export enum TrackOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  TitleAsc = 'title_ASC',
+  TitleDesc = 'title_DESC',
+  ArtistAsc = 'artist_ASC',
+  ArtistDesc = 'artist_DESC',
+  DurationAsc = 'duration_ASC',
+  DurationDesc = 'duration_DESC',
+  LinkAsc = 'link_ASC',
+  LinkDesc = 'link_DESC'
+}
+
+export type TrackScalarWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<TrackScalarWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<TrackScalarWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<TrackScalarWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  title?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  title_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  title_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  title_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  title_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  title_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  title_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  title_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  title_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  title_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  title_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  title_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  title_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  title_not_ends_with?: Maybe<Scalars['String']>,
+  artist?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  artist_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  artist_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  artist_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  artist_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  artist_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  artist_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  artist_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  artist_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  artist_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  artist_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  artist_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  artist_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  artist_not_ends_with?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  duration_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  duration_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  duration_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  duration_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  duration_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  duration_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  duration_gte?: Maybe<Scalars['Int']>,
+  link?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  link_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  link_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  link_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  link_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  link_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  link_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  link_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  link_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  link_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  link_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  link_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  link_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  link_not_ends_with?: Maybe<Scalars['String']>,
+};
+
+export type TrackUpdateDataInput = {
+  title?: Maybe<Scalars['String']>,
+  artist?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  link?: Maybe<Scalars['String']>,
+};
+
+export type TrackUpdateManyDataInput = {
+  title?: Maybe<Scalars['String']>,
+  artist?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  link?: Maybe<Scalars['String']>,
+};
+
+export type TrackUpdateManyInput = {
+  create?: Maybe<Array<TrackCreateInput>>,
+  connect?: Maybe<Array<TrackWhereUniqueInput>>,
+  set?: Maybe<Array<TrackWhereUniqueInput>>,
+  disconnect?: Maybe<Array<TrackWhereUniqueInput>>,
+  delete?: Maybe<Array<TrackWhereUniqueInput>>,
+  update?: Maybe<Array<TrackUpdateWithWhereUniqueNestedInput>>,
+  updateMany?: Maybe<Array<TrackUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<TrackScalarWhereInput>>,
+  upsert?: Maybe<Array<TrackUpsertWithWhereUniqueNestedInput>>,
+};
+
+export type TrackUpdateManyWithWhereNestedInput = {
+  where: TrackScalarWhereInput,
+  data: TrackUpdateManyDataInput,
+};
+
+export type TrackUpdateWithWhereUniqueNestedInput = {
+  where: TrackWhereUniqueInput,
+  data: TrackUpdateDataInput,
+};
+
+export type TrackUpsertWithWhereUniqueNestedInput = {
+  where: TrackWhereUniqueInput,
+  update: TrackUpdateDataInput,
+  create: TrackCreateInput,
+};
+
+export type TrackWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<TrackWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<TrackWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<TrackWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  title?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  title_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  title_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  title_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  title_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  title_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  title_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  title_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  title_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  title_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  title_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  title_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  title_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  title_not_ends_with?: Maybe<Scalars['String']>,
+  artist?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  artist_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  artist_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  artist_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  artist_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  artist_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  artist_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  artist_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  artist_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  artist_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  artist_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  artist_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  artist_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  artist_not_ends_with?: Maybe<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  duration_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  duration_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  duration_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  duration_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  duration_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  duration_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  duration_gte?: Maybe<Scalars['Int']>,
+  link?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  link_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  link_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  link_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  link_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  link_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  link_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  link_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  link_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  link_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  link_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  link_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  link_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  link_not_ends_with?: Maybe<Scalars['String']>,
+};
+
+export type TrackWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+export type Training = Node & {
+   __typename?: 'Training',
+  id: Scalars['ID'],
+  title: Scalars['String'],
+  type: TrainingType,
+  createdAt: Scalars['DateTime'],
+  trainingDate: Scalars['DateTime'],
+  location: Scalars['String'],
+  registrations?: Maybe<Array<User>>,
+  attendance?: Maybe<Scalars['Int']>,
+  ratings?: Maybe<Array<Rating>>,
+  published: Scalars['Boolean'],
+  blocks?: Maybe<Array<BlockInstance>>,
+};
+
+
+export type TrainingRegistrationsArgs = {
+  where?: Maybe<UserWhereInput>,
+  orderBy?: Maybe<UserOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type TrainingRatingsArgs = {
+  where?: Maybe<RatingWhereInput>,
+  orderBy?: Maybe<RatingOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type TrainingBlocksArgs = {
+  where?: Maybe<BlockInstanceWhereInput>,
+  orderBy?: Maybe<BlockInstanceOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+export type TrainingArchive = {
+   __typename?: 'TrainingArchive',
+  trainings: Array<TrainingArchiveItem>,
+  totalCount: Scalars['Int'],
+};
+
+export type TrainingArchiveItem = {
+   __typename?: 'TrainingArchiveItem',
+  id: Scalars['ID'],
+  title: Scalars['String'],
+  type: TrainingType,
+  trainingDate: Scalars['DateTime'],
+  location: Scalars['String'],
+  attendance?: Maybe<Scalars['Int']>,
+  ratings?: Maybe<Scalars['Float']>,
+  blocks: Array<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+};
+
+/** A connection to a list of items. */
+export type TrainingConnection = {
+   __typename?: 'TrainingConnection',
+  /** Information to aid in pagination. */
+  pageInfo: PageInfo,
+  /** A list of edges. */
+  edges: Array<Maybe<TrainingEdge>>,
+  aggregate: AggregateTraining,
+};
+
+export type TrainingCreateOneWithoutBlocksInput = {
+  create?: Maybe<TrainingCreateWithoutBlocksInput>,
+  connect?: Maybe<TrainingWhereUniqueInput>,
+};
+
+export type TrainingCreateWithoutBlocksInput = {
+  id?: Maybe<Scalars['ID']>,
+  title: Scalars['String'],
+  trainingDate: Scalars['DateTime'],
+  location: Scalars['String'],
+  attendance?: Maybe<Scalars['Int']>,
+  published: Scalars['Boolean'],
+  type: TrainingTypeCreateOneInput,
+  registrations?: Maybe<UserCreateManyInput>,
+  ratings?: Maybe<RatingCreateManyInput>,
+};
+
+/** An edge in a connection. */
+export type TrainingEdge = {
+   __typename?: 'TrainingEdge',
+  /** The item at the end of the edge. */
+  node: Training,
+  /** A cursor for use in pagination. */
+  cursor: Scalars['String'],
+};
+
+export enum TrainingOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  TitleAsc = 'title_ASC',
+  TitleDesc = 'title_DESC',
+  CreatedAtAsc = 'createdAt_ASC',
+  CreatedAtDesc = 'createdAt_DESC',
+  TrainingDateAsc = 'trainingDate_ASC',
+  TrainingDateDesc = 'trainingDate_DESC',
+  LocationAsc = 'location_ASC',
+  LocationDesc = 'location_DESC',
+  AttendanceAsc = 'attendance_ASC',
+  AttendanceDesc = 'attendance_DESC',
+  PublishedAsc = 'published_ASC',
+  PublishedDesc = 'published_DESC'
+}
+
+export type TrainingType = Node & {
+   __typename?: 'TrainingType',
+  id: Scalars['ID'],
+  name: Scalars['String'],
+  description: Scalars['String'],
+};
+
+export type TrainingTypeCreateInput = {
+  id?: Maybe<Scalars['ID']>,
+  name: Scalars['String'],
+  description: Scalars['String'],
+};
+
+export type TrainingTypeCreateOneInput = {
+  create?: Maybe<TrainingTypeCreateInput>,
+  connect?: Maybe<TrainingTypeWhereUniqueInput>,
+};
+
+export enum TrainingTypeOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  NameAsc = 'name_ASC',
+  NameDesc = 'name_DESC',
+  DescriptionAsc = 'description_ASC',
+  DescriptionDesc = 'description_DESC'
+}
+
+export type TrainingTypeUpdateDataInput = {
+  name?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+};
+
+export type TrainingTypeUpdateOneRequiredInput = {
+  create?: Maybe<TrainingTypeCreateInput>,
+  connect?: Maybe<TrainingTypeWhereUniqueInput>,
+  update?: Maybe<TrainingTypeUpdateDataInput>,
+  upsert?: Maybe<TrainingTypeUpsertNestedInput>,
+};
+
+export type TrainingTypeUpsertNestedInput = {
+  update: TrainingTypeUpdateDataInput,
+  create: TrainingTypeCreateInput,
+};
+
+export type TrainingTypeWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<TrainingTypeWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<TrainingTypeWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<TrainingTypeWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  name?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  name_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  name_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  name_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  name_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  name_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  name_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  name_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  name_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  name_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  name_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  name_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  name_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  name_not_ends_with?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  description_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  description_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  description_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  description_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  description_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  description_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  description_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  description_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  description_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  description_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  description_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  description_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  description_not_ends_with?: Maybe<Scalars['String']>,
+};
+
+export type TrainingTypeWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+  name?: Maybe<Scalars['String']>,
+};
+
+export type TrainingUpdateInput = {
+  title?: Maybe<Scalars['String']>,
+  trainingDate?: Maybe<Scalars['DateTime']>,
+  location?: Maybe<Scalars['String']>,
+  attendance?: Maybe<Scalars['Int']>,
+  published?: Maybe<Scalars['Boolean']>,
+  type?: Maybe<TrainingTypeUpdateOneRequiredInput>,
+  registrations?: Maybe<UserUpdateManyInput>,
+  ratings?: Maybe<RatingUpdateManyInput>,
+  blocks?: Maybe<BlockInstanceUpdateManyWithoutParentTrainingInput>,
+};
+
+export type TrainingUpdateOneWithoutBlocksInput = {
+  create?: Maybe<TrainingCreateWithoutBlocksInput>,
+  connect?: Maybe<TrainingWhereUniqueInput>,
+  disconnect?: Maybe<Scalars['Boolean']>,
+  delete?: Maybe<Scalars['Boolean']>,
+  update?: Maybe<TrainingUpdateWithoutBlocksDataInput>,
+  upsert?: Maybe<TrainingUpsertWithoutBlocksInput>,
+};
+
+export type TrainingUpdateWithoutBlocksDataInput = {
+  title?: Maybe<Scalars['String']>,
+  trainingDate?: Maybe<Scalars['DateTime']>,
+  location?: Maybe<Scalars['String']>,
+  attendance?: Maybe<Scalars['Int']>,
+  published?: Maybe<Scalars['Boolean']>,
+  type?: Maybe<TrainingTypeUpdateOneRequiredInput>,
+  registrations?: Maybe<UserUpdateManyInput>,
+  ratings?: Maybe<RatingUpdateManyInput>,
+};
+
+export type TrainingUpsertWithoutBlocksInput = {
+  update: TrainingUpdateWithoutBlocksDataInput,
+  create: TrainingCreateWithoutBlocksInput,
+};
+
+export type TrainingWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<TrainingWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<TrainingWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<TrainingWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  title?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  title_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  title_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  title_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  title_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  title_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  title_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  title_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  title_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  title_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  title_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  title_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  title_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  title_not_ends_with?: Maybe<Scalars['String']>,
+  createdAt?: Maybe<Scalars['DateTime']>,
+  /** All values that are not equal to given value. */
+  createdAt_not?: Maybe<Scalars['DateTime']>,
+  /** All values that are contained in given list. */
+  createdAt_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values that are not contained in given list. */
+  createdAt_not_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values less than the given value. */
+  createdAt_lt?: Maybe<Scalars['DateTime']>,
+  /** All values less than or equal the given value. */
+  createdAt_lte?: Maybe<Scalars['DateTime']>,
+  /** All values greater than the given value. */
+  createdAt_gt?: Maybe<Scalars['DateTime']>,
+  /** All values greater than or equal the given value. */
+  createdAt_gte?: Maybe<Scalars['DateTime']>,
+  trainingDate?: Maybe<Scalars['DateTime']>,
+  /** All values that are not equal to given value. */
+  trainingDate_not?: Maybe<Scalars['DateTime']>,
+  /** All values that are contained in given list. */
+  trainingDate_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values that are not contained in given list. */
+  trainingDate_not_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values less than the given value. */
+  trainingDate_lt?: Maybe<Scalars['DateTime']>,
+  /** All values less than or equal the given value. */
+  trainingDate_lte?: Maybe<Scalars['DateTime']>,
+  /** All values greater than the given value. */
+  trainingDate_gt?: Maybe<Scalars['DateTime']>,
+  /** All values greater than or equal the given value. */
+  trainingDate_gte?: Maybe<Scalars['DateTime']>,
+  location?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  location_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  location_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  location_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  location_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  location_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  location_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  location_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  location_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  location_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  location_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  location_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  location_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  location_not_ends_with?: Maybe<Scalars['String']>,
+  attendance?: Maybe<Scalars['Int']>,
+  /** All values that are not equal to given value. */
+  attendance_not?: Maybe<Scalars['Int']>,
+  /** All values that are contained in given list. */
+  attendance_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values that are not contained in given list. */
+  attendance_not_in?: Maybe<Array<Scalars['Int']>>,
+  /** All values less than the given value. */
+  attendance_lt?: Maybe<Scalars['Int']>,
+  /** All values less than or equal the given value. */
+  attendance_lte?: Maybe<Scalars['Int']>,
+  /** All values greater than the given value. */
+  attendance_gt?: Maybe<Scalars['Int']>,
+  /** All values greater than or equal the given value. */
+  attendance_gte?: Maybe<Scalars['Int']>,
+  published?: Maybe<Scalars['Boolean']>,
+  /** All values that are not equal to given value. */
+  published_not?: Maybe<Scalars['Boolean']>,
+  type?: Maybe<TrainingTypeWhereInput>,
+  registrations_every?: Maybe<UserWhereInput>,
+  registrations_some?: Maybe<UserWhereInput>,
+  registrations_none?: Maybe<UserWhereInput>,
+  ratings_every?: Maybe<RatingWhereInput>,
+  ratings_some?: Maybe<RatingWhereInput>,
+  ratings_none?: Maybe<RatingWhereInput>,
+  blocks_every?: Maybe<BlockInstanceWhereInput>,
+  blocks_some?: Maybe<BlockInstanceWhereInput>,
+  blocks_none?: Maybe<BlockInstanceWhereInput>,
+};
+
+export type TrainingWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+};
+
+
+export type User = Node & {
+   __typename?: 'User',
+  id: Scalars['ID'],
+  email: Scalars['String'],
+  name: Scalars['String'],
+  password: Scalars['String'],
+  resetToken?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  createdAt: Scalars['DateTime'],
+  comments?: Maybe<Array<Comment>>,
+  ratings?: Maybe<Array<Rating>>,
+  permissions: Array<Permission>,
+  interests: Array<Scalars['String']>,
+};
+
+
+export type UserCommentsArgs = {
+  where?: Maybe<CommentWhereInput>,
+  orderBy?: Maybe<CommentOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+
+export type UserRatingsArgs = {
+  where?: Maybe<RatingWhereInput>,
+  orderBy?: Maybe<RatingOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
+};
+
+export type UserCreateInput = {
+  id?: Maybe<Scalars['ID']>,
+  email: Scalars['String'],
+  name: Scalars['String'],
+  password: Scalars['String'],
+  resetToken?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  permissions?: Maybe<UserCreatepermissionsInput>,
+  interests?: Maybe<UserCreateinterestsInput>,
+  comments?: Maybe<CommentCreateManyWithoutAuthorInput>,
+  ratings?: Maybe<RatingCreateManyWithoutUserInput>,
+};
+
+export type UserCreateinterestsInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type UserCreateManyInput = {
+  create?: Maybe<Array<UserCreateInput>>,
+  connect?: Maybe<Array<UserWhereUniqueInput>>,
+};
+
+export type UserCreateOneWithoutRatingsInput = {
+  create?: Maybe<UserCreateWithoutRatingsInput>,
+  connect?: Maybe<UserWhereUniqueInput>,
+};
+
+export type UserCreatepermissionsInput = {
+  set?: Maybe<Array<Permission>>,
+};
+
+export type UserCreateWithoutRatingsInput = {
+  id?: Maybe<Scalars['ID']>,
+  email: Scalars['String'],
+  name: Scalars['String'],
+  password: Scalars['String'],
+  resetToken?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  permissions?: Maybe<UserCreatepermissionsInput>,
+  interests?: Maybe<UserCreateinterestsInput>,
+  comments?: Maybe<CommentCreateManyWithoutAuthorInput>,
+};
+
+export enum UserOrderByInput {
+  IdAsc = 'id_ASC',
+  IdDesc = 'id_DESC',
+  EmailAsc = 'email_ASC',
+  EmailDesc = 'email_DESC',
+  NameAsc = 'name_ASC',
+  NameDesc = 'name_DESC',
+  PasswordAsc = 'password_ASC',
+  PasswordDesc = 'password_DESC',
+  ResetTokenAsc = 'resetToken_ASC',
+  ResetTokenDesc = 'resetToken_DESC',
+  ResetTokenExpiryAsc = 'resetTokenExpiry_ASC',
+  ResetTokenExpiryDesc = 'resetTokenExpiry_DESC',
+  CreatedAtAsc = 'createdAt_ASC',
+  CreatedAtDesc = 'createdAt_DESC'
+}
+
+export type UserScalarWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<UserScalarWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<UserScalarWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<UserScalarWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  email?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  email_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  email_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  email_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  email_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  email_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  email_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  email_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  email_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  email_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  email_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  email_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  email_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  email_not_ends_with?: Maybe<Scalars['String']>,
+  name?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  name_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  name_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  name_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  name_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  name_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  name_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  name_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  name_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  name_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  name_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  name_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  name_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  name_not_ends_with?: Maybe<Scalars['String']>,
+  password?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  password_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  password_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  password_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  password_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  password_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  password_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  password_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  password_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  password_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  password_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  password_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  password_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  password_not_ends_with?: Maybe<Scalars['String']>,
+  resetToken?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  resetToken_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  resetToken_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  resetToken_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  resetToken_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  resetToken_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  resetToken_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  resetToken_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  resetToken_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  resetToken_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  resetToken_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  resetToken_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  resetToken_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  resetToken_not_ends_with?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  /** All values that are not equal to given value. */
+  resetTokenExpiry_not?: Maybe<Scalars['Float']>,
+  /** All values that are contained in given list. */
+  resetTokenExpiry_in?: Maybe<Array<Scalars['Float']>>,
+  /** All values that are not contained in given list. */
+  resetTokenExpiry_not_in?: Maybe<Array<Scalars['Float']>>,
+  /** All values less than the given value. */
+  resetTokenExpiry_lt?: Maybe<Scalars['Float']>,
+  /** All values less than or equal the given value. */
+  resetTokenExpiry_lte?: Maybe<Scalars['Float']>,
+  /** All values greater than the given value. */
+  resetTokenExpiry_gt?: Maybe<Scalars['Float']>,
+  /** All values greater than or equal the given value. */
+  resetTokenExpiry_gte?: Maybe<Scalars['Float']>,
+  createdAt?: Maybe<Scalars['DateTime']>,
+  /** All values that are not equal to given value. */
+  createdAt_not?: Maybe<Scalars['DateTime']>,
+  /** All values that are contained in given list. */
+  createdAt_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values that are not contained in given list. */
+  createdAt_not_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values less than the given value. */
+  createdAt_lt?: Maybe<Scalars['DateTime']>,
+  /** All values less than or equal the given value. */
+  createdAt_lte?: Maybe<Scalars['DateTime']>,
+  /** All values greater than the given value. */
+  createdAt_gt?: Maybe<Scalars['DateTime']>,
+  /** All values greater than or equal the given value. */
+  createdAt_gte?: Maybe<Scalars['DateTime']>,
+};
+
+export type UserUpdateDataInput = {
+  email?: Maybe<Scalars['String']>,
+  name?: Maybe<Scalars['String']>,
+  password?: Maybe<Scalars['String']>,
+  resetToken?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  permissions?: Maybe<UserUpdatepermissionsInput>,
+  interests?: Maybe<UserUpdateinterestsInput>,
+  comments?: Maybe<CommentUpdateManyWithoutAuthorInput>,
+  ratings?: Maybe<RatingUpdateManyWithoutUserInput>,
+};
+
+export type UserUpdateInput = {
+  email?: Maybe<Scalars['String']>,
+  name?: Maybe<Scalars['String']>,
+  password?: Maybe<Scalars['String']>,
+  resetToken?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  permissions?: Maybe<UserUpdatepermissionsInput>,
+  interests?: Maybe<UserUpdateinterestsInput>,
+  comments?: Maybe<CommentUpdateManyWithoutAuthorInput>,
+  ratings?: Maybe<RatingUpdateManyWithoutUserInput>,
+};
+
+export type UserUpdateinterestsInput = {
+  set?: Maybe<Array<Scalars['String']>>,
+};
+
+export type UserUpdateManyDataInput = {
+  email?: Maybe<Scalars['String']>,
+  name?: Maybe<Scalars['String']>,
+  password?: Maybe<Scalars['String']>,
+  resetToken?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  permissions?: Maybe<UserUpdatepermissionsInput>,
+  interests?: Maybe<UserUpdateinterestsInput>,
+};
+
+export type UserUpdateManyInput = {
+  create?: Maybe<Array<UserCreateInput>>,
+  connect?: Maybe<Array<UserWhereUniqueInput>>,
+  set?: Maybe<Array<UserWhereUniqueInput>>,
+  disconnect?: Maybe<Array<UserWhereUniqueInput>>,
+  delete?: Maybe<Array<UserWhereUniqueInput>>,
+  update?: Maybe<Array<UserUpdateWithWhereUniqueNestedInput>>,
+  updateMany?: Maybe<Array<UserUpdateManyWithWhereNestedInput>>,
+  deleteMany?: Maybe<Array<UserScalarWhereInput>>,
+  upsert?: Maybe<Array<UserUpsertWithWhereUniqueNestedInput>>,
+};
+
+export type UserUpdateManyWithWhereNestedInput = {
+  where: UserScalarWhereInput,
+  data: UserUpdateManyDataInput,
+};
+
+export type UserUpdateOneRequiredWithoutRatingsInput = {
+  create?: Maybe<UserCreateWithoutRatingsInput>,
+  connect?: Maybe<UserWhereUniqueInput>,
+  update?: Maybe<UserUpdateWithoutRatingsDataInput>,
+  upsert?: Maybe<UserUpsertWithoutRatingsInput>,
+};
+
+export type UserUpdatepermissionsInput = {
+  set?: Maybe<Array<Permission>>,
+};
+
+export type UserUpdateWithoutRatingsDataInput = {
+  email?: Maybe<Scalars['String']>,
+  name?: Maybe<Scalars['String']>,
+  password?: Maybe<Scalars['String']>,
+  resetToken?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  permissions?: Maybe<UserUpdatepermissionsInput>,
+  interests?: Maybe<UserUpdateinterestsInput>,
+  comments?: Maybe<CommentUpdateManyWithoutAuthorInput>,
+};
+
+export type UserUpdateWithWhereUniqueNestedInput = {
+  where: UserWhereUniqueInput,
+  data: UserUpdateDataInput,
+};
+
+export type UserUpsertWithoutRatingsInput = {
+  update: UserUpdateWithoutRatingsDataInput,
+  create: UserCreateWithoutRatingsInput,
+};
+
+export type UserUpsertWithWhereUniqueNestedInput = {
+  where: UserWhereUniqueInput,
+  update: UserUpdateDataInput,
+  create: UserCreateInput,
+};
+
+export type UserWhereInput = {
+  /** Logical AND on all given filters. */
+  AND?: Maybe<Array<UserWhereInput>>,
+  /** Logical OR on all given filters. */
+  OR?: Maybe<Array<UserWhereInput>>,
+  /** Logical NOT on all given filters combined by AND. */
+  NOT?: Maybe<Array<UserWhereInput>>,
+  id?: Maybe<Scalars['ID']>,
+  /** All values that are not equal to given value. */
+  id_not?: Maybe<Scalars['ID']>,
+  /** All values that are contained in given list. */
+  id_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values that are not contained in given list. */
+  id_not_in?: Maybe<Array<Scalars['ID']>>,
+  /** All values less than the given value. */
+  id_lt?: Maybe<Scalars['ID']>,
+  /** All values less than or equal the given value. */
+  id_lte?: Maybe<Scalars['ID']>,
+  /** All values greater than the given value. */
+  id_gt?: Maybe<Scalars['ID']>,
+  /** All values greater than or equal the given value. */
+  id_gte?: Maybe<Scalars['ID']>,
+  /** All values containing the given string. */
+  id_contains?: Maybe<Scalars['ID']>,
+  /** All values not containing the given string. */
+  id_not_contains?: Maybe<Scalars['ID']>,
+  /** All values starting with the given string. */
+  id_starts_with?: Maybe<Scalars['ID']>,
+  /** All values not starting with the given string. */
+  id_not_starts_with?: Maybe<Scalars['ID']>,
+  /** All values ending with the given string. */
+  id_ends_with?: Maybe<Scalars['ID']>,
+  /** All values not ending with the given string. */
+  id_not_ends_with?: Maybe<Scalars['ID']>,
+  email?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  email_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  email_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  email_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  email_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  email_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  email_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  email_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  email_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  email_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  email_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  email_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  email_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  email_not_ends_with?: Maybe<Scalars['String']>,
+  name?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  name_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  name_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  name_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  name_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  name_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  name_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  name_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  name_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  name_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  name_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  name_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  name_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  name_not_ends_with?: Maybe<Scalars['String']>,
+  password?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  password_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  password_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  password_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  password_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  password_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  password_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  password_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  password_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  password_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  password_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  password_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  password_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  password_not_ends_with?: Maybe<Scalars['String']>,
+  resetToken?: Maybe<Scalars['String']>,
+  /** All values that are not equal to given value. */
+  resetToken_not?: Maybe<Scalars['String']>,
+  /** All values that are contained in given list. */
+  resetToken_in?: Maybe<Array<Scalars['String']>>,
+  /** All values that are not contained in given list. */
+  resetToken_not_in?: Maybe<Array<Scalars['String']>>,
+  /** All values less than the given value. */
+  resetToken_lt?: Maybe<Scalars['String']>,
+  /** All values less than or equal the given value. */
+  resetToken_lte?: Maybe<Scalars['String']>,
+  /** All values greater than the given value. */
+  resetToken_gt?: Maybe<Scalars['String']>,
+  /** All values greater than or equal the given value. */
+  resetToken_gte?: Maybe<Scalars['String']>,
+  /** All values containing the given string. */
+  resetToken_contains?: Maybe<Scalars['String']>,
+  /** All values not containing the given string. */
+  resetToken_not_contains?: Maybe<Scalars['String']>,
+  /** All values starting with the given string. */
+  resetToken_starts_with?: Maybe<Scalars['String']>,
+  /** All values not starting with the given string. */
+  resetToken_not_starts_with?: Maybe<Scalars['String']>,
+  /** All values ending with the given string. */
+  resetToken_ends_with?: Maybe<Scalars['String']>,
+  /** All values not ending with the given string. */
+  resetToken_not_ends_with?: Maybe<Scalars['String']>,
+  resetTokenExpiry?: Maybe<Scalars['Float']>,
+  /** All values that are not equal to given value. */
+  resetTokenExpiry_not?: Maybe<Scalars['Float']>,
+  /** All values that are contained in given list. */
+  resetTokenExpiry_in?: Maybe<Array<Scalars['Float']>>,
+  /** All values that are not contained in given list. */
+  resetTokenExpiry_not_in?: Maybe<Array<Scalars['Float']>>,
+  /** All values less than the given value. */
+  resetTokenExpiry_lt?: Maybe<Scalars['Float']>,
+  /** All values less than or equal the given value. */
+  resetTokenExpiry_lte?: Maybe<Scalars['Float']>,
+  /** All values greater than the given value. */
+  resetTokenExpiry_gt?: Maybe<Scalars['Float']>,
+  /** All values greater than or equal the given value. */
+  resetTokenExpiry_gte?: Maybe<Scalars['Float']>,
+  createdAt?: Maybe<Scalars['DateTime']>,
+  /** All values that are not equal to given value. */
+  createdAt_not?: Maybe<Scalars['DateTime']>,
+  /** All values that are contained in given list. */
+  createdAt_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values that are not contained in given list. */
+  createdAt_not_in?: Maybe<Array<Scalars['DateTime']>>,
+  /** All values less than the given value. */
+  createdAt_lt?: Maybe<Scalars['DateTime']>,
+  /** All values less than or equal the given value. */
+  createdAt_lte?: Maybe<Scalars['DateTime']>,
+  /** All values greater than the given value. */
+  createdAt_gt?: Maybe<Scalars['DateTime']>,
+  /** All values greater than or equal the given value. */
+  createdAt_gte?: Maybe<Scalars['DateTime']>,
+  comments_every?: Maybe<CommentWhereInput>,
+  comments_some?: Maybe<CommentWhereInput>,
+  comments_none?: Maybe<CommentWhereInput>,
+  ratings_every?: Maybe<RatingWhereInput>,
+  ratings_some?: Maybe<RatingWhereInput>,
+  ratings_none?: Maybe<RatingWhereInput>,
+};
+
+export type UserWhereUniqueInput = {
+  id?: Maybe<Scalars['ID']>,
+  email?: Maybe<Scalars['String']>,
+};
+
+
+
+export type ResolverTypeWrapper<T> = Promise<T> | T;
+
+
+export type StitchingResolver<TResult, TParent, TContext, TArgs> = {
+  fragment: string;
+  resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
+};
+
+export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
+  | ResolverFn<TResult, TParent, TContext, TArgs>
+  | StitchingResolver<TResult, TParent, TContext, TArgs>;
+
+export type ResolverFn<TResult, TParent, TContext, TArgs> = (
+  parent: TParent,
+  args: TArgs,
+  context: TContext,
+  info: GraphQLResolveInfo
+) => Promise<TResult> | TResult;
+
+export type SubscriptionSubscribeFn<TResult, TParent, TContext, TArgs> = (
+  parent: TParent,
+  args: TArgs,
+  context: TContext,
+  info: GraphQLResolveInfo
+) => AsyncIterator<TResult> | Promise<AsyncIterator<TResult>>;
+
+export type SubscriptionResolveFn<TResult, TParent, TContext, TArgs> = (
+  parent: TParent,
+  args: TArgs,
+  context: TContext,
+  info: GraphQLResolveInfo
+) => TResult | Promise<TResult>;
+
+export interface SubscriptionSubscriberObject<TResult, TKey extends string, TParent, TContext, TArgs> {
+  subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>;
+  resolve?: SubscriptionResolveFn<TResult, { [key in TKey]: TResult }, TContext, TArgs>;
+}
+
+export interface SubscriptionResolverObject<TResult, TParent, TContext, TArgs> {
+  subscribe: SubscriptionSubscribeFn<any, TParent, TContext, TArgs>;
+  resolve: SubscriptionResolveFn<TResult, any, TContext, TArgs>;
+}
+
+export type SubscriptionObject<TResult, TKey extends string, TParent, TContext, TArgs> =
+  | SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
+  | SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
+
+export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
+  | ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
+  | SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;
+
+export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
+  parent: TParent,
+  context: TContext,
+  info: GraphQLResolveInfo
+) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
+
+export type isTypeOfResolverFn<T = {}> = (obj: T, info: GraphQLResolveInfo) => boolean | Promise<boolean>;
+
+export type NextResolverFn<T> = () => Promise<T>;
+
+export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
+  next: NextResolverFn<TResult>,
+  parent: TParent,
+  args: TArgs,
+  context: TContext,
+  info: GraphQLResolveInfo
+) => TResult | Promise<TResult>;
+
+/** Mapping between all available schema types and the resolvers types */
+export type ResolversTypes = {
+  Query: ResolverTypeWrapper<{}>,
+  Int: ResolverTypeWrapper<Scalars['Int']>,
+  TrainingArchive: ResolverTypeWrapper<TrainingArchive>,
+  TrainingArchiveItem: ResolverTypeWrapper<TrainingArchiveItem>,
+  ID: ResolverTypeWrapper<Scalars['ID']>,
+  String: ResolverTypeWrapper<Scalars['String']>,
+  TrainingType: ResolverTypeWrapper<TrainingType>,
+  Node: ResolversTypes['TrainingType'] | ResolversTypes['Training'] | ResolversTypes['User'] | ResolversTypes['Comment'] | ResolversTypes['Rating'] | ResolversTypes['BlockInstance'] | ResolversTypes['Block'] | ResolversTypes['Format'] | ResolversTypes['Track'] | ResolversTypes['ExerciseInstance'] | ResolversTypes['Exercise'] | ResolversTypes['File'],
+  DateTime: ResolverTypeWrapper<Scalars['DateTime']>,
+  Float: ResolverTypeWrapper<Scalars['Float']>,
+  TrainingWhereInput: TrainingWhereInput,
+  Boolean: ResolverTypeWrapper<Scalars['Boolean']>,
+  TrainingTypeWhereInput: TrainingTypeWhereInput,
+  UserWhereInput: UserWhereInput,
+  CommentWhereInput: CommentWhereInput,
+  RatingWhereInput: RatingWhereInput,
+  BlockInstanceWhereInput: BlockInstanceWhereInput,
+  BlockWhereInput: BlockWhereInput,
+  FormatWhereInput: FormatWhereInput,
+  TrackWhereInput: TrackWhereInput,
+  ExerciseInstanceWhereInput: ExerciseInstanceWhereInput,
+  ExerciseWhereInput: ExerciseWhereInput,
+  TrainingOrderByInput: TrainingOrderByInput,
+  Training: ResolverTypeWrapper<Training>,
+  UserOrderByInput: UserOrderByInput,
+  User: ResolverTypeWrapper<User>,
+  CommentOrderByInput: CommentOrderByInput,
+  Comment: ResolverTypeWrapper<Comment>,
+  RatingOrderByInput: RatingOrderByInput,
+  Rating: ResolverTypeWrapper<Rating>,
+  Permission: Permission,
+  BlockInstanceOrderByInput: BlockInstanceOrderByInput,
+  BlockInstance: ResolverTypeWrapper<BlockInstance>,
+  Block: ResolverTypeWrapper<Block>,
+  Format: ResolverTypeWrapper<Format>,
+  TrackOrderByInput: TrackOrderByInput,
+  Track: ResolverTypeWrapper<Track>,
+  ExerciseInstanceOrderByInput: ExerciseInstanceOrderByInput,
+  ExerciseInstance: ResolverTypeWrapper<ExerciseInstance>,
+  Exercise: ResolverTypeWrapper<Exercise>,
+  TrainingConnection: ResolverTypeWrapper<TrainingConnection>,
+  PageInfo: ResolverTypeWrapper<PageInfo>,
+  TrainingEdge: ResolverTypeWrapper<TrainingEdge>,
+  AggregateTraining: ResolverTypeWrapper<AggregateTraining>,
+  FsFile: ResolverTypeWrapper<FsFile>,
+  File: ResolverTypeWrapper<File>,
+  UserWhereUniqueInput: UserWhereUniqueInput,
+  TrainingTypeWhereUniqueInput: TrainingTypeWhereUniqueInput,
+  TrainingTypeOrderByInput: TrainingTypeOrderByInput,
+  BlockWhereUniqueInput: BlockWhereUniqueInput,
+  BlockOrderByInput: BlockOrderByInput,
+  FormatWhereUniqueInput: FormatWhereUniqueInput,
+  FormatOrderByInput: FormatOrderByInput,
+  ExerciseWhereUniqueInput: ExerciseWhereUniqueInput,
+  ExerciseOrderByInput: ExerciseOrderByInput,
+  Mutation: ResolverTypeWrapper<{}>,
+  Upload: ResolverTypeWrapper<Scalars['Upload']>,
+  UserCreateInput: UserCreateInput,
+  UserCreatepermissionsInput: UserCreatepermissionsInput,
+  UserCreateinterestsInput: UserCreateinterestsInput,
+  CommentCreateManyWithoutAuthorInput: CommentCreateManyWithoutAuthorInput,
+  CommentCreateWithoutAuthorInput: CommentCreateWithoutAuthorInput,
+  CommentWhereUniqueInput: CommentWhereUniqueInput,
+  RatingCreateManyWithoutUserInput: RatingCreateManyWithoutUserInput,
+  RatingCreateWithoutUserInput: RatingCreateWithoutUserInput,
+  RatingWhereUniqueInput: RatingWhereUniqueInput,
+  UserUpdateInput: UserUpdateInput,
+  UserUpdatepermissionsInput: UserUpdatepermissionsInput,
+  UserUpdateinterestsInput: UserUpdateinterestsInput,
+  CommentUpdateManyWithoutAuthorInput: CommentUpdateManyWithoutAuthorInput,
+  CommentUpdateWithWhereUniqueWithoutAuthorInput: CommentUpdateWithWhereUniqueWithoutAuthorInput,
+  CommentUpdateWithoutAuthorDataInput: CommentUpdateWithoutAuthorDataInput,
+  CommentUpdateManyWithWhereNestedInput: CommentUpdateManyWithWhereNestedInput,
+  CommentScalarWhereInput: CommentScalarWhereInput,
+  CommentUpdateManyDataInput: CommentUpdateManyDataInput,
+  CommentUpsertWithWhereUniqueWithoutAuthorInput: CommentUpsertWithWhereUniqueWithoutAuthorInput,
+  RatingUpdateManyWithoutUserInput: RatingUpdateManyWithoutUserInput,
+  RatingUpdateWithWhereUniqueWithoutUserInput: RatingUpdateWithWhereUniqueWithoutUserInput,
+  RatingUpdateWithoutUserDataInput: RatingUpdateWithoutUserDataInput,
+  RatingUpdateManyWithWhereNestedInput: RatingUpdateManyWithWhereNestedInput,
+  RatingScalarWhereInput: RatingScalarWhereInput,
+  RatingUpdateManyDataInput: RatingUpdateManyDataInput,
+  RatingUpsertWithWhereUniqueWithoutUserInput: RatingUpsertWithWhereUniqueWithoutUserInput,
+  TrainingTypeCreateOneInput: TrainingTypeCreateOneInput,
+  TrainingTypeCreateInput: TrainingTypeCreateInput,
+  BlockInstanceCreateManyWithoutParentTrainingInput: BlockInstanceCreateManyWithoutParentTrainingInput,
+  BlockInstanceCreateWithoutParentTrainingInput: BlockInstanceCreateWithoutParentTrainingInput,
+  BlockCreateOneWithoutParentBlockInstancesInput: BlockCreateOneWithoutParentBlockInstancesInput,
+  BlockCreateWithoutParentBlockInstancesInput: BlockCreateWithoutParentBlockInstancesInput,
+  BlockCreatevideosInput: BlockCreatevideosInput,
+  BlockCreatepicturesInput: BlockCreatepicturesInput,
+  FormatCreateOneInput: FormatCreateOneInput,
+  FormatCreateInput: FormatCreateInput,
+  TrackCreateManyInput: TrackCreateManyInput,
+  TrackCreateInput: TrackCreateInput,
+  TrackWhereUniqueInput: TrackWhereUniqueInput,
+  BlockInstanceCreateManyWithoutParentBlockInput: BlockInstanceCreateManyWithoutParentBlockInput,
+  BlockInstanceCreateWithoutParentBlockInput: BlockInstanceCreateWithoutParentBlockInput,
+  TrainingCreateOneWithoutBlocksInput: TrainingCreateOneWithoutBlocksInput,
+  TrainingCreateWithoutBlocksInput: TrainingCreateWithoutBlocksInput,
+  UserCreateManyInput: UserCreateManyInput,
+  RatingCreateManyInput: RatingCreateManyInput,
+  RatingCreateInput: RatingCreateInput,
+  UserCreateOneWithoutRatingsInput: UserCreateOneWithoutRatingsInput,
+  UserCreateWithoutRatingsInput: UserCreateWithoutRatingsInput,
+  TrainingWhereUniqueInput: TrainingWhereUniqueInput,
+  BlockInstanceWhereUniqueInput: BlockInstanceWhereUniqueInput,
+  ExerciseInstanceCreateManyWithoutParentBlockInstancesInput: ExerciseInstanceCreateManyWithoutParentBlockInstancesInput,
+  ExerciseInstanceCreateWithoutParentBlockInstancesInput: ExerciseInstanceCreateWithoutParentBlockInstancesInput,
+  ExerciseCreateOneWithoutParentExerciseInstancesInput: ExerciseCreateOneWithoutParentExerciseInstancesInput,
+  ExerciseCreateWithoutParentExerciseInstancesInput: ExerciseCreateWithoutParentExerciseInstancesInput,
+  ExerciseCreatevideosInput: ExerciseCreatevideosInput,
+  ExerciseCreatepicturesInput: ExerciseCreatepicturesInput,
+  ExerciseCreatetargetsInput: ExerciseCreatetargetsInput,
+  ExerciseCreatebaseExerciseInput: ExerciseCreatebaseExerciseInput,
+  ExerciseInstanceWhereUniqueInput: ExerciseInstanceWhereUniqueInput,
+  BlockCreateOneWithoutBlocksInput: BlockCreateOneWithoutBlocksInput,
+  BlockCreateWithoutBlocksInput: BlockCreateWithoutBlocksInput,
+  BlockInstanceCreateManyWithoutBlockInput: BlockInstanceCreateManyWithoutBlockInput,
+  BlockInstanceCreateWithoutBlockInput: BlockInstanceCreateWithoutBlockInput,
+  TrainingUpdateInput: TrainingUpdateInput,
+  TrainingTypeUpdateOneRequiredInput: TrainingTypeUpdateOneRequiredInput,
+  TrainingTypeUpdateDataInput: TrainingTypeUpdateDataInput,
+  TrainingTypeUpsertNestedInput: TrainingTypeUpsertNestedInput,
+  UserUpdateManyInput: UserUpdateManyInput,
+  UserUpdateWithWhereUniqueNestedInput: UserUpdateWithWhereUniqueNestedInput,
+  UserUpdateDataInput: UserUpdateDataInput,
+  UserUpdateManyWithWhereNestedInput: UserUpdateManyWithWhereNestedInput,
+  UserScalarWhereInput: UserScalarWhereInput,
+  UserUpdateManyDataInput: UserUpdateManyDataInput,
+  UserUpsertWithWhereUniqueNestedInput: UserUpsertWithWhereUniqueNestedInput,
+  RatingUpdateManyInput: RatingUpdateManyInput,
+  RatingUpdateWithWhereUniqueNestedInput: RatingUpdateWithWhereUniqueNestedInput,
+  RatingUpdateDataInput: RatingUpdateDataInput,
+  UserUpdateOneRequiredWithoutRatingsInput: UserUpdateOneRequiredWithoutRatingsInput,
+  UserUpdateWithoutRatingsDataInput: UserUpdateWithoutRatingsDataInput,
+  UserUpsertWithoutRatingsInput: UserUpsertWithoutRatingsInput,
+  RatingUpsertWithWhereUniqueNestedInput: RatingUpsertWithWhereUniqueNestedInput,
+  BlockInstanceUpdateManyWithoutParentTrainingInput: BlockInstanceUpdateManyWithoutParentTrainingInput,
+  BlockInstanceUpdateWithWhereUniqueWithoutParentTrainingInput: BlockInstanceUpdateWithWhereUniqueWithoutParentTrainingInput,
+  BlockInstanceUpdateWithoutParentTrainingDataInput: BlockInstanceUpdateWithoutParentTrainingDataInput,
+  BlockUpdateOneRequiredWithoutParentBlockInstancesInput: BlockUpdateOneRequiredWithoutParentBlockInstancesInput,
+  BlockUpdateWithoutParentBlockInstancesDataInput: BlockUpdateWithoutParentBlockInstancesDataInput,
+  BlockUpdatevideosInput: BlockUpdatevideosInput,
+  BlockUpdatepicturesInput: BlockUpdatepicturesInput,
+  FormatUpdateOneRequiredInput: FormatUpdateOneRequiredInput,
+  FormatUpdateDataInput: FormatUpdateDataInput,
+  FormatUpsertNestedInput: FormatUpsertNestedInput,
+  TrackUpdateManyInput: TrackUpdateManyInput,
+  TrackUpdateWithWhereUniqueNestedInput: TrackUpdateWithWhereUniqueNestedInput,
+  TrackUpdateDataInput: TrackUpdateDataInput,
+  TrackUpdateManyWithWhereNestedInput: TrackUpdateManyWithWhereNestedInput,
+  TrackScalarWhereInput: TrackScalarWhereInput,
+  TrackUpdateManyDataInput: TrackUpdateManyDataInput,
+  TrackUpsertWithWhereUniqueNestedInput: TrackUpsertWithWhereUniqueNestedInput,
+  BlockInstanceUpdateManyWithoutParentBlockInput: BlockInstanceUpdateManyWithoutParentBlockInput,
+  BlockInstanceUpdateWithWhereUniqueWithoutParentBlockInput: BlockInstanceUpdateWithWhereUniqueWithoutParentBlockInput,
+  BlockInstanceUpdateWithoutParentBlockDataInput: BlockInstanceUpdateWithoutParentBlockDataInput,
+  TrainingUpdateOneWithoutBlocksInput: TrainingUpdateOneWithoutBlocksInput,
+  TrainingUpdateWithoutBlocksDataInput: TrainingUpdateWithoutBlocksDataInput,
+  TrainingUpsertWithoutBlocksInput: TrainingUpsertWithoutBlocksInput,
+  BlockInstanceUpdateManyWithWhereNestedInput: BlockInstanceUpdateManyWithWhereNestedInput,
+  BlockInstanceScalarWhereInput: BlockInstanceScalarWhereInput,
+  BlockInstanceUpdateManyDataInput: BlockInstanceUpdateManyDataInput,
+  BlockInstanceUpsertWithWhereUniqueWithoutParentBlockInput: BlockInstanceUpsertWithWhereUniqueWithoutParentBlockInput,
+  ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput: ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput,
+  ExerciseInstanceUpdateWithWhereUniqueWithoutParentBlockInstancesInput: ExerciseInstanceUpdateWithWhereUniqueWithoutParentBlockInstancesInput,
+  ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput: ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput,
+  ExerciseUpdateOneRequiredWithoutParentExerciseInstancesInput: ExerciseUpdateOneRequiredWithoutParentExerciseInstancesInput,
+  ExerciseUpdateWithoutParentExerciseInstancesDataInput: ExerciseUpdateWithoutParentExerciseInstancesDataInput,
+  ExerciseUpdatevideosInput: ExerciseUpdatevideosInput,
+  ExerciseUpdatepicturesInput: ExerciseUpdatepicturesInput,
+  ExerciseUpdatetargetsInput: ExerciseUpdatetargetsInput,
+  ExerciseUpdatebaseExerciseInput: ExerciseUpdatebaseExerciseInput,
+  ExerciseUpsertWithoutParentExerciseInstancesInput: ExerciseUpsertWithoutParentExerciseInstancesInput,
+  ExerciseInstanceUpdateManyWithWhereNestedInput: ExerciseInstanceUpdateManyWithWhereNestedInput,
+  ExerciseInstanceScalarWhereInput: ExerciseInstanceScalarWhereInput,
+  ExerciseInstanceUpdateManyDataInput: ExerciseInstanceUpdateManyDataInput,
+  ExerciseInstanceUpsertWithWhereUniqueWithoutParentBlockInstancesInput: ExerciseInstanceUpsertWithWhereUniqueWithoutParentBlockInstancesInput,
+  BlockUpsertWithoutParentBlockInstancesInput: BlockUpsertWithoutParentBlockInstancesInput,
+  BlockUpdateOneWithoutBlocksInput: BlockUpdateOneWithoutBlocksInput,
+  BlockUpdateWithoutBlocksDataInput: BlockUpdateWithoutBlocksDataInput,
+  BlockInstanceUpdateManyWithoutBlockInput: BlockInstanceUpdateManyWithoutBlockInput,
+  BlockInstanceUpdateWithWhereUniqueWithoutBlockInput: BlockInstanceUpdateWithWhereUniqueWithoutBlockInput,
+  BlockInstanceUpdateWithoutBlockDataInput: BlockInstanceUpdateWithoutBlockDataInput,
+  BlockInstanceUpsertWithWhereUniqueWithoutBlockInput: BlockInstanceUpsertWithWhereUniqueWithoutBlockInput,
+  BlockUpsertWithoutBlocksInput: BlockUpsertWithoutBlocksInput,
+  BlockInstanceUpsertWithWhereUniqueWithoutParentTrainingInput: BlockInstanceUpsertWithWhereUniqueWithoutParentTrainingInput,
+};
+
+/** Mapping between all available schema types and the resolvers parents */
+export type ResolversParentTypes = {
+  Query: {},
+  Int: Scalars['Int'],
+  TrainingArchive: TrainingArchive,
+  TrainingArchiveItem: TrainingArchiveItem,
+  ID: Scalars['ID'],
+  String: Scalars['String'],
+  TrainingType: TrainingType,
+  Node: ResolversParentTypes['TrainingType'] | ResolversParentTypes['Training'] | ResolversParentTypes['User'] | ResolversParentTypes['Comment'] | ResolversParentTypes['Rating'] | ResolversParentTypes['BlockInstance'] | ResolversParentTypes['Block'] | ResolversParentTypes['Format'] | ResolversParentTypes['Track'] | ResolversParentTypes['ExerciseInstance'] | ResolversParentTypes['Exercise'] | ResolversParentTypes['File'],
+  DateTime: Scalars['DateTime'],
+  Float: Scalars['Float'],
+  TrainingWhereInput: TrainingWhereInput,
+  Boolean: Scalars['Boolean'],
+  TrainingTypeWhereInput: TrainingTypeWhereInput,
+  UserWhereInput: UserWhereInput,
+  CommentWhereInput: CommentWhereInput,
+  RatingWhereInput: RatingWhereInput,
+  BlockInstanceWhereInput: BlockInstanceWhereInput,
+  BlockWhereInput: BlockWhereInput,
+  FormatWhereInput: FormatWhereInput,
+  TrackWhereInput: TrackWhereInput,
+  ExerciseInstanceWhereInput: ExerciseInstanceWhereInput,
+  ExerciseWhereInput: ExerciseWhereInput,
+  TrainingOrderByInput: TrainingOrderByInput,
+  Training: Training,
+  UserOrderByInput: UserOrderByInput,
+  User: User,
+  CommentOrderByInput: CommentOrderByInput,
+  Comment: Comment,
+  RatingOrderByInput: RatingOrderByInput,
+  Rating: Rating,
+  Permission: Permission,
+  BlockInstanceOrderByInput: BlockInstanceOrderByInput,
+  BlockInstance: BlockInstance,
+  Block: Block,
+  Format: Format,
+  TrackOrderByInput: TrackOrderByInput,
+  Track: Track,
+  ExerciseInstanceOrderByInput: ExerciseInstanceOrderByInput,
+  ExerciseInstance: ExerciseInstance,
+  Exercise: Exercise,
+  TrainingConnection: TrainingConnection,
+  PageInfo: PageInfo,
+  TrainingEdge: TrainingEdge,
+  AggregateTraining: AggregateTraining,
+  FsFile: FsFile,
+  File: File,
+  UserWhereUniqueInput: UserWhereUniqueInput,
+  TrainingTypeWhereUniqueInput: TrainingTypeWhereUniqueInput,
+  TrainingTypeOrderByInput: TrainingTypeOrderByInput,
+  BlockWhereUniqueInput: BlockWhereUniqueInput,
+  BlockOrderByInput: BlockOrderByInput,
+  FormatWhereUniqueInput: FormatWhereUniqueInput,
+  FormatOrderByInput: FormatOrderByInput,
+  ExerciseWhereUniqueInput: ExerciseWhereUniqueInput,
+  ExerciseOrderByInput: ExerciseOrderByInput,
+  Mutation: {},
+  Upload: Scalars['Upload'],
+  UserCreateInput: UserCreateInput,
+  UserCreatepermissionsInput: UserCreatepermissionsInput,
+  UserCreateinterestsInput: UserCreateinterestsInput,
+  CommentCreateManyWithoutAuthorInput: CommentCreateManyWithoutAuthorInput,
+  CommentCreateWithoutAuthorInput: CommentCreateWithoutAuthorInput,
+  CommentWhereUniqueInput: CommentWhereUniqueInput,
+  RatingCreateManyWithoutUserInput: RatingCreateManyWithoutUserInput,
+  RatingCreateWithoutUserInput: RatingCreateWithoutUserInput,
+  RatingWhereUniqueInput: RatingWhereUniqueInput,
+  UserUpdateInput: UserUpdateInput,
+  UserUpdatepermissionsInput: UserUpdatepermissionsInput,
+  UserUpdateinterestsInput: UserUpdateinterestsInput,
+  CommentUpdateManyWithoutAuthorInput: CommentUpdateManyWithoutAuthorInput,
+  CommentUpdateWithWhereUniqueWithoutAuthorInput: CommentUpdateWithWhereUniqueWithoutAuthorInput,
+  CommentUpdateWithoutAuthorDataInput: CommentUpdateWithoutAuthorDataInput,
+  CommentUpdateManyWithWhereNestedInput: CommentUpdateManyWithWhereNestedInput,
+  CommentScalarWhereInput: CommentScalarWhereInput,
+  CommentUpdateManyDataInput: CommentUpdateManyDataInput,
+  CommentUpsertWithWhereUniqueWithoutAuthorInput: CommentUpsertWithWhereUniqueWithoutAuthorInput,
+  RatingUpdateManyWithoutUserInput: RatingUpdateManyWithoutUserInput,
+  RatingUpdateWithWhereUniqueWithoutUserInput: RatingUpdateWithWhereUniqueWithoutUserInput,
+  RatingUpdateWithoutUserDataInput: RatingUpdateWithoutUserDataInput,
+  RatingUpdateManyWithWhereNestedInput: RatingUpdateManyWithWhereNestedInput,
+  RatingScalarWhereInput: RatingScalarWhereInput,
+  RatingUpdateManyDataInput: RatingUpdateManyDataInput,
+  RatingUpsertWithWhereUniqueWithoutUserInput: RatingUpsertWithWhereUniqueWithoutUserInput,
+  TrainingTypeCreateOneInput: TrainingTypeCreateOneInput,
+  TrainingTypeCreateInput: TrainingTypeCreateInput,
+  BlockInstanceCreateManyWithoutParentTrainingInput: BlockInstanceCreateManyWithoutParentTrainingInput,
+  BlockInstanceCreateWithoutParentTrainingInput: BlockInstanceCreateWithoutParentTrainingInput,
+  BlockCreateOneWithoutParentBlockInstancesInput: BlockCreateOneWithoutParentBlockInstancesInput,
+  BlockCreateWithoutParentBlockInstancesInput: BlockCreateWithoutParentBlockInstancesInput,
+  BlockCreatevideosInput: BlockCreatevideosInput,
+  BlockCreatepicturesInput: BlockCreatepicturesInput,
+  FormatCreateOneInput: FormatCreateOneInput,
+  FormatCreateInput: FormatCreateInput,
+  TrackCreateManyInput: TrackCreateManyInput,
+  TrackCreateInput: TrackCreateInput,
+  TrackWhereUniqueInput: TrackWhereUniqueInput,
+  BlockInstanceCreateManyWithoutParentBlockInput: BlockInstanceCreateManyWithoutParentBlockInput,
+  BlockInstanceCreateWithoutParentBlockInput: BlockInstanceCreateWithoutParentBlockInput,
+  TrainingCreateOneWithoutBlocksInput: TrainingCreateOneWithoutBlocksInput,
+  TrainingCreateWithoutBlocksInput: TrainingCreateWithoutBlocksInput,
+  UserCreateManyInput: UserCreateManyInput,
+  RatingCreateManyInput: RatingCreateManyInput,
+  RatingCreateInput: RatingCreateInput,
+  UserCreateOneWithoutRatingsInput: UserCreateOneWithoutRatingsInput,
+  UserCreateWithoutRatingsInput: UserCreateWithoutRatingsInput,
+  TrainingWhereUniqueInput: TrainingWhereUniqueInput,
+  BlockInstanceWhereUniqueInput: BlockInstanceWhereUniqueInput,
+  ExerciseInstanceCreateManyWithoutParentBlockInstancesInput: ExerciseInstanceCreateManyWithoutParentBlockInstancesInput,
+  ExerciseInstanceCreateWithoutParentBlockInstancesInput: ExerciseInstanceCreateWithoutParentBlockInstancesInput,
+  ExerciseCreateOneWithoutParentExerciseInstancesInput: ExerciseCreateOneWithoutParentExerciseInstancesInput,
+  ExerciseCreateWithoutParentExerciseInstancesInput: ExerciseCreateWithoutParentExerciseInstancesInput,
+  ExerciseCreatevideosInput: ExerciseCreatevideosInput,
+  ExerciseCreatepicturesInput: ExerciseCreatepicturesInput,
+  ExerciseCreatetargetsInput: ExerciseCreatetargetsInput,
+  ExerciseCreatebaseExerciseInput: ExerciseCreatebaseExerciseInput,
+  ExerciseInstanceWhereUniqueInput: ExerciseInstanceWhereUniqueInput,
+  BlockCreateOneWithoutBlocksInput: BlockCreateOneWithoutBlocksInput,
+  BlockCreateWithoutBlocksInput: BlockCreateWithoutBlocksInput,
+  BlockInstanceCreateManyWithoutBlockInput: BlockInstanceCreateManyWithoutBlockInput,
+  BlockInstanceCreateWithoutBlockInput: BlockInstanceCreateWithoutBlockInput,
+  TrainingUpdateInput: TrainingUpdateInput,
+  TrainingTypeUpdateOneRequiredInput: TrainingTypeUpdateOneRequiredInput,
+  TrainingTypeUpdateDataInput: TrainingTypeUpdateDataInput,
+  TrainingTypeUpsertNestedInput: TrainingTypeUpsertNestedInput,
+  UserUpdateManyInput: UserUpdateManyInput,
+  UserUpdateWithWhereUniqueNestedInput: UserUpdateWithWhereUniqueNestedInput,
+  UserUpdateDataInput: UserUpdateDataInput,
+  UserUpdateManyWithWhereNestedInput: UserUpdateManyWithWhereNestedInput,
+  UserScalarWhereInput: UserScalarWhereInput,
+  UserUpdateManyDataInput: UserUpdateManyDataInput,
+  UserUpsertWithWhereUniqueNestedInput: UserUpsertWithWhereUniqueNestedInput,
+  RatingUpdateManyInput: RatingUpdateManyInput,
+  RatingUpdateWithWhereUniqueNestedInput: RatingUpdateWithWhereUniqueNestedInput,
+  RatingUpdateDataInput: RatingUpdateDataInput,
+  UserUpdateOneRequiredWithoutRatingsInput: UserUpdateOneRequiredWithoutRatingsInput,
+  UserUpdateWithoutRatingsDataInput: UserUpdateWithoutRatingsDataInput,
+  UserUpsertWithoutRatingsInput: UserUpsertWithoutRatingsInput,
+  RatingUpsertWithWhereUniqueNestedInput: RatingUpsertWithWhereUniqueNestedInput,
+  BlockInstanceUpdateManyWithoutParentTrainingInput: BlockInstanceUpdateManyWithoutParentTrainingInput,
+  BlockInstanceUpdateWithWhereUniqueWithoutParentTrainingInput: BlockInstanceUpdateWithWhereUniqueWithoutParentTrainingInput,
+  BlockInstanceUpdateWithoutParentTrainingDataInput: BlockInstanceUpdateWithoutParentTrainingDataInput,
+  BlockUpdateOneRequiredWithoutParentBlockInstancesInput: BlockUpdateOneRequiredWithoutParentBlockInstancesInput,
+  BlockUpdateWithoutParentBlockInstancesDataInput: BlockUpdateWithoutParentBlockInstancesDataInput,
+  BlockUpdatevideosInput: BlockUpdatevideosInput,
+  BlockUpdatepicturesInput: BlockUpdatepicturesInput,
+  FormatUpdateOneRequiredInput: FormatUpdateOneRequiredInput,
+  FormatUpdateDataInput: FormatUpdateDataInput,
+  FormatUpsertNestedInput: FormatUpsertNestedInput,
+  TrackUpdateManyInput: TrackUpdateManyInput,
+  TrackUpdateWithWhereUniqueNestedInput: TrackUpdateWithWhereUniqueNestedInput,
+  TrackUpdateDataInput: TrackUpdateDataInput,
+  TrackUpdateManyWithWhereNestedInput: TrackUpdateManyWithWhereNestedInput,
+  TrackScalarWhereInput: TrackScalarWhereInput,
+  TrackUpdateManyDataInput: TrackUpdateManyDataInput,
+  TrackUpsertWithWhereUniqueNestedInput: TrackUpsertWithWhereUniqueNestedInput,
+  BlockInstanceUpdateManyWithoutParentBlockInput: BlockInstanceUpdateManyWithoutParentBlockInput,
+  BlockInstanceUpdateWithWhereUniqueWithoutParentBlockInput: BlockInstanceUpdateWithWhereUniqueWithoutParentBlockInput,
+  BlockInstanceUpdateWithoutParentBlockDataInput: BlockInstanceUpdateWithoutParentBlockDataInput,
+  TrainingUpdateOneWithoutBlocksInput: TrainingUpdateOneWithoutBlocksInput,
+  TrainingUpdateWithoutBlocksDataInput: TrainingUpdateWithoutBlocksDataInput,
+  TrainingUpsertWithoutBlocksInput: TrainingUpsertWithoutBlocksInput,
+  BlockInstanceUpdateManyWithWhereNestedInput: BlockInstanceUpdateManyWithWhereNestedInput,
+  BlockInstanceScalarWhereInput: BlockInstanceScalarWhereInput,
+  BlockInstanceUpdateManyDataInput: BlockInstanceUpdateManyDataInput,
+  BlockInstanceUpsertWithWhereUniqueWithoutParentBlockInput: BlockInstanceUpsertWithWhereUniqueWithoutParentBlockInput,
+  ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput: ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput,
+  ExerciseInstanceUpdateWithWhereUniqueWithoutParentBlockInstancesInput: ExerciseInstanceUpdateWithWhereUniqueWithoutParentBlockInstancesInput,
+  ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput: ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput,
+  ExerciseUpdateOneRequiredWithoutParentExerciseInstancesInput: ExerciseUpdateOneRequiredWithoutParentExerciseInstancesInput,
+  ExerciseUpdateWithoutParentExerciseInstancesDataInput: ExerciseUpdateWithoutParentExerciseInstancesDataInput,
+  ExerciseUpdatevideosInput: ExerciseUpdatevideosInput,
+  ExerciseUpdatepicturesInput: ExerciseUpdatepicturesInput,
+  ExerciseUpdatetargetsInput: ExerciseUpdatetargetsInput,
+  ExerciseUpdatebaseExerciseInput: ExerciseUpdatebaseExerciseInput,
+  ExerciseUpsertWithoutParentExerciseInstancesInput: ExerciseUpsertWithoutParentExerciseInstancesInput,
+  ExerciseInstanceUpdateManyWithWhereNestedInput: ExerciseInstanceUpdateManyWithWhereNestedInput,
+  ExerciseInstanceScalarWhereInput: ExerciseInstanceScalarWhereInput,
+  ExerciseInstanceUpdateManyDataInput: ExerciseInstanceUpdateManyDataInput,
+  ExerciseInstanceUpsertWithWhereUniqueWithoutParentBlockInstancesInput: ExerciseInstanceUpsertWithWhereUniqueWithoutParentBlockInstancesInput,
+  BlockUpsertWithoutParentBlockInstancesInput: BlockUpsertWithoutParentBlockInstancesInput,
+  BlockUpdateOneWithoutBlocksInput: BlockUpdateOneWithoutBlocksInput,
+  BlockUpdateWithoutBlocksDataInput: BlockUpdateWithoutBlocksDataInput,
+  BlockInstanceUpdateManyWithoutBlockInput: BlockInstanceUpdateManyWithoutBlockInput,
+  BlockInstanceUpdateWithWhereUniqueWithoutBlockInput: BlockInstanceUpdateWithWhereUniqueWithoutBlockInput,
+  BlockInstanceUpdateWithoutBlockDataInput: BlockInstanceUpdateWithoutBlockDataInput,
+  BlockInstanceUpsertWithWhereUniqueWithoutBlockInput: BlockInstanceUpsertWithWhereUniqueWithoutBlockInput,
+  BlockUpsertWithoutBlocksInput: BlockUpsertWithoutBlocksInput,
+  BlockInstanceUpsertWithWhereUniqueWithoutParentTrainingInput: BlockInstanceUpsertWithWhereUniqueWithoutParentTrainingInput,
+};
+
+export type AggregateTrainingResolvers<ContextType = any, ParentType extends ResolversParentTypes['AggregateTraining'] = ResolversParentTypes['AggregateTraining']> = {
+  count?: Resolver<ResolversTypes['Int'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type BlockResolvers<ContextType = any, ParentType extends ResolversParentTypes['Block'] = ResolversParentTypes['Block']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  title?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  description?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  videos?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>,
+  pictures?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>,
+  duration?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>,
+  format?: Resolver<ResolversTypes['Format'], ParentType, ContextType>,
+  rest?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>,
+  tracks?: Resolver<Maybe<Array<ResolversTypes['Track']>>, ParentType, ContextType, RequireFields<BlockTracksArgs, never>>,
+  blocks?: Resolver<Maybe<Array<ResolversTypes['BlockInstance']>>, ParentType, ContextType, RequireFields<BlockBlocksArgs, never>>,
+  parentBlockInstances?: Resolver<Maybe<Array<ResolversTypes['BlockInstance']>>, ParentType, ContextType, RequireFields<BlockParentBlockInstancesArgs, never>>,
+  exercises?: Resolver<Maybe<Array<ResolversTypes['ExerciseInstance']>>, ParentType, ContextType, RequireFields<BlockExercisesArgs, never>>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type BlockInstanceResolvers<ContextType = any, ParentType extends ResolversParentTypes['BlockInstance'] = ResolversParentTypes['BlockInstance']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  block?: Resolver<ResolversTypes['Block'], ParentType, ContextType>,
+  parentBlock?: Resolver<Maybe<ResolversTypes['Block']>, ParentType, ContextType>,
+  parentTraining?: Resolver<Maybe<ResolversTypes['Training']>, ParentType, ContextType>,
+  order?: Resolver<ResolversTypes['Int'], ParentType, ContextType>,
+  rounds?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>,
+  variation?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type CommentResolvers<ContextType = any, ParentType extends ResolversParentTypes['Comment'] = ResolversParentTypes['Comment']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  text?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  author?: Resolver<ResolversTypes['User'], ParentType, ContextType>,
+  createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export interface DateTimeScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['DateTime'], any> {
+  name: 'DateTime'
+}
+
+export type ExerciseResolvers<ContextType = any, ParentType extends ResolversParentTypes['Exercise'] = ResolversParentTypes['Exercise']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  name?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  description?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  videos?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>,
+  pictures?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>,
+  targets?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>,
+  baseExercise?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>,
+  parentExerciseInstances?: Resolver<Maybe<Array<ResolversTypes['ExerciseInstance']>>, ParentType, ContextType, RequireFields<ExerciseParentExerciseInstancesArgs, never>>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type ExerciseInstanceResolvers<ContextType = any, ParentType extends ResolversParentTypes['ExerciseInstance'] = ResolversParentTypes['ExerciseInstance']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  exercise?: Resolver<ResolversTypes['Exercise'], ParentType, ContextType>,
+  order?: Resolver<ResolversTypes['Int'], ParentType, ContextType>,
+  repetitions?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>,
+  variation?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  parentBlockInstances?: Resolver<ResolversTypes['Block'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type FileResolvers<ContextType = any, ParentType extends ResolversParentTypes['File'] = ResolversParentTypes['File']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  updatedAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  path?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  mimetype?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  user?: Resolver<ResolversTypes['User'], ParentType, ContextType>,
+  thumbnail?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  filename?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  encoding?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  size?: Resolver<ResolversTypes['Int'], ParentType, ContextType>,
+  comment?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type FormatResolvers<ContextType = any, ParentType extends ResolversParentTypes['Format'] = ResolversParentTypes['Format']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  name?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  description?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type FsFileResolvers<ContextType = any, ParentType extends ResolversParentTypes['FsFile'] = ResolversParentTypes['FsFile']> = {
+  filename?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  path?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  size?: Resolver<ResolversTypes['Int'], ParentType, ContextType>,
+  ctime?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  mtime?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type MutationResolvers<ContextType = any, ParentType extends ResolversParentTypes['Mutation'] = ResolversParentTypes['Mutation']> = {
+  uploadFile?: Resolver<ResolversTypes['File'], ParentType, ContextType, RequireFields<MutationUploadFileArgs, 'file'>>,
+  createUser?: Resolver<ResolversTypes['User'], ParentType, ContextType, RequireFields<MutationCreateUserArgs, 'data'>>,
+  updateUser?: Resolver<Maybe<ResolversTypes['User']>, ParentType, ContextType, RequireFields<MutationUpdateUserArgs, 'email' | 'data'>>,
+  deleteUser?: Resolver<Maybe<ResolversTypes['User']>, ParentType, ContextType, RequireFields<MutationDeleteUserArgs, 'email'>>,
+  createTraining?: Resolver<ResolversTypes['Training'], ParentType, ContextType, RequireFields<MutationCreateTrainingArgs, 'title' | 'type' | 'trainingDate' | 'location' | 'published'>>,
+  deleteTraining?: Resolver<ResolversTypes['Training'], ParentType, ContextType, RequireFields<MutationDeleteTrainingArgs, 'id'>>,
+  updateTraining?: Resolver<ResolversTypes['Training'], ParentType, ContextType, RequireFields<MutationUpdateTrainingArgs, 'where' | 'data'>>,
+  createTrainingType?: Resolver<ResolversTypes['TrainingType'], ParentType, ContextType, RequireFields<MutationCreateTrainingTypeArgs, 'name' | 'description'>>,
+  createFormat?: Resolver<ResolversTypes['Format'], ParentType, ContextType, RequireFields<MutationCreateFormatArgs, 'name' | 'description'>>,
+  userLogin?: Resolver<ResolversTypes['User'], ParentType, ContextType, RequireFields<MutationUserLoginArgs, 'email' | 'password'>>,
+  userLogout?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  userSignup?: Resolver<ResolversTypes['User'], ParentType, ContextType, RequireFields<MutationUserSignupArgs, 'name' | 'email' | 'password'>>,
+  requestReset?: Resolver<ResolversTypes['String'], ParentType, ContextType, RequireFields<MutationRequestResetArgs, 'email'>>,
+  resetPassword?: Resolver<ResolversTypes['User'], ParentType, ContextType, RequireFields<MutationResetPasswordArgs, 'token' | 'password'>>,
+  register?: Resolver<ResolversTypes['Training'], ParentType, ContextType, RequireFields<MutationRegisterArgs, 'training'>>,
+  deregister?: Resolver<ResolversTypes['Training'], ParentType, ContextType, RequireFields<MutationDeregisterArgs, 'training'>>,
+  publish?: Resolver<ResolversTypes['Training'], ParentType, ContextType, RequireFields<MutationPublishArgs, 'training'>>,
+};
+
+export type NodeResolvers<ContextType = any, ParentType extends ResolversParentTypes['Node'] = ResolversParentTypes['Node']> = {
+  __resolveType: TypeResolveFn<'TrainingType' | 'Training' | 'User' | 'Comment' | 'Rating' | 'BlockInstance' | 'Block' | 'Format' | 'Track' | 'ExerciseInstance' | 'Exercise' | 'File', ParentType, ContextType>,
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+};
+
+export type PageInfoResolvers<ContextType = any, ParentType extends ResolversParentTypes['PageInfo'] = ResolversParentTypes['PageInfo']> = {
+  hasNextPage?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>,
+  hasPreviousPage?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>,
+  startCursor?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  endCursor?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type QueryResolvers<ContextType = any, ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query']> = {
+  trainingArchive?: Resolver<ResolversTypes['TrainingArchive'], ParentType, ContextType, RequireFields<QueryTrainingArchiveArgs, never>>,
+  publishedTrainings?: Resolver<Array<ResolversTypes['Training']>, ParentType, ContextType, RequireFields<QueryPublishedTrainingsArgs, never>>,
+  training?: Resolver<ResolversTypes['Training'], ParentType, ContextType, RequireFields<QueryTrainingArgs, never>>,
+  trainings?: Resolver<Array<ResolversTypes['Training']>, ParentType, ContextType, RequireFields<QueryTrainingsArgs, never>>,
+  trainingsCount?: Resolver<ResolversTypes['TrainingConnection'], ParentType, ContextType, RequireFields<QueryTrainingsCountArgs, never>>,
+  fsFiles?: Resolver<Array<ResolversTypes['FsFile']>, ParentType, ContextType, RequireFields<QueryFsFilesArgs, 'directory'>>,
+  files?: Resolver<Array<ResolversTypes['File']>, ParentType, ContextType>,
+  currentUser?: Resolver<ResolversTypes['User'], ParentType, ContextType>,
+  user?: Resolver<Maybe<ResolversTypes['User']>, ParentType, ContextType, RequireFields<QueryUserArgs, 'where'>>,
+  users?: Resolver<Array<ResolversTypes['User']>, ParentType, ContextType, RequireFields<QueryUsersArgs, never>>,
+  trainingType?: Resolver<Maybe<ResolversTypes['TrainingType']>, ParentType, ContextType, RequireFields<QueryTrainingTypeArgs, 'where'>>,
+  trainingTypes?: Resolver<Array<ResolversTypes['TrainingType']>, ParentType, ContextType, RequireFields<QueryTrainingTypesArgs, never>>,
+  block?: Resolver<Maybe<ResolversTypes['Block']>, ParentType, ContextType, RequireFields<QueryBlockArgs, 'where'>>,
+  blocks?: Resolver<Array<ResolversTypes['Block']>, ParentType, ContextType, RequireFields<QueryBlocksArgs, never>>,
+  format?: Resolver<Maybe<ResolversTypes['Format']>, ParentType, ContextType, RequireFields<QueryFormatArgs, 'where'>>,
+  formats?: Resolver<Array<ResolversTypes['Format']>, ParentType, ContextType, RequireFields<QueryFormatsArgs, never>>,
+  exercise?: Resolver<Maybe<ResolversTypes['Exercise']>, ParentType, ContextType, RequireFields<QueryExerciseArgs, 'where'>>,
+  exercises?: Resolver<Array<ResolversTypes['Exercise']>, ParentType, ContextType, RequireFields<QueryExercisesArgs, never>>,
+};
+
+export type RatingResolvers<ContextType = any, ParentType extends ResolversParentTypes['Rating'] = ResolversParentTypes['Rating']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  user?: Resolver<ResolversTypes['User'], ParentType, ContextType>,
+  value?: Resolver<ResolversTypes['Int'], ParentType, ContextType>,
+  comment?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type TrackResolvers<ContextType = any, ParentType extends ResolversParentTypes['Track'] = ResolversParentTypes['Track']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  title?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  artist?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  duration?: Resolver<ResolversTypes['Int'], ParentType, ContextType>,
+  link?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type TrainingResolvers<ContextType = any, ParentType extends ResolversParentTypes['Training'] = ResolversParentTypes['Training']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  title?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  type?: Resolver<ResolversTypes['TrainingType'], ParentType, ContextType>,
+  createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  trainingDate?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  location?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  registrations?: Resolver<Maybe<Array<ResolversTypes['User']>>, ParentType, ContextType, RequireFields<TrainingRegistrationsArgs, never>>,
+  attendance?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>,
+  ratings?: Resolver<Maybe<Array<ResolversTypes['Rating']>>, ParentType, ContextType, RequireFields<TrainingRatingsArgs, never>>,
+  published?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>,
+  blocks?: Resolver<Maybe<Array<ResolversTypes['BlockInstance']>>, ParentType, ContextType, RequireFields<TrainingBlocksArgs, never>>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type TrainingArchiveResolvers<ContextType = any, ParentType extends ResolversParentTypes['TrainingArchive'] = ResolversParentTypes['TrainingArchive']> = {
+  trainings?: Resolver<Array<ResolversTypes['TrainingArchiveItem']>, ParentType, ContextType>,
+  totalCount?: Resolver<ResolversTypes['Int'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type TrainingArchiveItemResolvers<ContextType = any, ParentType extends ResolversParentTypes['TrainingArchiveItem'] = ResolversParentTypes['TrainingArchiveItem']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  title?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  type?: Resolver<ResolversTypes['TrainingType'], ParentType, ContextType>,
+  trainingDate?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  location?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  attendance?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>,
+  ratings?: Resolver<Maybe<ResolversTypes['Float']>, ParentType, ContextType>,
+  blocks?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>,
+  duration?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type TrainingConnectionResolvers<ContextType = any, ParentType extends ResolversParentTypes['TrainingConnection'] = ResolversParentTypes['TrainingConnection']> = {
+  pageInfo?: Resolver<ResolversTypes['PageInfo'], ParentType, ContextType>,
+  edges?: Resolver<Array<Maybe<ResolversTypes['TrainingEdge']>>, ParentType, ContextType>,
+  aggregate?: Resolver<ResolversTypes['AggregateTraining'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type TrainingEdgeResolvers<ContextType = any, ParentType extends ResolversParentTypes['TrainingEdge'] = ResolversParentTypes['TrainingEdge']> = {
+  node?: Resolver<ResolversTypes['Training'], ParentType, ContextType>,
+  cursor?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type TrainingTypeResolvers<ContextType = any, ParentType extends ResolversParentTypes['TrainingType'] = ResolversParentTypes['TrainingType']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  name?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  description?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export interface UploadScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['Upload'], any> {
+  name: 'Upload'
+}
+
+export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
+  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>,
+  email?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  name?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  password?: Resolver<ResolversTypes['String'], ParentType, ContextType>,
+  resetToken?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
+  resetTokenExpiry?: Resolver<Maybe<ResolversTypes['Float']>, ParentType, ContextType>,
+  createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>,
+  comments?: Resolver<Maybe<Array<ResolversTypes['Comment']>>, ParentType, ContextType, RequireFields<UserCommentsArgs, never>>,
+  ratings?: Resolver<Maybe<Array<ResolversTypes['Rating']>>, ParentType, ContextType, RequireFields<UserRatingsArgs, never>>,
+  permissions?: Resolver<Array<ResolversTypes['Permission']>, ParentType, ContextType>,
+  interests?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>,
+  __isTypeOf?: isTypeOfResolverFn<ParentType>,
+};
+
+export type Resolvers<ContextType = any> = {
+  AggregateTraining?: AggregateTrainingResolvers<ContextType>,
+  Block?: BlockResolvers<ContextType>,
+  BlockInstance?: BlockInstanceResolvers<ContextType>,
+  Comment?: CommentResolvers<ContextType>,
+  DateTime?: GraphQLScalarType,
+  Exercise?: ExerciseResolvers<ContextType>,
+  ExerciseInstance?: ExerciseInstanceResolvers<ContextType>,
+  File?: FileResolvers<ContextType>,
+  Format?: FormatResolvers<ContextType>,
+  FsFile?: FsFileResolvers<ContextType>,
+  Mutation?: MutationResolvers<ContextType>,
+  Node?: NodeResolvers,
+  PageInfo?: PageInfoResolvers<ContextType>,
+  Query?: QueryResolvers<ContextType>,
+  Rating?: RatingResolvers<ContextType>,
+  Track?: TrackResolvers<ContextType>,
+  Training?: TrainingResolvers<ContextType>,
+  TrainingArchive?: TrainingArchiveResolvers<ContextType>,
+  TrainingArchiveItem?: TrainingArchiveItemResolvers<ContextType>,
+  TrainingConnection?: TrainingConnectionResolvers<ContextType>,
+  TrainingEdge?: TrainingEdgeResolvers<ContextType>,
+  TrainingType?: TrainingTypeResolvers<ContextType>,
+  Upload?: GraphQLScalarType,
+  User?: UserResolvers<ContextType>,
+};
+
+
+/**
+ * @deprecated
+ * Use "Resolvers" root object instead. If you wish to get "IResolvers", add "typesPrefix: I" to your config.
+*/
+export type IResolvers<ContextType = any> = Resolvers<ContextType>;

+ 7 - 13
backend/index.ts → backend/src/index.ts

@@ -5,20 +5,14 @@ import cookieParser from 'cookie-parser'
 import { ApolloServer, ApolloServerExpressConfig } from 'apollo-server-express'
 import { merge } from 'lodash'
 import { importSchema } from 'graphql-import'
-import { db, populateUser } from './src/db'
-import { authenticate } from './src/user/authenticate'
-import file from './src/file'
-import user from './src/user'
-import history from './src/history'
-import training from './src/training'
+import { db, populateUser } from './db'
+import { authenticate } from './user/authenticate'
+import file from './file'
+import user from './user'
+import history from './history'
+import training from './training'
 
-const resolvers = merge(
-  file.resolvers,
-  training.resolvers,
-  user.resolvers,
-  history.resolvers
-  //google.resolvers
-)
+const resolvers = merge(file.resolvers, training.resolvers, user.resolvers, history.resolvers)
 
 const typeDefs = importSchema('./schema.graphql').replace('scalar Upload', '')
 // scalar Upload has to be in schema, or importSchema will complain.

+ 140 - 96
backend/src/training/resolvers.ts

@@ -1,113 +1,157 @@
 // const { transport, emailTemplate } = require('./mail')
-
-import { IResolvers } from 'apollo-server-express'
+import { QueryResolvers, MutationResolvers, Resolvers } from '../gql/resolvers'
 import { checkPermission } from '../user/resolvers'
-//const LoginError = new Error('You must be logged in.')
-//const PermissionError = new Error('Insufficient permissions.')
 
-export const resolvers: IResolvers = {
-  Query: {
-    publishedTrainings: async (parent, args, context, info) => {
-      checkPermission(context)
-      return context.db.query.trainings(
+const Query: QueryResolvers = {
+  trainingArchive: async (parent, { first = 4, skip = 0 }, context, info) => {
+    const filter = { published: true }
+    const trainings = await context.db.query.trainings(
+      { where: filter, orderBy: 'trainingDate_DESC', skip, first },
+      '{ id }'
+    )
+    const trainingsConnection = await context.db.query.trainingsConnection(
+      { where: filter },
+      '{ aggregate { count } }'
+    )
+    console.log(first, skip, trainings, trainingsConnection)
+    return {
+      totalCount: trainingsConnection.aggregate.count,
+      trainings: trainings.map((training: any) => training.id),
+    }
+  },
+  publishedTrainings: async (parent, args, context, info) => {
+    checkPermission(context)
+    return context.db.query.trainings(
+      {
+        where: { published: true },
+        orderBy: 'trainingDate_DESC',
+        first: 10,
+        ...args,
+      },
+      info
+    )
+  },
+  training: async (parent, args, context, info) => {
+    checkPermission(context)
+    if (args && args.id) {
+      console.log('?', args)
+      return context.db.query.training({ where: args }, info)
+    } else {
+      const trainingsArray = await context.db.query.trainings(
         {
           where: { published: true },
           orderBy: 'trainingDate_DESC',
-          first: 10,
-          ...args,
+          first: 1,
         },
         info
       )
-    },
-    training: async (parent, args, context, info) => {
-      checkPermission(context)
-      if (args && args.id) {
-        console.log('?', args)
-        return context.db.query.training({ where: args }, info)
-      } else {
-        const trainingsArray = await context.db.query.trainings(
-          {
-            where: { published: true },
-            orderBy: 'trainingDate_DESC',
-            first: 1,
-          },
-          info
-        )
-        console.log(trainingsArray)
-        if (trainingsArray && trainingsArray.length > 0) return trainingsArray[0]
-      }
-    },
-    trainings: async (parent, args, context, info) => {
-      checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
-      return context.db.query.trainings(args, info)
-    },
-    trainingsCount: async (parent, args, context, info) => {
-      checkPermission(context)
-      return await context.db.query.trainingsConnection(args, '{ aggregate { count } }')
-    },
-    trainingTypes: async (parent, args, context, info) => {
-      checkPermission(context)
-      return context.db.query.trainingTypes({}, info)
-    },
-    blocks: async (parent, args, context, info) => {
-      checkPermission(context)
-      return context.db.query.blocks({}, info)
-    },
-    formats: async (parent, args, context, info) => {
-      checkPermission(context)
-      return context.db.query.formats({}, info)
-    },
-    exercises: async (parent, args, context, info) => {
-      checkPermission(context)
-      return context.db.query.exercises({}, info)
-    },
+      console.log(trainingsArray)
+      if (trainingsArray && trainingsArray.length > 0) return trainingsArray[0]
+    }
+  },
+  trainings: async (parent, args, context, info) => {
+    checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
+    return context.db.query.trainings(args, info)
+  },
+  trainingsCount: async (parent, args, context, info) => {
+    checkPermission(context)
+    return await context.db.query.trainingsConnection(args, '{ aggregate { count } }')
+  },
+  trainingTypes: async (parent, args, context, info) => {
+    checkPermission(context)
+    return context.db.query.trainingTypes({}, info)
+  },
+  blocks: async (parent, args, context, info) => {
+    checkPermission(context)
+    return context.db.query.blocks({}, info)
   },
+  formats: async (parent, args, context, info) => {
+    checkPermission(context)
+    return context.db.query.formats({}, info)
+  },
+  exercises: async (parent, args, context, info) => {
+    checkPermission(context)
+    return context.db.query.exercises({}, info)
+  },
+}
 
-  Mutation: {
-    createTraining: async (parent, args, context, info) => {
-      checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
-      const training = await context.db.mutation.createTraining({ data: args }, info)
-      return training
-    },
-    updateTraining: async (parent, args, context, info) => {
-      checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
-      const training = await context.db.mutation.updateTraining(args, info)
-      return training
-    },
-    createTrainingType: async (parent, args, context, info) => {
-      checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
-      const trainingType = await context.db.mutation.createTrainingType({ data: args }, info)
-      return trainingType
-    },
-    // createBlock: async (parent, args, context, info) => {
-    //   checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
-    //   const block = await context.db.mutation.createBlock({ data: args }, info)
-    //   return block
-    // },
-    createFormat: (parent, args, context, info) => {
-      checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
-      return context.db.mutation.createFormat({ data: args }, info)
-    },
-    register: (parent, args, context, info) => {
-      checkPermission(context)
-      return context.db.mutation.updateTraining({
-        where: { id: args.training },
-        data: { registrations: { connect: { id: context.req.userId } } },
+const Mutation: MutationResolvers = {
+  createTraining: async (parent, args, context, info) => {
+    checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
+    const training = await context.db.mutation.createTraining({ data: args }, info)
+    return training
+  },
+  updateTraining: async (parent, args, context, info) => {
+    checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
+    const training = await context.db.mutation.updateTraining(args, info)
+    return training
+  },
+  deleteTraining: (parent, args, context, info) => {
+    checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
+    return context.db.mutation.deleteTraining({ where: { id: args.id } })
+  },
+  createTrainingType: (parent, args, context, info) => {
+    checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
+    return context.db.mutation.createTrainingType({ data: args }, info)
+  },
+  // createBlock: async (parent, args, context, info) => {
+  //   checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
+  //   const block = await context.db.mutation.createBlock({ data: args }, info)
+  //   return block
+  // },
+  createFormat: (parent, args, context, info) => {
+    checkPermission(context, ['INSTRUCTOR', 'ADMIN'])
+    return context.db.mutation.createFormat({ data: args }, info)
+  },
+  register: (parent, args, context, info) => {
+    checkPermission(context)
+    return context.db.mutation.updateTraining({
+      where: { id: args.training },
+      data: { registrations: { connect: { id: context.req.userId } } },
+    })
+  },
+  deregister: (parent, args, context, info) => {
+    checkPermission(context)
+    return context.db.mutation.updateTraining({
+      where: { id: args.training },
+      data: { registrations: { disconnect: { id: context.req.userId } } },
+    })
+  },
+  publish: (parent, args, context, info) => {
+    checkPermission(context, ['INSTRUCTOR'])
+    return context.db.mutation.updateTraining({
+      where: { id: args.training },
+      data: { published: !!args.status },
+    })
+  },
+}
+
+export const resolvers: Resolvers = {
+  Query,
+  Mutation,
+  TrainingArchive: {
+    trainings: async ({ trainings }, args, context, info) => {
+      const trainingDetails = await context.db.query.trainings(
+        { where: { id_in: trainings } },
+        info
+      )
+      return trainingDetails.map((trainingDetail: any, index: number) => {
+        return { ...trainingDetail, __extras__: trainings[index] }
       })
     },
-    deregister: (parent, args, context, info) => {
-      checkPermission(context)
-      return context.db.mutation.updateTraining({
-        where: { id: args.training },
-        data: { registrations: { disconnect: { id: context.req.userId } } },
-      })
+  },
+  TrainingArchiveItem: {
+    duration: (parent, args, context, info) => {
+      return 2
     },
-    publish: (parent, args, context, info) => {
-      checkPermission(context, ['INSTRUCTOR'])
-      return context.db.mutation.updateTraining({
-        where: { id: args.training },
-        data: { published: args.status },
-      })
+    blocks: async ({ __extras__ }: any, args, context, info) => {
+      console.log(__extras__, args)
+      const blockInstances = await context.db.query.blockInstances(
+        { where: { parentTraining: { id: __extras__ } } },
+        '{ block { title } }'
+      )
+      console.log(blockInstances)
+      return blockInstances.map((blockInstance: any) => blockInstance.block.title)
     },
   },
 }

+ 1 - 0
backend/src/user/resolvers.ts

@@ -166,6 +166,7 @@ export const resolvers: IResolvers = {
  * @param permission - String or list of strings with required permissions
  */
 export function checkPermission(context: any, permission?: string | string[]) {
+  console.log(context.req.userId)
   if (!context.req.userId) throw new Error('Login required.')
   if (typeof permission === 'string') {
     if (!context.req.user.permissions.includes(permission))

+ 3 - 7
backend/tsconfig.json

@@ -16,12 +16,8 @@
     "noImplicitReturns": true,
     "noUnusedLocals": true,
     "noFallthroughCasesInSwitch": true,
-    "esModuleInterop": true,
-    "baseUrl": ".",
-    "paths": {
-      "*": ["node_modules/*", "src/*"]
-    }
+    "esModuleInterop": true
   },
-  "exclude": ["node_modules", "dist"],
-  "include": ["*.ts", "**/*.ts"]
+  "exclude": ["./node_modules", "./dist"],
+  "include": ["./src/*.ts", "./src/**/*.ts"]
 }

+ 8 - 0
codegen.yml

@@ -18,3 +18,11 @@ generates:
       - 'typescript'
       - 'typescript-operations'
       - 'typescript-react-apollo'
+
+  backend/src/gql/resolvers.ts:
+    config:
+      - defaultMapper: Partial<{T}>
+      - useIndexSignature: true
+    plugins:
+      - typescript
+      - typescript-resolvers

+ 2 - 0
docker-compose.yml

@@ -22,6 +22,7 @@ services:
     volumes:
       - './backend:/app'
       - 'backend-nm:/app/node_modules'
+      - './upload_files:/app/upload_files'
     environment:
       - NODE_ENV=development
       - PRISMA_MANAGEMENT_API_SECRET=PrismaSecret
@@ -62,6 +63,7 @@ services:
       - '8820:8820'
     volumes:
       - './proxy/nginx.conf:/etc/nginx/nginx.conf:ro'
+      - './upload_files:/www/upload_files'
 
 volumes:
   frontend-nm:

+ 62 - 0
frontend/package-lock.json

@@ -5021,6 +5021,27 @@
       "integrity": "sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA==",
       "dev": true
     },
+    "@types/apollo-upload-client": {
+      "version": "8.1.3",
+      "resolved": "https://registry.npmjs.org/@types/apollo-upload-client/-/apollo-upload-client-8.1.3.tgz",
+      "integrity": "sha512-E0bmMnkXBIiHY5Tl+U1Yum70loe93AOV7K+/3E/oGcdpH4izX4owwu+Cz1hRDkkYacHahKJCHz0xSLiL/ENRmA==",
+      "requires": {
+        "@types/extract-files": "*",
+        "apollo-link": "^1.2.12",
+        "apollo-link-http-common": "^0.2.4",
+        "graphql": "^14.5.3"
+      },
+      "dependencies": {
+        "graphql": {
+          "version": "14.6.0",
+          "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.6.0.tgz",
+          "integrity": "sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg==",
+          "requires": {
+            "iterall": "^1.2.2"
+          }
+        }
+      }
+    },
     "@types/babel__core": {
       "version": "7.1.7",
       "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.7.tgz",
@@ -5086,6 +5107,11 @@
         "@types/react": "*"
       }
     },
+    "@types/extract-files": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@types/extract-files/-/extract-files-3.1.0.tgz",
+      "integrity": "sha512-tLNI7qpktX1NYqE4yXSp9sHgBJOH4kO03WAgeZYDC+xhi005ZDEHkHVdy+/zoNEHasu5kJIU0yqECgT7xxANdg=="
+    },
     "@types/howler": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/@types/howler/-/howler-2.1.2.tgz",
@@ -5851,6 +5877,32 @@
         "tslib": "^1.9.3"
       }
     },
+    "apollo-upload-client": {
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-13.0.0.tgz",
+      "integrity": "sha512-lJ9/bk1BH1lD15WhWRha2J3+LrXrPIX5LP5EwiOUHv8PCORp4EUrcujrA3rI5hZeZygrTX8bshcuMdpqpSrvtA==",
+      "requires": {
+        "@babel/runtime": "^7.9.2",
+        "apollo-link": "^1.2.12",
+        "apollo-link-http-common": "^0.2.14",
+        "extract-files": "^8.0.0"
+      },
+      "dependencies": {
+        "@babel/runtime": {
+          "version": "7.9.2",
+          "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
+          "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
+          "requires": {
+            "regenerator-runtime": "^0.13.4"
+          }
+        },
+        "regenerator-runtime": {
+          "version": "0.13.5",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+          "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
+        }
+      }
+    },
     "apollo-utilities": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.3.tgz",
@@ -8683,6 +8735,11 @@
         }
       }
     },
+    "extract-files": {
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-8.1.0.tgz",
+      "integrity": "sha512-PTGtfthZK79WUMk+avLmwx3NGdU8+iVFXC2NMGxKsn0MnihOG2lvumj+AZo8CTwTrwjXDgZ5tztbRlEdRjBonQ=="
+    },
     "extsprintf": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -10574,6 +10631,11 @@
         "istanbul-lib-report": "^3.0.0"
       }
     },
+    "iterall": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz",
+      "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg=="
+    },
     "jest": {
       "version": "25.3.0",
       "resolved": "https://registry.npmjs.org/jest/-/jest-25.3.0.tgz",

+ 2 - 0
frontend/package.json

@@ -17,6 +17,7 @@
     "@fortawesome/fontawesome-svg-core": "^1.2.28",
     "@fortawesome/free-solid-svg-icons": "^5.13.0",
     "@fortawesome/react-fontawesome": "^0.1.9",
+    "@types/apollo-upload-client": "^8.1.3",
     "@types/howler": "^2.1.2",
     "@types/lodash": "^4.14.149",
     "@types/react-onclickoutside": "^6.7.3",
@@ -25,6 +26,7 @@
     "apollo-boost": "0.4.7",
     "apollo-link": "^1.2.14",
     "apollo-link-error": "^1.1.13",
+    "apollo-upload-client": "^13.0.0",
     "array-move": "^2.2.1",
     "date-fns": "^2.12.0",
     "dotenv": "^8.2.0",

+ 0 - 0
frontend/pages/admin/block/[id].tsx


+ 25 - 0
frontend/pages/admin/block/index.tsx

@@ -0,0 +1,25 @@
+import { useBlocksQuery } from '../../../src/gql'
+import { FunctionComponent } from 'react'
+import { TBlock } from '../../../src/training/types'
+import { AdminList } from '../../../src/app'
+
+const AdminBlock: FunctionComponent<{ item: TBlock }> = ({ item }) => {
+  return (
+    <div>
+      {item.id} {item.title}
+    </div>
+  )
+}
+
+const AdminBlocks = () => {
+  const props = {
+    name: 'Blocks',
+    adminMenu: '/admin/block',
+    get: useBlocksQuery(),
+    dataKey: 'blocks',
+    Component: AdminBlock,
+  }
+  return <AdminList {...props} />
+}
+
+export default AdminBlocks

+ 0 - 0
frontend/pages/admin/exercise/[id].tsx


+ 25 - 0
frontend/pages/admin/exercise/index.tsx

@@ -0,0 +1,25 @@
+import { useExercisesQuery } from '../../../src/gql'
+import { FunctionComponent } from 'react'
+import { TExercise } from '../../../src/training/types'
+import { AdminList } from '../../../src/app'
+
+const AdminExercise: FunctionComponent<{ item: TExercise }> = ({ item }) => {
+  return (
+    <div>
+      {item.id} {item.name}
+    </div>
+  )
+}
+
+const AdminExercises = () => {
+  const props = {
+    name: 'Exercises',
+    adminMenu: '/admin/exercise',
+    get: useExercisesQuery(),
+    dataKey: 'exercises',
+    Component: AdminExercise,
+  }
+  return <AdminList {...props} />
+}
+
+export default AdminExercises

+ 0 - 0
frontend/pages/admin/file/[id].tsx


+ 12 - 0
frontend/pages/admin/file/index.tsx

@@ -0,0 +1,12 @@
+import { UploadFile } from '../../../src/file'
+import { AdminPage } from '../../../src/app'
+
+const Files = () => {
+  return (
+    <AdminPage>
+      <UploadFile />
+    </AdminPage>
+  )
+}
+
+export default Files

+ 74 - 37
frontend/pages/admin/training/index.tsx

@@ -1,44 +1,81 @@
-import Link from 'next/link'
-import { useTrainingsQuery } from '../../../src/gql'
-import { AdminPage } from '../../../src/app'
+import {
+  useTrainingsQuery,
+  useDeleteTrainingMutation,
+  TrainingsDocument,
+  usePublishMutation,
+  PublishDocument,
+} from '../../../src/gql'
+import { FunctionComponent } from 'react'
+import { TTraining } from '../../../src/training/types'
+import { AdminList } from '../../../src/app'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons'
+import theme from '../../../src/styles/theme'
 
-const TrainingsList = () => {
-  const { data, error, loading } = useTrainingsQuery()
+const AdminTraining: FunctionComponent<{ item: TTraining; className?: string }> = ({
+  item,
+  className,
+}) => {
+  const [publish, publishResult] = usePublishMutation({
+    refetchQueries: [{ query: TrainingsDocument }],
+  })
 
   return (
-    <AdminPage>
-      <section>
-        {error && <p>Error loading trainings...</p>}
-        {loading && <p>Loading data...</p>}
-        {data && data.trainings.length > 0 ? (
-          <ul>
-            {data?.trainings.map((training) => (
-              <li key={training.id}>
-                <button type='button'>Delete</button>
-                <Link href='training/[id]' as={`training/${training.id}`}>
-                  <a>{training.title}</a>
-                </Link>
-              </li>
-            ))}
-          </ul>
-        ) : (
-          <p>No trainings found.</p>
-        )}
-        <Link href='training/create'>
-          <a>Create training</a>
-        </Link>
-
-        <style jsx>{`
-          li {
-            list-style: none;
-          }
-          ul {
-            padding: 0;
+    <div className={className}>
+      <div>
+        <button
+          type='button'
+          title='publish'
+          onClick={(event) =>
+            publish({ variables: { training: item.id, status: !item.published } })
           }
-        `}</style>
-      </section>
-    </AdminPage>
+        >
+          <FontAwesomeIcon icon={item.published ? faEye : faEyeSlash} height={16} />
+        </button>
+      </div>
+      <div className='admin-training-title'>{item.title}</div>{' '}
+      <div className='admin-training-blocks'>
+        {item.blocks?.map((block) => block.block.title).join(' ')}
+      </div>
+      <div className='admin-training-date'>{new Date(item.trainingDate).toLocaleString()}</div>
+      <style jsx>{`
+        .${className} {
+          display: flex;
+        }
+        .admin-training-title {
+          width: 15%;
+        }
+        .admin-training-blocks {
+          width: 65%;
+        }
+        .admin-training-date {
+          width: 20%;
+          text-align: right;
+        }
+        button {
+          margin: 0 0.4em;
+          padding: 0;
+          color: ${theme.colors.buttonBackground};
+          background-color: transparent;
+        }
+      `}</style>
+    </div>
   )
 }
 
-export default TrainingsList
+const AdminTrainings = () => {
+  const props = {
+    name: 'Trainings',
+    adminMenu: '/admin/training',
+    get: useTrainingsQuery(),
+    remove: useDeleteTrainingMutation({
+      refetchQueries: [{ query: TrainingsDocument }],
+      update: (args) => console.log(args),
+    }),
+    dataKey: 'trainings',
+    Component: AdminTraining,
+  }
+  return <AdminList {...props} />
+}
+
+export default AdminTrainings

+ 7 - 8
frontend/pages/index.tsx

@@ -60,17 +60,17 @@ const Home = () => {
           @media (min-width: ${theme.midsize}) {
             .next-training {
               display: grid;
-              grid-template-columns: 1fr auto;
               grid-template-areas:
-                'title    info'
+                'title    info   '
                 'program  program'
                 'archive  archive';
+              grid-template-columns: 1fr auto;
               column-gap: 1em;
             }
             .training-title {
             grid-area: title;
             }
-            :global(.training-meta) {
+            :global(.training-meta-wrap) {
               grid-area: info;
             }
             :global(.training-program) {
@@ -83,12 +83,11 @@ const Home = () => {
           @media (min-width: ${theme.fullsize}) {
             .next-training {
               padding: 3em 3em;
-              grid-template-columns: 2fr 1fr;
-              grid-template-rows: auto 1fr auto;
               grid-template-areas:
-                'title    program'
-                'info     program'
-                'archive  program';
+                'free1  title    program  free2'
+                'free1  info     program  free2'
+                'free1  archive  archive  free2';
+              grid-template-columns: minmax(0, 1fr) minmax(550px, 4fr) minmax(300px, 2fr) minmax(0, 1fr);
               column-gap: 2em;
               background-image: linear-gradient(
                 to bottom,

+ 127 - 0
frontend/src/app/components/AdminList.tsx

@@ -0,0 +1,127 @@
+import { FunctionComponent } from 'react'
+import AdminPage from './AdminPage'
+import Link from 'next/link'
+import theme from '../../styles/theme'
+import { QueryResult, MutationTuple } from '@apollo/client'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faEdit, faTrash, faEye, faPlusCircle } from '@fortawesome/free-solid-svg-icons'
+
+interface IAdminList {
+  name: string
+  adminMenu?: string
+  dataKey: string
+  get: QueryResult<any>
+  remove?: MutationTuple<any, any>
+  Component: FunctionComponent<any>
+}
+
+const AdminList = ({ name, adminMenu, dataKey, get, remove, Component }: IAdminList) => {
+  const [removeFunction, removeResult] = remove ?? [undefined, undefined]
+
+  let content
+  if (get.loading) content = <p>Loading data...</p>
+  else if (get.error) content = <p>Error loading data.</p>
+  else if (!get.data) content = <p>No data found.</p>
+  else
+    content = (
+      <ul>
+        {get.data[dataKey].map((item: any) => (
+          <li key={item.id}>
+            <Component key={item.id} item={item} className='admin-component' />
+
+            <div className='admin-toolbar'>
+              <Link href={`/${adminMenu}/[id]`} as={`${adminMenu}/${item.id}`}>
+                <a title='edit'>
+                  <button type='button'>
+                    <FontAwesomeIcon icon={faEdit} height={16} />
+                  </button>
+                </a>
+              </Link>
+              {removeFunction && removeResult && (
+                <button
+                  onClick={(event) => {
+                    removeFunction()
+                  }}
+                  disabled={removeResult.loading}
+                  title='delete'
+                >
+                  <FontAwesomeIcon icon={faTrash} height={16} />
+                </button>
+              )}
+            </div>
+          </li>
+        ))}
+        <style jsx>{`
+          ul {
+            padding: 0;
+          }
+          ul :global(li) {
+            padding: 0.2em 0.5em;
+            display: flex;
+            list-style: none;
+            align-items: center;
+            background-color: #0770;
+            transition: background-color 250ms ease-in-out;
+            border-top: 1px solid #0002;
+            position: relative;
+          }
+          ul :global(li:last-child) {
+            border-bottom: 1px solid #0002;
+          }
+          ul :global(li:hover) {
+            background-color: ${theme.colors.formHighlightBackground}44;
+          }
+          ul :global(.admin-component) {
+            flex-grow: 1;
+          }
+          ul :global(.admin-toolbar button) {
+            padding: 0.4em;
+            margin: 0;
+            color: ${theme.colors.buttonBackground};
+            background-color: transparent;
+          }
+
+          ul :global(a) {
+            color: ${theme.colors.button};
+            text-decoration: none;
+          }
+          ul :global(li .admin-toolbar) {
+            display: none;
+            position: absolute;
+            top: 0;
+            right: 0;
+            width: 80px;
+            background-color: ${theme.colors.background};
+          }
+          ul :global(li:hover .admin-toolbar) {
+            display: flex;
+          }
+        `}</style>
+      </ul>
+    )
+
+  return (
+    <AdminPage>
+      <h2>{name}</h2>
+      <Link href={`${adminMenu}/create`}>
+        <a>
+          <button>
+            <FontAwesomeIcon icon={faPlusCircle} height={36} />
+          </button>
+        </a>
+      </Link>
+      {content}
+      <style jsx>{`
+        button {
+          color: ${theme.colors.buttonBackground};
+          background-color: transparent;
+          display: inline;
+          margin: 0.4rem;
+          padding: 0;
+        }
+      `}</style>
+    </AdminPage>
+  )
+}
+
+export default AdminList

+ 17 - 2
frontend/src/app/components/AdminSideBar.tsx

@@ -11,6 +11,21 @@ const AdminSideBar = () => {
             <li className='admin-item'>Trainings</li>
           </a>
         </Link>
+        <Link href='/admin/block'>
+          <a>
+            <li className='admin-item'>Blocks</li>
+          </a>
+        </Link>
+        <Link href='/admin/exercise'>
+          <a>
+            <li className='admin-item'>Exercises</li>
+          </a>
+        </Link>
+        <Link href='/admin/file'>
+          <a>
+            <li className='admin-item'>Files</li>
+          </a>
+        </Link>
         <Link href='/admin/user'>
           <a>
             <li className='admin-item'>Users</li>
@@ -22,8 +37,8 @@ const AdminSideBar = () => {
         nav {
           margin: 0;
           padding: 0;
-          color: ${theme.colors.mobileNav};
-          background-color: ${theme.colors.mobileNavBackground};
+          color: ${theme.colors.presentation};
+          background-color: ${theme.colors.presentationBackground};
           min-height: 100%;
         }
         nav h1,

+ 1 - 1
frontend/src/app/components/Logo.tsx

@@ -37,7 +37,7 @@ const Logo = () => (
           height: 0.2em;
           border-radius: 50%;
           background-color: white;
-          right: 40%;
+          right: 50%;
           bottom: 55%;
         }
 

+ 18 - 1
frontend/src/app/components/Nav.tsx

@@ -12,7 +12,6 @@ const Nav = () => {
   const [menu, setMenu] = useState(false)
   const ref = useRef<HTMLDivElement>(null)
   useOnClickOutside(ref, () => {
-    console.log('outside checkbox', menu)
     setMenu(false)
   })
 
@@ -85,6 +84,23 @@ const Nav = () => {
           text-transform: uppercase;
         }
 
+        nav :global(form input),
+        nav :global(form select),
+        nav :global(form text) {
+          border: 2px solid ${theme.colors.white}00;
+          color: ${theme.colors.white};
+          background-color: ${theme.colors.white}22;
+          transition: all 250ms ease-in-out;
+        }
+
+        nav :global(form input:focus),
+        nav :global(form select:focus),
+        nav :global(form text:focus) {
+          color: ${theme.colors.black};
+          background-color: ${theme.colors.white}bb;
+          border-bottom: 2px solid ${theme.colors.white}22;
+        }
+
         .nav-toggle {
           display: none;
         }
@@ -151,6 +167,7 @@ const Nav = () => {
           }
           nav {
             all: unset;
+            height: 100%;
             display: flex;
             position: relative;
             align-items: center;

+ 10 - 1
frontend/src/app/components/Search.tsx

@@ -27,13 +27,15 @@ const Search = () => {
 
         {menu ? (
           <section className='searchmenu'>
-            <input type='search' />
+            <input type='search' placeholder='Search text' />
           </section>
         ) : null}
       </li>
 
       <style jsx>{`
         .searchmenu {
+          position: absolute;
+          padding: 1em 0.3em;
           right: 0;
           top: 100%;
 
@@ -44,6 +46,13 @@ const Search = () => {
         .searchmenu :global(a) {
           color: ${theme.colors.mobileNav};
         }
+
+        @media (min-width: ${theme.fullsize}) {
+          .searchmenu {
+            width: 100%;
+            padding: 1em;
+          }
+        }
       `}</style>
     </>
   )

+ 2 - 1
frontend/src/app/index.tsx

@@ -1,8 +1,9 @@
 import AdminPage from './components/AdminPage'
+import AdminList from './components/AdminList'
 import Page from './components/Page'
 import Header from './components/Header'
 import Footer from './components/Footer'
 import Meta from './components/Meta'
 import Nav from './components/Nav'
 
-export { Page, AdminPage, Header, Footer, Meta, Nav }
+export { Page, AdminPage, AdminList, Header, Footer, Meta, Nav }

+ 113 - 0
frontend/src/file/components/UploadFile.tsx

@@ -0,0 +1,113 @@
+import { useState, ChangeEvent } from 'react'
+
+import { useUploadFileMutation, useFsFilesQuery, useFilesQuery } from '../../gql'
+import { danglingFsFiles } from '../utils'
+
+interface IForm {
+  file: File | null
+  comment: string
+}
+
+const initialVariables: IForm = {
+  file: null,
+  comment: '',
+}
+
+const FileManager = () => {
+  const [folder, setFolder] = useState('upload_files')
+
+  const uploadFiles = useFsFilesQuery({ variables: { directory: folder } })
+  const files = useFilesQuery()
+
+  const error = (uploadFiles.error || files.error) && <p>Fehler beim Laden der Dateien...</p>
+  const loading = (uploadFiles.loading || files.loading) && <p>Lade Dateien...</p>
+
+  const danglingFsFilesFound = danglingFsFiles(uploadFiles.data, files.data)
+
+  function handleChange(event: ChangeEvent<HTMLInputElement>) {
+    setFolder(event.target.value)
+  }
+
+  return (
+    <form>
+      <h1>File Manager</h1>
+      <input type='text' name='folder' id='folder' value={folder} onChange={handleChange} />
+      {error}
+      {loading}
+      {danglingFsFilesFound ? (
+        <table>
+          <thead>
+            <tr>
+              <th></th>
+              <th>Datei</th>
+            </tr>
+          </thead>
+          <tbody>
+            {files.data?.files.map((file, index) =>
+              file ? (
+                <tr key={index}>
+                  <td>
+                    <input type='checkbox' />
+                  </td>
+                  <td>
+                    <a href={`/${file.path}`} download={file.filename}>
+                      {file.filename}
+                    </a>
+                  </td>
+                </tr>
+              ) : null
+            )}
+          </tbody>
+        </table>
+      ) : (
+        <p>no dangeling files found.</p>
+      )}
+    </form>
+  )
+}
+
+const UploadFile = () => {
+  const [uploadFile, { error, loading }] = useUploadFileMutation()
+  const [variables, setVariables] = useState(initialVariables)
+
+  return (
+    <>
+      <form
+        onSubmit={(event) => {
+          event.preventDefault()
+          uploadFile({ variables })
+        }}
+      >
+        <input
+          type='file'
+          name='file'
+          id='file'
+          onChange={(event) =>
+            setVariables({
+              ...variables,
+              file: event.target.files && event.target.files[0],
+            })
+          }
+        />
+        <textarea
+          name='comment'
+          id='comment'
+          placeholder='Kommentar'
+          onChange={(event) =>
+            setVariables({
+              ...variables,
+              comment: event.target.value,
+            })
+          }
+        ></textarea>
+        <button type='submit' disabled={loading}>
+          Upload
+        </button>
+        {error && <div className='error'>Error</div>}
+      </form>
+      <FileManager />
+    </>
+  )
+}
+
+export default UploadFile

+ 27 - 0
frontend/src/file/file.graphql

@@ -0,0 +1,27 @@
+scalar Upload
+
+query fsFiles($directory: String!) {
+  fsFiles(directory: $directory) {
+    filename
+    path
+    size
+    ctime
+    mtime
+  }
+}
+
+query files {
+  files {
+    filename
+    path
+    size
+    updatedAt
+    comment
+  }
+}
+
+mutation uploadFile($file: Upload!, $comment: String) {
+  uploadFile(file: $file, comment: $comment) {
+    id
+  }
+}

+ 3 - 0
frontend/src/file/index.ts

@@ -0,0 +1,3 @@
+import UploadFile from './components/UploadFile'
+
+export { UploadFile }

+ 9 - 0
frontend/src/file/utils.ts

@@ -0,0 +1,9 @@
+import { FsFilesQuery, FilesQuery } from '../gql'
+
+export function danglingFsFiles(fsFiles: FsFilesQuery | undefined, dbFiles: FilesQuery | undefined) {
+  return fsFiles && fsFiles.fsFiles.filter(fsFile => dbFiles && !dbFiles.files.map(dbFile => dbFile && dbFile.path).includes(fsFile && fsFile.path))
+}
+
+// export function danglingDbFiles(fsFiles: FsFile[], dbFiles: File[]) {
+//   return fsFiles.filter(fsFile => !dbFiles.map(dbFile => dbFile.path).includes(fsFile.path))
+// }

+ 21 - 0
frontend/src/form/components/Form.tsx

@@ -0,0 +1,21 @@
+import { FunctionComponent, DetailedHTMLProps, FormHTMLAttributes } from 'react'
+import { FormProvider, useForm } from '../hooks/useForm'
+
+interface IForm {
+  initialValues: any
+}
+
+const Form: FunctionComponent<IForm &
+  DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>> = ({
+  children,
+  initialValues,
+  ...props
+}) => {
+  return (
+    <FormProvider value={initialValues}>
+      <form {...props}>{children}</form>
+    </FormProvider>
+  )
+}
+
+export default Form

+ 0 - 1
frontend/src/form/components/TextInput.tsx

@@ -18,7 +18,6 @@ const TextInput = ({ name, label, id, type, onChange, value, className, ...props
       onChange(newValue)
     } else return onChange(event)
   }
-  console.log(name)
 
   return (
     <>

+ 7 - 8
frontend/src/form/hooks/useForm.tsx

@@ -1,8 +1,12 @@
-import { useState, ChangeEvent } from 'react'
+import { useState, ChangeEvent, createContext, useContext } from 'react'
 import { set, cloneDeep } from 'lodash'
 
+export const FormContext = createContext<{ values: any; onChange: any }>({} as any)
+export const FormProvider = FormContext.Provider
+
 export function useForm<T extends Dict>(initialValues: T) {
   const [values, setValues] = useState(initialValues)
+  //const form = useContext(FormContext)
 
   const touched = Object.entries(initialValues)
     .filter(([key, value]) => value !== values[key])
@@ -13,16 +17,11 @@ export function useForm<T extends Dict>(initialValues: T) {
   }
 
   function onChange(
-    event:
-      | ChangeEvent<HTMLInputElement>
-      | ChangeEvent<HTMLSelectElement>
-      | CustomChangeEvent
+    event: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLSelectElement> | CustomChangeEvent
   ) {
     const { type, name, value } = event.target
     const newValue =
-      type === 'checkbox'
-        ? (event.target as EventTarget & HTMLInputElement).checked
-        : value
+      type === 'checkbox' ? (event.target as EventTarget & HTMLInputElement).checked : value
 
     if (name.includes('.')) {
       const copy = cloneDeep(values)

+ 400 - 114
frontend/src/gql/index.tsx

@@ -30,7 +30,7 @@ export type Block = Node & {
   rest?: Maybe<Scalars['Int']>,
   tracks?: Maybe<Array<Track>>,
   blocks?: Maybe<Array<BlockInstance>>,
-  links?: Maybe<Array<BlockInstance>>,
+  parentBlockInstances?: Maybe<Array<BlockInstance>>,
   exercises?: Maybe<Array<ExerciseInstance>>,
 };
 
@@ -57,7 +57,7 @@ export type BlockBlocksArgs = {
 };
 
 
-export type BlockLinksArgs = {
+export type BlockParentBlockInstancesArgs = {
   where?: Maybe<BlockInstanceWhereInput>,
   orderBy?: Maybe<BlockInstanceOrderByInput>,
   skip?: Maybe<Scalars['Int']>,
@@ -83,8 +83,8 @@ export type BlockCreateOneWithoutBlocksInput = {
   connect?: Maybe<BlockWhereUniqueInput>,
 };
 
-export type BlockCreateOneWithoutLinksInput = {
-  create?: Maybe<BlockCreateWithoutLinksInput>,
+export type BlockCreateOneWithoutParentBlockInstancesInput = {
+  create?: Maybe<BlockCreateWithoutParentBlockInstancesInput>,
   connect?: Maybe<BlockWhereUniqueInput>,
 };
 
@@ -106,11 +106,11 @@ export type BlockCreateWithoutBlocksInput = {
   pictures?: Maybe<BlockCreatepicturesInput>,
   format: FormatCreateOneInput,
   tracks?: Maybe<TrackCreateManyInput>,
-  links?: Maybe<BlockInstanceCreateManyWithoutBlockInput>,
-  exercises?: Maybe<ExerciseInstanceCreateManyInput>,
+  parentBlockInstances?: Maybe<BlockInstanceCreateManyWithoutBlockInput>,
+  exercises?: Maybe<ExerciseInstanceCreateManyWithoutParentBlockInstancesInput>,
 };
 
-export type BlockCreateWithoutLinksInput = {
+export type BlockCreateWithoutParentBlockInstancesInput = {
   id?: Maybe<Scalars['ID']>,
   title: Scalars['String'],
   description?: Maybe<Scalars['String']>,
@@ -121,7 +121,7 @@ export type BlockCreateWithoutLinksInput = {
   format: FormatCreateOneInput,
   tracks?: Maybe<TrackCreateManyInput>,
   blocks?: Maybe<BlockInstanceCreateManyWithoutParentBlockInput>,
-  exercises?: Maybe<ExerciseInstanceCreateManyInput>,
+  exercises?: Maybe<ExerciseInstanceCreateManyWithoutParentBlockInstancesInput>,
 };
 
 export type BlockInstance = Node & {
@@ -163,7 +163,7 @@ export type BlockInstanceCreateWithoutParentBlockInput = {
   order: Scalars['Int'],
   rounds?: Maybe<Scalars['Int']>,
   variation?: Maybe<Scalars['String']>,
-  block: BlockCreateOneWithoutLinksInput,
+  block: BlockCreateOneWithoutParentBlockInstancesInput,
   parentTraining?: Maybe<TrainingCreateOneWithoutBlocksInput>,
 };
 
@@ -172,7 +172,7 @@ export type BlockInstanceCreateWithoutParentTrainingInput = {
   order: Scalars['Int'],
   rounds?: Maybe<Scalars['Int']>,
   variation?: Maybe<Scalars['String']>,
-  block: BlockCreateOneWithoutLinksInput,
+  block: BlockCreateOneWithoutParentBlockInstancesInput,
   parentBlock?: Maybe<BlockCreateOneWithoutBlocksInput>,
 };
 
@@ -339,7 +339,7 @@ export type BlockInstanceUpdateWithoutParentBlockDataInput = {
   order?: Maybe<Scalars['Int']>,
   rounds?: Maybe<Scalars['Int']>,
   variation?: Maybe<Scalars['String']>,
-  block?: Maybe<BlockUpdateOneRequiredWithoutLinksInput>,
+  block?: Maybe<BlockUpdateOneRequiredWithoutParentBlockInstancesInput>,
   parentTraining?: Maybe<TrainingUpdateOneWithoutBlocksInput>,
 };
 
@@ -347,7 +347,7 @@ export type BlockInstanceUpdateWithoutParentTrainingDataInput = {
   order?: Maybe<Scalars['Int']>,
   rounds?: Maybe<Scalars['Int']>,
   variation?: Maybe<Scalars['String']>,
-  block?: Maybe<BlockUpdateOneRequiredWithoutLinksInput>,
+  block?: Maybe<BlockUpdateOneRequiredWithoutParentBlockInstancesInput>,
   parentBlock?: Maybe<BlockUpdateOneWithoutBlocksInput>,
 };
 
@@ -497,11 +497,11 @@ export enum BlockOrderByInput {
   RestDesc = 'rest_DESC'
 }
 
-export type BlockUpdateOneRequiredWithoutLinksInput = {
-  create?: Maybe<BlockCreateWithoutLinksInput>,
+export type BlockUpdateOneRequiredWithoutParentBlockInstancesInput = {
+  create?: Maybe<BlockCreateWithoutParentBlockInstancesInput>,
   connect?: Maybe<BlockWhereUniqueInput>,
-  update?: Maybe<BlockUpdateWithoutLinksDataInput>,
-  upsert?: Maybe<BlockUpsertWithoutLinksInput>,
+  update?: Maybe<BlockUpdateWithoutParentBlockInstancesDataInput>,
+  upsert?: Maybe<BlockUpsertWithoutParentBlockInstancesInput>,
 };
 
 export type BlockUpdateOneWithoutBlocksInput = {
@@ -530,11 +530,11 @@ export type BlockUpdateWithoutBlocksDataInput = {
   pictures?: Maybe<BlockUpdatepicturesInput>,
   format?: Maybe<FormatUpdateOneRequiredInput>,
   tracks?: Maybe<TrackUpdateManyInput>,
-  links?: Maybe<BlockInstanceUpdateManyWithoutBlockInput>,
-  exercises?: Maybe<ExerciseInstanceUpdateManyInput>,
+  parentBlockInstances?: Maybe<BlockInstanceUpdateManyWithoutBlockInput>,
+  exercises?: Maybe<ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput>,
 };
 
-export type BlockUpdateWithoutLinksDataInput = {
+export type BlockUpdateWithoutParentBlockInstancesDataInput = {
   title?: Maybe<Scalars['String']>,
   description?: Maybe<Scalars['String']>,
   duration?: Maybe<Scalars['Int']>,
@@ -544,7 +544,7 @@ export type BlockUpdateWithoutLinksDataInput = {
   format?: Maybe<FormatUpdateOneRequiredInput>,
   tracks?: Maybe<TrackUpdateManyInput>,
   blocks?: Maybe<BlockInstanceUpdateManyWithoutParentBlockInput>,
-  exercises?: Maybe<ExerciseInstanceUpdateManyInput>,
+  exercises?: Maybe<ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput>,
 };
 
 export type BlockUpsertWithoutBlocksInput = {
@@ -552,9 +552,9 @@ export type BlockUpsertWithoutBlocksInput = {
   create: BlockCreateWithoutBlocksInput,
 };
 
-export type BlockUpsertWithoutLinksInput = {
-  update: BlockUpdateWithoutLinksDataInput,
-  create: BlockCreateWithoutLinksInput,
+export type BlockUpsertWithoutParentBlockInstancesInput = {
+  update: BlockUpdateWithoutParentBlockInstancesDataInput,
+  create: BlockCreateWithoutParentBlockInstancesInput,
 };
 
 export type BlockWhereInput = {
@@ -682,9 +682,9 @@ export type BlockWhereInput = {
   blocks_every?: Maybe<BlockInstanceWhereInput>,
   blocks_some?: Maybe<BlockInstanceWhereInput>,
   blocks_none?: Maybe<BlockInstanceWhereInput>,
-  links_every?: Maybe<BlockInstanceWhereInput>,
-  links_some?: Maybe<BlockInstanceWhereInput>,
-  links_none?: Maybe<BlockInstanceWhereInput>,
+  parentBlockInstances_every?: Maybe<BlockInstanceWhereInput>,
+  parentBlockInstances_some?: Maybe<BlockInstanceWhereInput>,
+  parentBlockInstances_none?: Maybe<BlockInstanceWhereInput>,
   exercises_every?: Maybe<ExerciseInstanceWhereInput>,
   exercises_some?: Maybe<ExerciseInstanceWhereInput>,
   exercises_none?: Maybe<ExerciseInstanceWhereInput>,
@@ -926,24 +926,26 @@ export type Exercise = Node & {
   pictures: Array<Scalars['String']>,
   targets: Array<Scalars['String']>,
   baseExercise: Array<Scalars['String']>,
+  parentExerciseInstances?: Maybe<Array<ExerciseInstance>>,
 };
 
-export type ExerciseCreatebaseExerciseInput = {
-  set?: Maybe<Array<Scalars['String']>>,
+
+export type ExerciseParentExerciseInstancesArgs = {
+  where?: Maybe<ExerciseInstanceWhereInput>,
+  orderBy?: Maybe<ExerciseInstanceOrderByInput>,
+  skip?: Maybe<Scalars['Int']>,
+  after?: Maybe<Scalars['String']>,
+  before?: Maybe<Scalars['String']>,
+  first?: Maybe<Scalars['Int']>,
+  last?: Maybe<Scalars['Int']>
 };
 
-export type ExerciseCreateInput = {
-  id?: Maybe<Scalars['ID']>,
-  name: Scalars['String'],
-  description?: Maybe<Scalars['String']>,
-  videos?: Maybe<ExerciseCreatevideosInput>,
-  pictures?: Maybe<ExerciseCreatepicturesInput>,
-  targets?: Maybe<ExerciseCreatetargetsInput>,
-  baseExercise?: Maybe<ExerciseCreatebaseExerciseInput>,
+export type ExerciseCreatebaseExerciseInput = {
+  set?: Maybe<Array<Scalars['String']>>,
 };
 
-export type ExerciseCreateOneInput = {
-  create?: Maybe<ExerciseCreateInput>,
+export type ExerciseCreateOneWithoutParentExerciseInstancesInput = {
+  create?: Maybe<ExerciseCreateWithoutParentExerciseInstancesInput>,
   connect?: Maybe<ExerciseWhereUniqueInput>,
 };
 
@@ -959,25 +961,36 @@ export type ExerciseCreatevideosInput = {
   set?: Maybe<Array<Scalars['String']>>,
 };
 
+export type ExerciseCreateWithoutParentExerciseInstancesInput = {
+  id?: Maybe<Scalars['ID']>,
+  name: Scalars['String'],
+  description?: Maybe<Scalars['String']>,
+  videos?: Maybe<ExerciseCreatevideosInput>,
+  pictures?: Maybe<ExerciseCreatepicturesInput>,
+  targets?: Maybe<ExerciseCreatetargetsInput>,
+  baseExercise?: Maybe<ExerciseCreatebaseExerciseInput>,
+};
+
 export type ExerciseInstance = Node & {
   id: Scalars['ID'],
   exercise: Exercise,
   order: Scalars['Int'],
   repetitions?: Maybe<Scalars['Int']>,
   variation?: Maybe<Scalars['String']>,
+  parentBlockInstances: Block,
 };
 
-export type ExerciseInstanceCreateInput = {
+export type ExerciseInstanceCreateManyWithoutParentBlockInstancesInput = {
+  create?: Maybe<Array<ExerciseInstanceCreateWithoutParentBlockInstancesInput>>,
+  connect?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
+};
+
+export type ExerciseInstanceCreateWithoutParentBlockInstancesInput = {
   id?: Maybe<Scalars['ID']>,
   order: Scalars['Int'],
   repetitions?: Maybe<Scalars['Int']>,
   variation?: Maybe<Scalars['String']>,
-  exercise: ExerciseCreateOneInput,
-};
-
-export type ExerciseInstanceCreateManyInput = {
-  create?: Maybe<Array<ExerciseInstanceCreateInput>>,
-  connect?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
+  exercise: ExerciseCreateOneWithoutParentExerciseInstancesInput,
 };
 
 export enum ExerciseInstanceOrderByInput {
@@ -1084,29 +1097,22 @@ export type ExerciseInstanceScalarWhereInput = {
   variation_not_ends_with?: Maybe<Scalars['String']>,
 };
 
-export type ExerciseInstanceUpdateDataInput = {
-  order?: Maybe<Scalars['Int']>,
-  repetitions?: Maybe<Scalars['Int']>,
-  variation?: Maybe<Scalars['String']>,
-  exercise?: Maybe<ExerciseUpdateOneRequiredInput>,
-};
-
 export type ExerciseInstanceUpdateManyDataInput = {
   order?: Maybe<Scalars['Int']>,
   repetitions?: Maybe<Scalars['Int']>,
   variation?: Maybe<Scalars['String']>,
 };
 
-export type ExerciseInstanceUpdateManyInput = {
-  create?: Maybe<Array<ExerciseInstanceCreateInput>>,
+export type ExerciseInstanceUpdateManyWithoutParentBlockInstancesInput = {
+  create?: Maybe<Array<ExerciseInstanceCreateWithoutParentBlockInstancesInput>>,
   connect?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
   set?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
   disconnect?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
   delete?: Maybe<Array<ExerciseInstanceWhereUniqueInput>>,
-  update?: Maybe<Array<ExerciseInstanceUpdateWithWhereUniqueNestedInput>>,
+  update?: Maybe<Array<ExerciseInstanceUpdateWithWhereUniqueWithoutParentBlockInstancesInput>>,
   updateMany?: Maybe<Array<ExerciseInstanceUpdateManyWithWhereNestedInput>>,
   deleteMany?: Maybe<Array<ExerciseInstanceScalarWhereInput>>,
-  upsert?: Maybe<Array<ExerciseInstanceUpsertWithWhereUniqueNestedInput>>,
+  upsert?: Maybe<Array<ExerciseInstanceUpsertWithWhereUniqueWithoutParentBlockInstancesInput>>,
 };
 
 export type ExerciseInstanceUpdateManyWithWhereNestedInput = {
@@ -1114,15 +1120,22 @@ export type ExerciseInstanceUpdateManyWithWhereNestedInput = {
   data: ExerciseInstanceUpdateManyDataInput,
 };
 
-export type ExerciseInstanceUpdateWithWhereUniqueNestedInput = {
+export type ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput = {
+  order?: Maybe<Scalars['Int']>,
+  repetitions?: Maybe<Scalars['Int']>,
+  variation?: Maybe<Scalars['String']>,
+  exercise?: Maybe<ExerciseUpdateOneRequiredWithoutParentExerciseInstancesInput>,
+};
+
+export type ExerciseInstanceUpdateWithWhereUniqueWithoutParentBlockInstancesInput = {
   where: ExerciseInstanceWhereUniqueInput,
-  data: ExerciseInstanceUpdateDataInput,
+  data: ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput,
 };
 
-export type ExerciseInstanceUpsertWithWhereUniqueNestedInput = {
+export type ExerciseInstanceUpsertWithWhereUniqueWithoutParentBlockInstancesInput = {
   where: ExerciseInstanceWhereUniqueInput,
-  update: ExerciseInstanceUpdateDataInput,
-  create: ExerciseInstanceCreateInput,
+  update: ExerciseInstanceUpdateWithoutParentBlockInstancesDataInput,
+  create: ExerciseInstanceCreateWithoutParentBlockInstancesInput,
 };
 
 export type ExerciseInstanceWhereInput = {
@@ -1217,6 +1230,7 @@ export type ExerciseInstanceWhereInput = {
   /** All values not ending with the given string. */
   variation_not_ends_with?: Maybe<Scalars['String']>,
   exercise?: Maybe<ExerciseWhereInput>,
+  parentBlockInstances?: Maybe<BlockWhereInput>,
 };
 
 export type ExerciseInstanceWhereUniqueInput = {
@@ -1236,20 +1250,11 @@ export type ExerciseUpdatebaseExerciseInput = {
   set?: Maybe<Array<Scalars['String']>>,
 };
 
-export type ExerciseUpdateDataInput = {
-  name?: Maybe<Scalars['String']>,
-  description?: Maybe<Scalars['String']>,
-  videos?: Maybe<ExerciseUpdatevideosInput>,
-  pictures?: Maybe<ExerciseUpdatepicturesInput>,
-  targets?: Maybe<ExerciseUpdatetargetsInput>,
-  baseExercise?: Maybe<ExerciseUpdatebaseExerciseInput>,
-};
-
-export type ExerciseUpdateOneRequiredInput = {
-  create?: Maybe<ExerciseCreateInput>,
+export type ExerciseUpdateOneRequiredWithoutParentExerciseInstancesInput = {
+  create?: Maybe<ExerciseCreateWithoutParentExerciseInstancesInput>,
   connect?: Maybe<ExerciseWhereUniqueInput>,
-  update?: Maybe<ExerciseUpdateDataInput>,
-  upsert?: Maybe<ExerciseUpsertNestedInput>,
+  update?: Maybe<ExerciseUpdateWithoutParentExerciseInstancesDataInput>,
+  upsert?: Maybe<ExerciseUpsertWithoutParentExerciseInstancesInput>,
 };
 
 export type ExerciseUpdatepicturesInput = {
@@ -1264,9 +1269,18 @@ export type ExerciseUpdatevideosInput = {
   set?: Maybe<Array<Scalars['String']>>,
 };
 
-export type ExerciseUpsertNestedInput = {
-  update: ExerciseUpdateDataInput,
-  create: ExerciseCreateInput,
+export type ExerciseUpdateWithoutParentExerciseInstancesDataInput = {
+  name?: Maybe<Scalars['String']>,
+  description?: Maybe<Scalars['String']>,
+  videos?: Maybe<ExerciseUpdatevideosInput>,
+  pictures?: Maybe<ExerciseUpdatepicturesInput>,
+  targets?: Maybe<ExerciseUpdatetargetsInput>,
+  baseExercise?: Maybe<ExerciseUpdatebaseExerciseInput>,
+};
+
+export type ExerciseUpsertWithoutParentExerciseInstancesInput = {
+  update: ExerciseUpdateWithoutParentExerciseInstancesDataInput,
+  create: ExerciseCreateWithoutParentExerciseInstancesInput,
 };
 
 export type ExerciseWhereInput = {
@@ -1357,6 +1371,9 @@ export type ExerciseWhereInput = {
   description_ends_with?: Maybe<Scalars['String']>,
   /** All values not ending with the given string. */
   description_not_ends_with?: Maybe<Scalars['String']>,
+  parentExerciseInstances_every?: Maybe<ExerciseInstanceWhereInput>,
+  parentExerciseInstances_some?: Maybe<ExerciseInstanceWhereInput>,
+  parentExerciseInstances_none?: Maybe<ExerciseInstanceWhereInput>,
 };
 
 export type ExerciseWhereUniqueInput = {
@@ -1528,6 +1545,7 @@ export type Mutation = {
   updateUser?: Maybe<User>,
   deleteUser?: Maybe<User>,
   createTraining: Training,
+  deleteTraining: Training,
   updateTraining: Training,
   createTrainingType: TrainingType,
   createFormat: Format,
@@ -1575,6 +1593,11 @@ export type MutationCreateTrainingArgs = {
 };
 
 
+export type MutationDeleteTrainingArgs = {
+  id: Scalars['ID']
+};
+
+
 export type MutationUpdateTrainingArgs = {
   where: TrainingWhereUniqueInput,
   data: TrainingUpdateInput
@@ -1656,6 +1679,7 @@ export enum Permission {
 }
 
 export type Query = {
+  trainingArchive: TrainingArchive,
   publishedTrainings: Array<Training>,
   training: Training,
   trainings: Array<Training>,
@@ -1676,6 +1700,12 @@ export type Query = {
 };
 
 
+export type QueryTrainingArchiveArgs = {
+  skip?: Maybe<Scalars['Int']>,
+  first?: Maybe<Scalars['Int']>
+};
+
+
 export type QueryPublishedTrainingsArgs = {
   where?: Maybe<TrainingWhereInput>,
   orderBy?: Maybe<TrainingOrderByInput>,
@@ -2480,6 +2510,23 @@ export type TrainingBlocksArgs = {
   last?: Maybe<Scalars['Int']>
 };
 
+export type TrainingArchive = {
+  trainings: Array<TrainingArchiveItem>,
+  totalCount: Scalars['Int'],
+};
+
+export type TrainingArchiveItem = {
+  id: Scalars['ID'],
+  title: Scalars['String'],
+  type: TrainingType,
+  trainingDate: Scalars['DateTime'],
+  location: Scalars['String'],
+  attendance?: Maybe<Scalars['Int']>,
+  ratings?: Maybe<Scalars['Float']>,
+  blocks: Array<Scalars['String']>,
+  duration?: Maybe<Scalars['Int']>,
+};
+
 /** A connection to a list of items. */
 export type TrainingConnection = {
   /** Information to aid in pagination. */
@@ -3407,18 +3454,39 @@ export type UserWhereUniqueInput = {
   email?: Maybe<Scalars['String']>,
 };
 
-export type PublishedTrainingsQueryVariables = {
-  where?: Maybe<TrainingWhereInput>,
-  orderBy?: Maybe<TrainingOrderByInput>,
+export type FsFilesQueryVariables = {
+  directory: Scalars['String']
+};
+
+
+export type FsFilesQuery = { fsFiles: Array<Pick<FsFile, 'filename' | 'path' | 'size' | 'ctime' | 'mtime'>> };
+
+export type FilesQueryVariables = {};
+
+
+export type FilesQuery = { files: Array<Pick<File, 'filename' | 'path' | 'size' | 'updatedAt' | 'comment'>> };
+
+export type UploadFileMutationVariables = {
+  file: Scalars['Upload'],
+  comment?: Maybe<Scalars['String']>
+};
+
+
+export type UploadFileMutation = { uploadFile: Pick<File, 'id'> };
+
+export type TrainingArchiveQueryVariables = {
   skip?: Maybe<Scalars['Int']>,
   first?: Maybe<Scalars['Int']>
 };
 
 
-export type PublishedTrainingsQuery = { publishedTrainings: Array<(
-    Pick<Training, 'id' | 'title' | 'trainingDate' | 'attendance'>
-    & { type: Pick<TrainingType, 'id' | 'name' | 'description'>, registrations: Maybe<Array<Pick<User, 'id'>>> }
-  )>, count: { aggregate: Pick<AggregateTraining, 'count'> } };
+export type TrainingArchiveQuery = { trainingArchive: (
+    Pick<TrainingArchive, 'totalCount'>
+    & { trainings: Array<(
+      Pick<TrainingArchiveItem, 'id' | 'title' | 'trainingDate' | 'location' | 'attendance' | 'blocks'>
+      & { type: Pick<TrainingType, 'name' | 'description'> }
+    )> }
+  ) };
 
 export type TrainingQueryVariables = {
   id?: Maybe<Scalars['ID']>
@@ -3427,6 +3495,13 @@ export type TrainingQueryVariables = {
 
 export type TrainingQuery = { training: DisplayTrainingFragment };
 
+export type DeleteTrainingMutationVariables = {
+  id: Scalars['ID']
+};
+
+
+export type DeleteTrainingMutation = { deleteTraining: Pick<Training, 'id'> };
+
 export type TrainingsQueryVariables = {
   where?: Maybe<TrainingWhereInput>,
   orderBy?: Maybe<TrainingOrderByInput>,
@@ -3569,7 +3644,36 @@ export type DisplayTrainingFragment = (
       & BlockWithoutBlocksFragment
     ) }
     & BlockInstanceWithoutBlockFragment
-  )>>, registrations: Maybe<Array<Pick<User, 'id'>>> }
+  )>>, registrations: Maybe<Array<Pick<User, 'id' | 'name'>>> }
+);
+
+export type EditTrainingFragment = (
+  Pick<Training, 'id' | 'createdAt' | 'title' | 'trainingDate' | 'location' | 'attendance' | 'published'>
+  & { type: Pick<TrainingType, 'id' | 'name' | 'description'>, blocks: Maybe<Array<(
+    { block: (
+      { blocks: Maybe<Array<(
+        { block: (
+          { blocks: Maybe<Array<(
+            { block: (
+              { blocks: Maybe<Array<(
+                { block: (
+                  { blocks: Maybe<Array<Pick<BlockInstance, 'id'>>> }
+                  & BlockWithoutBlocksFragment
+                ) }
+                & BlockInstanceWithoutBlockFragment
+              )>> }
+              & BlockWithoutBlocksFragment
+            ) }
+            & BlockInstanceWithoutBlockFragment
+          )>> }
+          & BlockWithoutBlocksFragment
+        ) }
+        & BlockInstanceWithoutBlockFragment
+      )>> }
+      & BlockWithoutBlocksFragment
+    ) }
+    & BlockInstanceWithoutBlockFragment
+  )>>, registrations: Maybe<Array<Pick<User, 'id' | 'name'>>> }
 );
 
 export type UsersQueryVariables = {};
@@ -3721,62 +3825,212 @@ export const DisplayTrainingFragmentDoc = gql`
   }
   registrations {
     id
+    name
   }
 }
     ${BlockInstanceWithoutBlockFragmentDoc}
 ${BlockWithoutBlocksFragmentDoc}`;
-export const PublishedTrainingsDocument = gql`
-    query publishedTrainings($where: TrainingWhereInput, $orderBy: TrainingOrderByInput, $skip: Int, $first: Int) {
-  publishedTrainings(where: $where, orderBy: $orderBy, skip: $skip, first: $first) {
+export const EditTrainingFragmentDoc = gql`
+    fragment editTraining on Training {
+  id
+  createdAt
+  title
+  type {
     id
-    title
-    type {
-      id
-      name
-      description
-    }
-    trainingDate
-    attendance
-    registrations {
-      id
+    name
+    description
+  }
+  createdAt
+  trainingDate
+  location
+  attendance
+  published
+  blocks {
+    ...blockInstanceWithoutBlock
+    block {
+      ...blockWithoutBlocks
+      blocks {
+        ...blockInstanceWithoutBlock
+        block {
+          ...blockWithoutBlocks
+          blocks {
+            ...blockInstanceWithoutBlock
+            block {
+              ...blockWithoutBlocks
+              blocks {
+                ...blockInstanceWithoutBlock
+                block {
+                  ...blockWithoutBlocks
+                  blocks {
+                    id
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
     }
   }
-  count: trainingsCount(where: $where) {
-    aggregate {
-      count
+  registrations {
+    id
+    name
+  }
+}
+    ${BlockInstanceWithoutBlockFragmentDoc}
+${BlockWithoutBlocksFragmentDoc}`;
+export const FsFilesDocument = gql`
+    query fsFiles($directory: String!) {
+  fsFiles(directory: $directory) {
+    filename
+    path
+    size
+    ctime
+    mtime
+  }
+}
+    `;
+
+/**
+ * __useFsFilesQuery__
+ *
+ * To run a query within a React component, call `useFsFilesQuery` and pass it any options that fit your needs.
+ * When your component renders, `useFsFilesQuery` returns an object from Apollo Client that contains loading, error, and data properties 
+ * you can use to render your UI.
+ *
+ * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
+ *
+ * @example
+ * const { data, loading, error } = useFsFilesQuery({
+ *   variables: {
+ *      directory: // value for 'directory'
+ *   },
+ * });
+ */
+export function useFsFilesQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<FsFilesQuery, FsFilesQueryVariables>) {
+        return ApolloReactHooks.useQuery<FsFilesQuery, FsFilesQueryVariables>(FsFilesDocument, baseOptions);
+      }
+export function useFsFilesLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<FsFilesQuery, FsFilesQueryVariables>) {
+          return ApolloReactHooks.useLazyQuery<FsFilesQuery, FsFilesQueryVariables>(FsFilesDocument, baseOptions);
+        }
+export type FsFilesQueryHookResult = ReturnType<typeof useFsFilesQuery>;
+export type FsFilesLazyQueryHookResult = ReturnType<typeof useFsFilesLazyQuery>;
+export type FsFilesQueryResult = ApolloReactCommon.QueryResult<FsFilesQuery, FsFilesQueryVariables>;
+export const FilesDocument = gql`
+    query files {
+  files {
+    filename
+    path
+    size
+    updatedAt
+    comment
+  }
+}
+    `;
+
+/**
+ * __useFilesQuery__
+ *
+ * To run a query within a React component, call `useFilesQuery` and pass it any options that fit your needs.
+ * When your component renders, `useFilesQuery` returns an object from Apollo Client that contains loading, error, and data properties 
+ * you can use to render your UI.
+ *
+ * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
+ *
+ * @example
+ * const { data, loading, error } = useFilesQuery({
+ *   variables: {
+ *   },
+ * });
+ */
+export function useFilesQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<FilesQuery, FilesQueryVariables>) {
+        return ApolloReactHooks.useQuery<FilesQuery, FilesQueryVariables>(FilesDocument, baseOptions);
+      }
+export function useFilesLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<FilesQuery, FilesQueryVariables>) {
+          return ApolloReactHooks.useLazyQuery<FilesQuery, FilesQueryVariables>(FilesDocument, baseOptions);
+        }
+export type FilesQueryHookResult = ReturnType<typeof useFilesQuery>;
+export type FilesLazyQueryHookResult = ReturnType<typeof useFilesLazyQuery>;
+export type FilesQueryResult = ApolloReactCommon.QueryResult<FilesQuery, FilesQueryVariables>;
+export const UploadFileDocument = gql`
+    mutation uploadFile($file: Upload!, $comment: String) {
+  uploadFile(file: $file, comment: $comment) {
+    id
+  }
+}
+    `;
+export type UploadFileMutationFn = ApolloReactCommon.MutationFunction<UploadFileMutation, UploadFileMutationVariables>;
+
+/**
+ * __useUploadFileMutation__
+ *
+ * To run a mutation, you first call `useUploadFileMutation` within a React component and pass it any options that fit your needs.
+ * When your component renders, `useUploadFileMutation` returns a tuple that includes:
+ * - A mutate function that you can call at any time to execute the mutation
+ * - An object with fields that represent the current status of the mutation's execution
+ *
+ * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
+ *
+ * @example
+ * const [uploadFileMutation, { data, loading, error }] = useUploadFileMutation({
+ *   variables: {
+ *      file: // value for 'file'
+ *      comment: // value for 'comment'
+ *   },
+ * });
+ */
+export function useUploadFileMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<UploadFileMutation, UploadFileMutationVariables>) {
+        return ApolloReactHooks.useMutation<UploadFileMutation, UploadFileMutationVariables>(UploadFileDocument, baseOptions);
+      }
+export type UploadFileMutationHookResult = ReturnType<typeof useUploadFileMutation>;
+export type UploadFileMutationResult = ApolloReactCommon.MutationResult<UploadFileMutation>;
+export type UploadFileMutationOptions = ApolloReactCommon.BaseMutationOptions<UploadFileMutation, UploadFileMutationVariables>;
+export const TrainingArchiveDocument = gql`
+    query trainingArchive($skip: Int, $first: Int) {
+  trainingArchive(skip: $skip, first: $first) {
+    trainings {
+      id
+      title
+      type {
+        name
+        description
+      }
+      trainingDate
+      location
+      attendance
+      blocks
     }
+    totalCount
   }
 }
     `;
 
 /**
- * __usePublishedTrainingsQuery__
+ * __useTrainingArchiveQuery__
  *
- * To run a query within a React component, call `usePublishedTrainingsQuery` and pass it any options that fit your needs.
- * When your component renders, `usePublishedTrainingsQuery` returns an object from Apollo Client that contains loading, error, and data properties 
+ * To run a query within a React component, call `useTrainingArchiveQuery` and pass it any options that fit your needs.
+ * When your component renders, `useTrainingArchiveQuery` returns an object from Apollo Client that contains loading, error, and data properties 
  * you can use to render your UI.
  *
  * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
  *
  * @example
- * const { data, loading, error } = usePublishedTrainingsQuery({
+ * const { data, loading, error } = useTrainingArchiveQuery({
  *   variables: {
- *      where: // value for 'where'
- *      orderBy: // value for 'orderBy'
  *      skip: // value for 'skip'
  *      first: // value for 'first'
  *   },
  * });
  */
-export function usePublishedTrainingsQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>) {
-        return ApolloReactHooks.useQuery<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>(PublishedTrainingsDocument, baseOptions);
+export function useTrainingArchiveQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<TrainingArchiveQuery, TrainingArchiveQueryVariables>) {
+        return ApolloReactHooks.useQuery<TrainingArchiveQuery, TrainingArchiveQueryVariables>(TrainingArchiveDocument, baseOptions);
       }
-export function usePublishedTrainingsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>) {
-          return ApolloReactHooks.useLazyQuery<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>(PublishedTrainingsDocument, baseOptions);
+export function useTrainingArchiveLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<TrainingArchiveQuery, TrainingArchiveQueryVariables>) {
+          return ApolloReactHooks.useLazyQuery<TrainingArchiveQuery, TrainingArchiveQueryVariables>(TrainingArchiveDocument, baseOptions);
         }
-export type PublishedTrainingsQueryHookResult = ReturnType<typeof usePublishedTrainingsQuery>;
-export type PublishedTrainingsLazyQueryHookResult = ReturnType<typeof usePublishedTrainingsLazyQuery>;
-export type PublishedTrainingsQueryResult = ApolloReactCommon.QueryResult<PublishedTrainingsQuery, PublishedTrainingsQueryVariables>;
+export type TrainingArchiveQueryHookResult = ReturnType<typeof useTrainingArchiveQuery>;
+export type TrainingArchiveLazyQueryHookResult = ReturnType<typeof useTrainingArchiveLazyQuery>;
+export type TrainingArchiveQueryResult = ApolloReactCommon.QueryResult<TrainingArchiveQuery, TrainingArchiveQueryVariables>;
 export const TrainingDocument = gql`
     query training($id: ID) {
   training(id: $id) {
@@ -3810,6 +4064,38 @@ export function useTrainingLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHoo
 export type TrainingQueryHookResult = ReturnType<typeof useTrainingQuery>;
 export type TrainingLazyQueryHookResult = ReturnType<typeof useTrainingLazyQuery>;
 export type TrainingQueryResult = ApolloReactCommon.QueryResult<TrainingQuery, TrainingQueryVariables>;
+export const DeleteTrainingDocument = gql`
+    mutation deleteTraining($id: ID!) {
+  deleteTraining(id: $id) {
+    id
+  }
+}
+    `;
+export type DeleteTrainingMutationFn = ApolloReactCommon.MutationFunction<DeleteTrainingMutation, DeleteTrainingMutationVariables>;
+
+/**
+ * __useDeleteTrainingMutation__
+ *
+ * To run a mutation, you first call `useDeleteTrainingMutation` within a React component and pass it any options that fit your needs.
+ * When your component renders, `useDeleteTrainingMutation` returns a tuple that includes:
+ * - A mutate function that you can call at any time to execute the mutation
+ * - An object with fields that represent the current status of the mutation's execution
+ *
+ * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
+ *
+ * @example
+ * const [deleteTrainingMutation, { data, loading, error }] = useDeleteTrainingMutation({
+ *   variables: {
+ *      id: // value for 'id'
+ *   },
+ * });
+ */
+export function useDeleteTrainingMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<DeleteTrainingMutation, DeleteTrainingMutationVariables>) {
+        return ApolloReactHooks.useMutation<DeleteTrainingMutation, DeleteTrainingMutationVariables>(DeleteTrainingDocument, baseOptions);
+      }
+export type DeleteTrainingMutationHookResult = ReturnType<typeof useDeleteTrainingMutation>;
+export type DeleteTrainingMutationResult = ApolloReactCommon.MutationResult<DeleteTrainingMutation>;
+export type DeleteTrainingMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteTrainingMutation, DeleteTrainingMutationVariables>;
 export const TrainingsDocument = gql`
     query trainings($where: TrainingWhereInput, $orderBy: TrainingOrderByInput, $skip: Int, $after: String, $before: String, $first: Int, $last: Int) {
   count: trainingsCount(where: $where) {

+ 5 - 11
frontend/src/lib/apollo.js → frontend/src/lib/apollo.ts

@@ -7,27 +7,21 @@
  * * Setting request to handle credentials.
  */
 
-// import { withData } from 'next-apollo'
-// import { HttpLink } from 'apollo-boost'
-import { ApolloLink } from 'apollo-link'
 import { onError } from 'apollo-link-error'
-
-import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
+import { createUploadLink } from 'apollo-upload-client'
+import { ApolloClient, InMemoryCache, from } from '@apollo/client'
 import fetch from 'isomorphic-unfetch'
 
 const client = new ApolloClient({
-  link: ApolloLink.from([
+  link: from([
     onError((errors) => {
       console.log(errors)
-      if (errors && errors.response && errors.response.errors) {
-        // errors.response.errors = null
-      }
     }),
-    new HttpLink({
+    createUploadLink({
       uri: '/graphql/',
       credentials: 'include',
       fetch,
-    }),
+    }) as any,
   ]),
   cache: new InMemoryCache(),
 })

+ 1 - 0
frontend/src/styles/global.ts

@@ -103,6 +103,7 @@ const GlobalStyle = css.global`
     border: none;
     background-color: ${theme.colors.buttonBackground};
     color: ${theme.colors.button};
+    cursor: pointer;
   }
 
   form fieldset {

+ 82 - 46
frontend/src/styles/theme.ts

@@ -1,20 +1,21 @@
-const theme = {
+const basicTheme = {
   colors: {
-    lightred: '#f0b0b0',
-    black: '#393939',
-    darkgrey: '#5d6a6b',
-    grey: '#7f8c8d',
-    lightgrey: '#95a5a5',
-    lighterblue: '#d6e4f0',
-    lightblue: '#b0d3f0',
-    blue: '#4482c3',
-    darkblue: '#285680',
-    darkerblue: '#204567',
-    offWhite: '#EDEDED',
-    nav: '#393939e7',
-
     logoRed: '#eb0000',
     logoBlack: '#1a1a1a',
+    white: '#eeeeee',
+    black: '#444444',
+  },
+  midsize: '512px',
+  fullsize: '1024px',
+  bs: '0 8px 12px 0 rgba(0,0,0,0.09)',
+  bsUp: '0 -8px 12px 0 rgba(0,0,0,0.18)',
+  bsSmall: '0 5px 10px 0 rgba(0,0,0,0.19)',
+}
+
+const theme = {
+  ...basicTheme,
+  colors: {
+    ...basicTheme.colors,
     color: '#424242',
     background: '#ededed',
     links: '#00A54D',
@@ -33,24 +34,6 @@ const theme = {
     presentation: '#e6ebe0',
     presentationBackground: '#3C8EC8',
   },
-  theme2: {
-    terraCotta: '#ed6a5a',
-    blond: '#f4f1bb',
-    brightCerulean: '#31afd4',
-    cambridgeBlue: '#9bc1bc',
-    platinum: '#e6ebe0',
-  },
-  theme3: {
-    sunsetOrange: '#ff595e',
-    sunGlow: '#ffca3a',
-    brightCerulean: '#31afd4',
-    yellowGreen: '#8ac926',
-    darkLavender: '#6a4c93',
-  },
-  maxWidth: '1000px',
-  bs: '0 8px 12px 0 rgba(0,0,0,0.09)',
-  bsUp: '0 -8px 12px 0 rgba(0,0,0,0.18)',
-  bsSmall: '0 5px 10px 0 rgba(0,0,0,0.19)',
 }
 
 const palette2 = {
@@ -59,25 +42,80 @@ const palette2 = {
   color3: '#FFD166',
   color4: '#118AB2',
   color5: '#073B4C',
-  white: '#eeeeee',
-  black: '#444444',
+  link: 'https://coolors.co/18daae-ef476f-ffd166-118ab2-073b4c',
+}
+
+const palette3 = {
+  color1: '#041C54',
+  color2: '#6E7082',
+  color3: '#E8521E',
+  color4: '#50D796',
+  color5: '#2ED3FD',
+  link: 'https://coolors.co/041c54-6e7082-e8521e-50d796-2ed3fd',
+}
+
+const palette4 = {
+  color1: '#85ffc7',
+  color2: '#004a99',
+  color3: '#ff8552',
+  color4: '#e6e6e6',
+  color5: '#39393a',
+  link: 'https://coolors.co/85ffc7-004a99-ff8552-e6e6e6-39393a',
+}
+
+const palette5 = {
+  color1: '#ffffff',
+  color2: '#d1d2cb',
+  color3: '#ff5e5b',
+  color4: '#00cecb',
+  color5: '#353535',
+  link: 'https://coolors.co/ffffff-d1d2cb-ff5e5b-00cecb-353535',
+}
+
+const palette6 = {
+  color1: '#ff7842',
+  color2: '#f6f9fa',
+  color3: '#afaca9',
+  color4: '#5da9e9',
+  color5: '#e5f4e3',
+  link: 'https://coolors.co/ff7842-f6f9fa-afaca9-5da9e9-e5f4e3',
+}
+
+const palette7 = {
+  color1: '#366389',
+  color2: '#2f4559',
+  color3: '#f3b038',
+  color4: '#f07230',
+  color5: '#8dcbe8',
+  link: 'https://coolors.co/366389-2f4559-f3b038-f07230-8dcbe8',
+}
+
+const palette8 = {
+  color1: '#011627',
+  color2: '#fdfffc',
+  color3: '#2ec4b6',
+  color4: '#e71d36',
+  color5: '#ff9f1c',
+  link: 'https://coolors.co/011627-fdfffc-2ec4b6-e71d36-ff9f1c',
 }
 
 const theme2 = {
+  ...basicTheme,
   colors: {
-    logoRed: '#eb0000',
-    logoBlack: '#1a1a1a',
-    color: palette2.black,
+    ...basicTheme.colors,
+    color: basicTheme.colors.black,
     highlight: palette2.color5,
-    background: palette2.white,
+    background: basicTheme.colors.white,
     links: palette2.color2,
     linksHighlight: palette2.color2,
-    headerColor: palette2.black,
-    headerBackground: palette2.white,
-    footer: palette2.white,
-    footerBackground: palette2.black,
-    button: palette2.white,
+    headerColor: basicTheme.colors.black,
+    headerBackground: basicTheme.colors.white,
+    footer: basicTheme.colors.white,
+    footerBackground: basicTheme.colors.black,
+    button: basicTheme.colors.white,
     buttonBackground: palette2.color2,
+    balloon: basicTheme.colors.black,
+    balloonBackground: palette2.color3,
     formColor: '#085B96',
     formBackground: '#8CC1E7',
     formHighlight: '#00A54D',
@@ -86,10 +124,8 @@ const theme2 = {
     formErrorBackground: '#FFAC94',
     mobileNav: '#efefef',
     mobileNavBackground: '#565656',
-    presentation: palette2.white,
+    presentation: basicTheme.colors.white,
     presentationBackground: palette2.color4,
-    white: palette2.white,
-    black: palette2.black,
   },
   midsize: '512px',
   fullsize: '1024px',

+ 1 - 1
frontend/src/training/components/BlockInstanceInputs.tsx

@@ -19,7 +19,7 @@ const BlockInstanceInputs = ({
       {!value.id.startsWith('++') && (
         <div className='bi-info'>
           <div>Block Instance ID{value.id}</div>
-          <div>Created at: {value}</div>
+          <div>Created at:</div>
         </div>
       )}
       <TextInput

+ 3 - 4
frontend/src/training/components/EditTraining.tsx

@@ -1,8 +1,7 @@
 import { useCreateTrainingMutation, useUpdateTrainingMutation } from '../../gql'
 import { useForm, TextInput, DateTimeInput, Checkbox } from '../../form'
-import { emptyTraining, emptyBlockInstance, prepareDataForDB } from '../utils'
+import { emptyTraining, prepareDataForDB } from '../utils'
 import TrainingTypeSelector from './TrainingTypeSelector'
-import BlockInstanceInputs from './BlockInstanceInputs'
 import { TTraining } from '../types'
 import Registrations from './Registrations'
 import Ratings from './Ratings'
@@ -18,7 +17,7 @@ const EditTraining = ({ training }: { training?: TTraining }) => {
     <form
       onSubmit={async (event) => {
         event.preventDefault()
-        const newValues = prepareDataForDB(values, training || emptyTraining())
+        const newValues = prepareDataForDB(values, training || {})
         if (!newValues || Object.keys(newValues).length === 0) {
           console.log('no changes.')
           return
@@ -39,7 +38,7 @@ const EditTraining = ({ training }: { training?: TTraining }) => {
       <fieldset className='fields-training'>
         {!values.id.startsWith('++') && (
           <div className='training-info'>
-            <div>Training ID: {values.id}, </div>
+            <div>Training ID: {values.id}</div>
             <div>Created at: {values.createdAt}</div>
           </div>
         )}

+ 0 - 1
frontend/src/training/components/RegistrationButton.tsx

@@ -2,7 +2,6 @@ import { useRegisterMutation, useDeregisterMutation, User, TrainingDocument } fr
 import { FunctionComponent, useContext } from 'react'
 import { UserContext } from '../../user/hooks'
 import { TTraining } from '../types'
-import theme from '../../styles/theme'
 
 type TRegisterButton = FunctionComponent<{ training: TTraining }>
 

+ 1 - 0
frontend/src/training/components/Registrations.tsx

@@ -7,6 +7,7 @@ const Registrations = ({
   registrations?: User[]
   className: string
 }) => {
+  console.log(registrations)
   return (
     <div className={className}>
       <h2>Registrations</h2>

+ 8 - 9
frontend/src/training/components/TrainingArchive.tsx

@@ -1,4 +1,4 @@
-import { useTrainingsQuery, usePublishedTrainingsQuery } from '../../gql'
+import { useTrainingArchiveQuery } from '../../gql'
 import { useState } from 'react'
 import TrainingHint from './TrainingHint'
 import theme from '../../styles/theme'
@@ -6,17 +6,16 @@ import theme from '../../styles/theme'
 const TrainingArchive = () => {
   const trainingsPerPage = 4
   const [state, setState] = useState(0)
-  const archive = usePublishedTrainingsQuery()
-  const { data, error, loading } = useTrainingsQuery({
-    variables: { skip: state * trainingsPerPage, first: trainingsPerPage },
+  const { data, error, loading } = useTrainingArchiveQuery({
+    variables: { first: trainingsPerPage, skip: state * trainingsPerPage },
   })
   if (loading) return <p>Loading trainings...</p>
   if (error) return <p>Error loading trainings.</p>
   if (!data) return null
-  const { trainings, count } = data
+  const { trainings, totalCount } = data.trainingArchive
   const pages = []
 
-  for (let index = 0; index < count.aggregate.count / trainingsPerPage; index++) {
+  for (let index = 0; index < totalCount / trainingsPerPage; index++) {
     pages.push(index)
   }
 
@@ -24,7 +23,7 @@ const TrainingArchive = () => {
     <section className='training-archive'>
       <h2>Training Archive</h2>
       <ul>
-        {trainings.map((training) => (
+        {trainings.map((training, index) => (
           <TrainingHint key={training.id} training={training} />
         ))}
       </ul>
@@ -67,12 +66,12 @@ const TrainingArchive = () => {
           background-color: ${theme.colors.buttonBackground};
           color: ${theme.colors.button};
         }
-        @media (min-width: 480px) {
+        @media (min-width: ${theme.midsize}) {
           ul {
             grid-template-columns: 1fr 1fr;
           }
         }
-        @media (min-width: 1024px) {
+        @media (min-width: ${theme.fullsize}) {
           ul {
             grid-template-columns: repeat(4, 1fr);
           }

+ 6 - 2
frontend/src/training/components/TrainingHint.tsx

@@ -1,14 +1,18 @@
 import { FunctionComponent } from 'react'
-import { TTraining } from '../types'
+import { TTrainingArchiveItem } from '../types'
 import Link from 'next/link'
+import TrainingTypeButton from './TrainingTypeButton'
 
-const TrainingHint: FunctionComponent<{ training: TTraining }> = ({ training }) => {
+const TrainingHint: FunctionComponent<{ training: TTrainingArchiveItem }> = ({ training }) => {
   return (
     <Link href='/training/[id]' as={`/training/${training.id}`}>
       <a>
         <li>
           <div>{training.title}</div>
           <div>{new Date(training.trainingDate).toLocaleString()}</div>
+          <div>
+            <TrainingTypeButton trainingType={training.type} />
+          </div>
           <style jsx>{``}</style>
         </li>
       </a>

+ 0 - 99
frontend/src/training/components/TrainingType.tsx

@@ -1,99 +0,0 @@
-/*import { Query, Mutation } from 'react-apollo'
-import { adopt } from 'react-adopt'
-import { Formik, Form } from 'formik'
-
-import { TextInput } from '../../lib/forms'
-import { CREATE_TRAINING_TYPE, TRAINING_TYPES } from '../../lib/graphql'
-import Overlay from '../../../components/overlay'
-
-const TrainingTypeInput = props => {
-  const [displayForm, setDisplayForm] = React.useState(false)
-
-  const toggleForm = ev => {
-    ev.preventDefault()
-    setDisplayForm(!displayForm)
-  }
-
-  return (
-    <Query query={TRAINING_TYPES}>
-      {({ data, error, loading }) => (
-        <>
-          <label>Training type</label>
-          <div>
-            <select disabled={(loading || error)}>
-              {data ? data.trainingTypes.map(trainingType =>
-                <option key={trainingType.id} value={trainingType.id}>{trainingType.name}</option>
-              ) : null}
-            </select>
-            <button
-              type='button'
-              onClick={toggleForm}
-            >Add
-            </button>
-          </div>
-          {displayForm ? (
-            <Overlay close={toggleForm}>
-              <TrainingTypeForm />
-            </Overlay>
-          ) : null}
-
-          <style jsx>
-            {`
-              div {
-                width: 100%;
-              }
-            `}
-          </style>
-        </>
-      )}
-    </Query>
-  )
-}
-
-const TrainingTypeAdoption = adopt({
-  mutation: ({ render }) => (
-    <Mutation
-      mutation={CREATE_TRAINING_TYPE}
-      refetchQueries={[{ query: TRAINING_TYPES }]}
-    >
-      {(createTrainingType, { data, error, loading }) => render({ createTrainingType, data, error, loading })}
-    </Mutation>
-  ),
-  form: ({ mutation: { createTrainingType }, render }) => (
-    <Formik
-      initialValues={{
-        name: '',
-        description: ''
-      }}
-      onSubmit={values => createTrainingType({ variables: values })}
-    >
-      {render}
-    </Formik>
-  )
-})
-
-const TrainingTypeForm = props => (
-  <TrainingTypeAdoption>{({ mutation, form }) => (
-    <Form>
-      <TextInput
-        label='Name'
-        name='name'
-        type='text'
-      />
-      <TextInput
-        label='Description'
-        name='description'
-        type='text'
-      />
-      <button type='reset'>Reset</button>
-      <button type='submit'>Save</button>
-    </Form>
-  )}
-  </TrainingTypeAdoption>
-)
-
-export { TrainingTypeForm }
-*/
-
-const TrainingTypeInput = () => <p>nothing here.</p>;
-export default TrainingTypeInput;

+ 60 - 0
frontend/src/training/components/TrainingTypeButton.tsx

@@ -0,0 +1,60 @@
+import { TrainingType } from '../../gql'
+import theme from '../../styles/theme'
+
+const TrainingTypeButton = ({ trainingType }: { trainingType?: TrainingType }) => {
+  if (!trainingType) return null
+  return (
+    <span className='training-type'>
+      {trainingType.name}
+      <span className='training-type-description'>{trainingType.description}</span>
+      <style jsx>{`
+        .training-type {
+          position: relative;
+          padding: 0.1em 0.4em;
+          font-size: 80%;
+          background-color: ${theme.colors.balloonBackground};
+          color: ${theme.colors.balloon};
+        }
+        .training-type .training-type-description {
+          display: none;
+          position: absolute;
+          padding: 0.4em;
+          margin-bottom: 10px;
+          bottom: 100%;
+          min-width: 10em;
+          left: 0;
+        }
+        .training-type:hover .training-type-description {
+          display: block;
+          background-color: ${theme.colors.balloonBackground};
+          color: ${theme.colors.balloon};
+          border: 1px solid ${theme.colors.balloon};
+        }
+        .training-type-description::after,
+        .training-type-description::before {
+          content: '';
+          display: block;
+          position: absolute;
+          bottom: -10px;
+          left: 3px;
+          width: 10px;
+          height: 10px;
+          z-index: 1;
+          background-color: ${theme.colors.balloonBackground};
+          border: 1px solid ${theme.colors.balloonBackground};
+          border-left: 1px solid ${theme.colors.balloon};
+          clip-path: polygon(0 0, 100% 0, 0 100%);
+          transform: skewX(45deg);
+        }
+        .training-type-description::after {
+          left: 3px;
+          border-left: 1px solid ${theme.colors.balloonBackground};
+          border-right: 1px solid ${theme.colors.balloon};
+          clip-path: polygon(0 0, 100% 0, 100% 100%);
+          transform: skewX(-45deg);
+        }
+      `}</style>
+    </span>
+  )
+}
+export default TrainingTypeButton

+ 68 - 22
frontend/src/training/training.graphql

@@ -1,30 +1,22 @@
 # import * from '../../../backend/database/generated/prisma.graphql'
 
 # Only some basic data to be able to display the training
-query publishedTrainings(
-  $where: TrainingWhereInput
-  $orderBy: TrainingOrderByInput
-  $skip: Int
-  $first: Int
-) {
-  publishedTrainings(where: $where, orderBy: $orderBy, skip: $skip, first: $first) {
-    id
-    title
-    type {
-      id
-      name
-      description
-    }
-    trainingDate
-    attendance
-    registrations {
+
+query trainingArchive($skip: Int, $first: Int) {
+  trainingArchive(skip: $skip, first: $first) {
+    trainings {
       id
+      title
+      type {
+        name
+        description
+      }
+      trainingDate
+      location
+      attendance
+      blocks
     }
-  }
-  count: trainingsCount(where: $where) {
-    aggregate {
-      count
-    }
+    totalCount
   }
 }
 
@@ -35,6 +27,12 @@ query training($id: ID) {
   }
 }
 
+mutation deleteTraining($id: ID!) {
+  deleteTraining(id: $id) {
+    id
+  }
+}
+
 # The full data set.
 query trainings(
   $where: TrainingWhereInput
@@ -244,5 +242,53 @@ fragment displayTraining on Training {
   }
   registrations {
     id
+    name
+  }
+}
+
+fragment editTraining on Training {
+  id
+  createdAt
+  title
+  type {
+    id
+    name
+    description
+  }
+  createdAt
+  trainingDate
+  location
+  attendance
+  published
+  blocks {
+    ...blockInstanceWithoutBlock
+    block {
+      ...blockWithoutBlocks
+      blocks {
+        ...blockInstanceWithoutBlock
+        block {
+          ...blockWithoutBlocks
+          blocks {
+            ...blockInstanceWithoutBlock
+            block {
+              ...blockWithoutBlocks
+              blocks {
+                ...blockInstanceWithoutBlock
+                block {
+                  ...blockWithoutBlocks
+                  blocks {
+                    id
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  registrations {
+    id
+    name
   }
 }

+ 9 - 25
frontend/src/training/types.ts

@@ -3,35 +3,24 @@ import {
   BlockInstance,
   Block,
   ExerciseInstance,
-  Exercise
+  Exercise,
+  TrainingArchiveItem,
 } from '../gql'
 
-export type TTraining = Pick<Training, 'id' | 'type'> &
-  Partial<Omit<Training, 'id' | 'type'>>
+export type TTrainingArchiveItem = Pick<TrainingArchiveItem, 'id'> &
+  Partial<Omit<TrainingArchiveItem, 'id'>>
+
+export type TTraining = Pick<Training, 'id' | 'type'> & Partial<Omit<Training, 'id' | 'type'>>
 export type TBlockInstance = Pick<BlockInstance, 'id' | 'block' | 'order'> &
   Partial<Omit<BlockInstance, 'id' | 'block' | 'order'>>
 export type TBlock = Pick<
   Block,
-  | 'id'
-  | 'title'
-  | 'exercises'
-  | 'videos'
-  | 'blocks'
-  | 'tracks'
-  | 'pictures'
-  | 'format'
+  'id' | 'title' | 'exercises' | 'videos' | 'blocks' | 'tracks' | 'pictures' | 'format'
 > &
   Partial<
     Omit<
       Block,
-      | 'id'
-      | 'title'
-      | 'exercises'
-      | 'videos'
-      | 'blocks'
-      | 'tracks'
-      | 'pictures'
-      | 'format'
+      'id' | 'title' | 'exercises' | 'videos' | 'blocks' | 'tracks' | 'pictures' | 'format'
     >
   >
 export type TExerciseInstance = Pick<ExerciseInstance, 'id' | 'exercise'> &
@@ -40,10 +29,5 @@ export type TExercise = Pick<
   Exercise,
   'id' | 'name' | 'pictures' | 'videos' | 'targets' | 'baseExercise'
 > &
-  Partial<
-    Omit<
-      Exercise,
-      'id' | 'name' | 'pictures' | 'videos' | 'targets' | 'baseExercise'
-    >
-  >
+  Partial<Omit<Exercise, 'id' | 'name' | 'pictures' | 'videos' | 'targets' | 'baseExercise'>>
 export type TRating = { value: number }

+ 10 - 6
frontend/src/user/components/UserNav.tsx

@@ -14,7 +14,6 @@ const UserNav = () => {
   const ref = useRef<HTMLLIElement>(null)
   const { user } = useContext(UserContext)
   useOnClickOutside(ref, () => {
-    console.log('outside menupoint', menu)
     setMenu(false)
   })
 
@@ -22,7 +21,7 @@ const UserNav = () => {
     <>
       {user?.data?.currentUser.permissions.includes(Permission.Admin) && (
         <li>
-          <Link href='admin'>
+          <Link href='/admin'>
             <a>
               <FontAwesomeIcon icon={faUserNinja} />
               Admin
@@ -34,7 +33,6 @@ const UserNav = () => {
         <a
           href=''
           onClick={(event) => {
-            console.log('menupoint', menu)
             event.preventDefault()
             setMenu(!menu)
           }}
@@ -61,9 +59,7 @@ const UserNav = () => {
 
       <style jsx>{`
         .usermenu {
-          right: 0;
-          top: 100%;
-
+          padding: 1em 0.3em;
           color: ${theme.colors.mobileNav};
           background-color: ${theme.colors.mobileNavBackground};
           align-content: end;
@@ -71,6 +67,14 @@ const UserNav = () => {
         .usermenu :global(a) {
           color: ${theme.colors.mobileNav};
         }
+        @media (min-width: ${theme.fullsize}) {
+          .usermenu {
+            position: absolute;
+            right: 0;
+            top: 100%;
+            padding: 1em;
+          }
+        }
       `}</style>
     </>
   )

+ 1 - 8
frontend/tsconfig.json

@@ -18,12 +18,5 @@
     "isolatedModules": true
   },
   "exclude": ["node_modules"],
-  "include": [
-    "next-env.d.ts",
-    "**/*.ts",
-    "**/*.tsx",
-    "lib/apollo.js",
-    "pages/_app.tsx",
-    "src/lib/apollo.js"
-  ]
+  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "pages/_app.tsx"]
 }

File diff suppressed because it is too large
+ 909 - 0
package-lock.json


+ 3 - 1
package.json

@@ -4,7 +4,8 @@
   "description": "",
   "main": "index.js",
   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "codegen": "graphql-codegen"
   },
   "repository": {
     "type": "git",
@@ -18,6 +19,7 @@
     "@graphql-codegen/typescript": "^1.9.1",
     "@graphql-codegen/typescript-operations": "^1.9.1",
     "@graphql-codegen/typescript-react-apollo": "^1.9.1",
+    "@graphql-codegen/typescript-resolvers": "1.13.3",
     "apollo-codegen": "^0.20.2"
   }
 }

+ 18 - 15
proxy/nginx.conf

@@ -7,29 +7,32 @@ events {
 http{
   sendfile on;
 
-  upstream docker-backend {
-    server backend:4000;
-  }
-
-  upstream docker-frontend {
-    server frontend:3000;
-  }
-
-  proxy_set_header   Host $host;
-  proxy_set_header   X-Real-IP $remote_addr;
-  proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
-  proxy_set_header   X-Forwarded-Host $server_name;
-
   server {
     listen 8820;
 
+    location /upload_files {
+      root                /www;
+      autoindex           off;
+      sendfile_max_chunk  100k;
+    }
+
     location / {
+      proxy_pass_header  Set-Cookie;
+      proxy_set_header   Host $host;
+      proxy_set_header   X-Real-IP $remote_addr;
+      proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
+      proxy_set_header   X-Forwarded-Host $server_name;
       proxy_pass      http://frontend:3000;
       proxy_redirect  off;
     }
 
-    location /graphql/ {
-      proxy_pass      http://backend:4000/graphql/;
+    location /graphql {
+      proxy_pass_header  Set-Cookie;
+      proxy_set_header   Host $host;
+      proxy_set_header   X-Real-IP $remote_addr;
+      proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
+      proxy_set_header   X-Forwarded-Host $server_name;
+      proxy_pass      http://backend:4000/graphql;
       proxy_redirect  off;
     }
   }

Some files were not shown because too many files changed in this diff