From fa0f42d88bccd4c52c0258740360703b0ec2f6e7 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Fri, 30 Oct 2020 17:21:06 +1100 Subject: [PATCH 01/24] Wiped out the DB to get the migration to work --- .../20201029214206-rejig-schema/README.md | 188 +++++ .../20201029214206-rejig-schema/schema.prisma | 76 ++ .../20201029214206-rejig-schema/steps.json | 706 ++++++++++++++++++ .../20201030061957-rejig-schema/README.md | 91 +++ .../20201030061957-rejig-schema/schema.prisma | 76 ++ .../20201030061957-rejig-schema/steps.json | 38 + api/prisma/migrations/migrate.lock | 4 +- api/prisma/schema.prisma | 88 ++- 8 files changed, 1236 insertions(+), 31 deletions(-) create mode 100644 api/prisma/migrations/20201029214206-rejig-schema/README.md create mode 100644 api/prisma/migrations/20201029214206-rejig-schema/schema.prisma create mode 100644 api/prisma/migrations/20201029214206-rejig-schema/steps.json create mode 100644 api/prisma/migrations/20201030061957-rejig-schema/README.md create mode 100644 api/prisma/migrations/20201030061957-rejig-schema/schema.prisma create mode 100644 api/prisma/migrations/20201030061957-rejig-schema/steps.json diff --git a/api/prisma/migrations/20201029214206-rejig-schema/README.md b/api/prisma/migrations/20201029214206-rejig-schema/README.md new file mode 100644 index 0000000..3014ffa --- /dev/null +++ b/api/prisma/migrations/20201029214206-rejig-schema/README.md @@ -0,0 +1,188 @@ +# Migration `20201029214206-rejig-schema` + +This migration has been generated by Kurt Hutten at 10/30/2020, 8:42:06 AM. +You can check out the [state of the schema](./schema.prisma) after the migration. + +# explanation + +The previous schema was really just thrown together to progress with parts of the client. +No relations had been included so this change in reality can be consider the initial schema. + +## Database Steps + +```sql +CREATE TABLE "PartReaction" ( + "emote" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "partId" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + + FOREIGN KEY ("userId") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY ("partId") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE +) + +CREATE TABLE "Comment" ( + "id" TEXT NOT NULL, + "text" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + + FOREIGN KEY ("id") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY ("id") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE, +PRIMARY KEY ("id") +) + +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_Part" ( + "id" TEXT NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "code" TEXT, + "mainImage" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "authorUserName" TEXT NOT NULL DEFAULT 'irevdev', + + FOREIGN KEY ("authorUserName") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, +PRIMARY KEY ("title","authorUserName") +); +INSERT INTO "new_Part" ("id", "title", "description", "mainImage", "createdAt", "code") SELECT "id", "title", "description", "mainImage", "createdAt", "code" FROM "Part"; +DROP TABLE "Part"; +ALTER TABLE "new_Part" RENAME TO "Part"; +CREATE UNIQUE INDEX "Part.id_unique" ON "Part"("id"); +CREATE UNIQUE INDEX "Part.title_authorUserName_unique" ON "Part"("title", "authorUserName"); +CREATE TABLE "new_User" ( + "userName" TEXT NOT NULL DEFAULT 'irevdev', + "email" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + "image" TEXT, + "bio" TEXT, +PRIMARY KEY ("userName") +); +INSERT INTO "new_User" ("email", "createdAt", "updatedAt", "image", "bio") SELECT "email", "createdAt", "updatedAt", "image", "bio" FROM "User"; +DROP TABLE "User"; +ALTER TABLE "new_User" RENAME TO "User"; +CREATE UNIQUE INDEX "User.email_unique" ON "User"("email"); +PRAGMA foreign_key_check; +PRAGMA foreign_keys=ON + +CREATE UNIQUE INDEX "PartReaction.emote_userId_partId_unique" ON "PartReaction"("emote", "userId", "partId") + +PRAGMA foreign_keys=off; +DROP TABLE "Post"; +PRAGMA foreign_keys=on + +PRAGMA foreign_keys=off; +DROP TABLE "Contact"; +PRAGMA foreign_keys=on +``` + +## Changes + +```diff +diff --git schema.prisma schema.prisma +migration 20201019072122-add-simplify-user-model..20201029214206-rejig-schema +--- datamodel.dml ++++ datamodel.dml +@@ -1,48 +1,76 @@ + datasource DS { + provider = ["sqlite", "postgresql"] +- url = "***" ++ url = "***" + } + generator client { + provider = "prisma-client-js" + binaryTargets = "native" + } +-model Post { +- id Int @id @default(autoincrement()) +- title String +- body String ++// sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode ++// enum Role { ++// USER ++// ADMIN ++// } ++ ++// enum PartType { ++// CASCADESTUDIO ++// JSCAD ++// } ++ ++model User { ++ userName String @id @default("irevdev") ++ email String @unique ++ // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev ++ // maybe let netlify handle roles for now. ++ // role String @default("user") ++ + createdAt DateTime @default(now()) ++ updatedAt DateTime @updatedAt ++ ++ image String? // url maybe id or file storage service? cloudinary? ++ bio String? //mark down ++ Part Part[] ++ Reaction PartReaction[] ++ Comment Comment[] + } + model Part { +- id Int @id @default(autoincrement()) +- title String +- description String // markdown string +- code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") +- mainImage String // link to cloudinary +- createdAt DateTime @default(now()) +- // userId +- //likes, comments, reactions ++ id String @unique @default(uuid()) ++ title String ++ description String? // markdown string ++ code String? ++ mainImage String? // link to cloudinary ++ createdAt DateTime @default(now()) ++ updatedAt DateTime @default(now()) @updatedAt ++ author User @relation(fields: [authorUserName], references: [userName]) ++ authorUserName String @default("irevdev") ++ ++ Comment Comment[] ++ Reaction PartReaction[] ++ @@id([title, authorUserName]) ++ @@unique([title, authorUserName]) + } +-model Contact { +- id Int @id @default(autoincrement()) +- name String +- email String +- message String ++model PartReaction { ++ emote String // an emoji ++ userId String ++ user User @relation(fields: [userId], references: [userName]) ++ partId String ++ part Part @relation(fields: [partId], references: [id]) ++ + createdAt DateTime @default(now()) ++ updatedAt DateTime @updatedAt ++ @@unique([emote, userId, partId]) + } +-model User { +- id Int @id @default(autoincrement()) +- email String @unique +- // userName String @unique +- // issuer String @unique ++model Comment { ++ id String @id @default(uuid()) ++ text String // the comment, should I allow mark down? ++ user User @relation(fields: [id], references: [userName]) ++ part Part @relation(fields: [id], references: [id]) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +- +- image String? // url maybe id or file storage service? cloudinary? +- bio String? //mark down + } +``` + + diff --git a/api/prisma/migrations/20201029214206-rejig-schema/schema.prisma b/api/prisma/migrations/20201029214206-rejig-schema/schema.prisma new file mode 100644 index 0000000..cfd2660 --- /dev/null +++ b/api/prisma/migrations/20201029214206-rejig-schema/schema.prisma @@ -0,0 +1,76 @@ +datasource DS { + provider = ["sqlite", "postgresql"] + url = "***" +} + +generator client { + provider = "prisma-client-js" + binaryTargets = "native" +} + +// sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode +// enum Role { +// USER +// ADMIN +// } + +// enum PartType { +// CASCADESTUDIO +// JSCAD +// } + +model User { + userName String @id @default(uuid()) + email String @unique + // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev + // maybe let netlify handle roles for now. + // role String @default("user") + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + image String? // url maybe id or file storage service? cloudinary? + bio String? //mark down + Part Part[] + Reaction PartReaction[] + Comment Comment[] +} + +model Part { + id String @unique @default(uuid()) + title String + description String? // markdown string + code String? + mainImage String? // link to cloudinary + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + author User @relation(fields: [authorUserName], references: [userName]) + authorUserName String + + Comment Comment[] + Reaction PartReaction[] + @@id([title, authorUserName]) + @@unique([title, authorUserName]) +} + +model PartReaction { + emote String // an emoji + userId String + user User @relation(fields: [userId], references: [userName]) + partId String + part Part @relation(fields: [partId], references: [id]) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + @@unique([emote, userId, partId]) +} + +model Comment { + id String @id @default(uuid()) + text String // the comment, should I allow mark down? + user User @relation(fields: [id], references: [userName]) + part Part @relation(fields: [id], references: [id]) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} diff --git a/api/prisma/migrations/20201029214206-rejig-schema/steps.json b/api/prisma/migrations/20201029214206-rejig-schema/steps.json new file mode 100644 index 0000000..a0b86eb --- /dev/null +++ b/api/prisma/migrations/20201029214206-rejig-schema/steps.json @@ -0,0 +1,706 @@ +{ + "version": "0.3.14-fixed", + "steps": [ + { + "tag": "CreateModel", + "model": "PartReaction" + }, + { + "tag": "CreateField", + "model": "PartReaction", + "field": "emote", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateField", + "model": "PartReaction", + "field": "userId", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateField", + "model": "PartReaction", + "field": "user", + "type": "User", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "user" + }, + "directive": "relation" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "user" + }, + "directive": "relation" + }, + "argument": "fields", + "value": "[userId]" + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "user" + }, + "directive": "relation" + }, + "argument": "references", + "value": "[userName]" + }, + { + "tag": "CreateField", + "model": "PartReaction", + "field": "partId", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateField", + "model": "PartReaction", + "field": "part", + "type": "Part", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "part" + }, + "directive": "relation" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "part" + }, + "directive": "relation" + }, + "argument": "fields", + "value": "[partId]" + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "part" + }, + "directive": "relation" + }, + "argument": "references", + "value": "[id]" + }, + { + "tag": "CreateField", + "model": "PartReaction", + "field": "createdAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "createdAt" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "createdAt" + }, + "directive": "default" + }, + "argument": "", + "value": "now()" + }, + { + "tag": "CreateField", + "model": "PartReaction", + "field": "updatedAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "updatedAt" + }, + "directive": "updatedAt" + } + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Model", + "model": "PartReaction", + "arguments": [ + { + "name": "", + "value": "[emote, userId, partId]" + } + ] + }, + "directive": "unique" + } + }, + { + "tag": "CreateModel", + "model": "Comment" + }, + { + "tag": "CreateField", + "model": "Comment", + "field": "id", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Comment", + "field": "id" + }, + "directive": "id" + } + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Comment", + "field": "id" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Comment", + "field": "id" + }, + "directive": "default" + }, + "argument": "", + "value": "uuid()" + }, + { + "tag": "CreateField", + "model": "Comment", + "field": "text", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateField", + "model": "Comment", + "field": "user", + "type": "User", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Comment", + "field": "user" + }, + "directive": "relation" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Comment", + "field": "user" + }, + "directive": "relation" + }, + "argument": "fields", + "value": "[id]" + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Comment", + "field": "user" + }, + "directive": "relation" + }, + "argument": "references", + "value": "[userName]" + }, + { + "tag": "CreateField", + "model": "Comment", + "field": "part", + "type": "Part", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Comment", + "field": "part" + }, + "directive": "relation" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Comment", + "field": "part" + }, + "directive": "relation" + }, + "argument": "fields", + "value": "[id]" + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Comment", + "field": "part" + }, + "directive": "relation" + }, + "argument": "references", + "value": "[id]" + }, + { + "tag": "CreateField", + "model": "Comment", + "field": "createdAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Comment", + "field": "createdAt" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Comment", + "field": "createdAt" + }, + "directive": "default" + }, + "argument": "", + "value": "now()" + }, + { + "tag": "CreateField", + "model": "Comment", + "field": "updatedAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Comment", + "field": "updatedAt" + }, + "directive": "updatedAt" + } + }, + { + "tag": "DeleteModel", + "model": "Post" + }, + { + "tag": "DeleteModel", + "model": "Contact" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "updatedAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "updatedAt" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "updatedAt" + }, + "directive": "default" + }, + "argument": "", + "value": "now()" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "updatedAt" + }, + "directive": "updatedAt" + } + }, + { + "tag": "CreateField", + "model": "Part", + "field": "author", + "type": "User", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "author" + }, + "directive": "relation" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "author" + }, + "directive": "relation" + }, + "argument": "fields", + "value": "[authorUserName]" + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "author" + }, + "directive": "relation" + }, + "argument": "references", + "value": "[userName]" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "authorUserName", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "authorUserName" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "authorUserName" + }, + "directive": "default" + }, + "argument": "", + "value": "\"irevdev\"" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "Comment", + "type": "Comment", + "arity": "List" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "Reaction", + "type": "PartReaction", + "arity": "List" + }, + { + "tag": "UpdateField", + "model": "Part", + "field": "id", + "type": "String" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "id" + }, + "directive": "unique" + } + }, + { + "tag": "UpdateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "id" + }, + "directive": "default" + }, + "argument": "", + "newValue": "uuid()" + }, + { + "tag": "DeleteDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "id" + }, + "directive": "id" + } + }, + { + "tag": "UpdateField", + "model": "Part", + "field": "description", + "arity": "Optional" + }, + { + "tag": "UpdateField", + "model": "Part", + "field": "mainImage", + "arity": "Optional" + }, + { + "tag": "UpdateField", + "model": "Part", + "field": "code", + "arity": "Optional" + }, + { + "tag": "DeleteDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "code" + }, + "directive": "default" + } + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Model", + "model": "Part" + }, + "directive": "id" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Model", + "model": "Part" + }, + "directive": "id" + }, + "argument": "", + "value": "[title, authorUserName]" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Model", + "model": "Part", + "arguments": [ + { + "name": "", + "value": "[title, authorUserName]" + } + ] + }, + "directive": "unique" + } + }, + { + "tag": "CreateField", + "model": "User", + "field": "userName", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "userName" + }, + "directive": "id" + } + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "userName" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "User", + "field": "userName" + }, + "directive": "default" + }, + "argument": "", + "value": "\"irevdev\"" + }, + { + "tag": "CreateField", + "model": "User", + "field": "Part", + "type": "Part", + "arity": "List" + }, + { + "tag": "CreateField", + "model": "User", + "field": "Reaction", + "type": "PartReaction", + "arity": "List" + }, + { + "tag": "CreateField", + "model": "User", + "field": "Comment", + "type": "Comment", + "arity": "List" + }, + { + "tag": "DeleteField", + "model": "User", + "field": "id" + } + ] +} \ No newline at end of file diff --git a/api/prisma/migrations/20201030061957-rejig-schema/README.md b/api/prisma/migrations/20201030061957-rejig-schema/README.md new file mode 100644 index 0000000..45e5d74 --- /dev/null +++ b/api/prisma/migrations/20201030061957-rejig-schema/README.md @@ -0,0 +1,91 @@ +# Migration `20201030061957-rejig-schema` + +This migration has been generated by Kurt Hutten at 10/30/2020, 5:19:57 PM. +You can check out the [state of the schema](./schema.prisma) after the migration. + +## Database Steps + +```sql +CREATE TABLE "User" ( + "userName" TEXT NOT NULL, + "email" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + "image" TEXT, + "bio" TEXT, +PRIMARY KEY ("userName") +) + +CREATE TABLE "Part" ( + "id" TEXT NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "code" TEXT, + "mainImage" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + "authorUserName" TEXT NOT NULL, + + FOREIGN KEY ("authorUserName") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, +PRIMARY KEY ("title","authorUserName") +) + +CREATE TABLE "PartReaction" ( + "emote" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "partId" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + + FOREIGN KEY ("userId") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY ("partId") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE +) + +CREATE TABLE "Comment" ( + "id" TEXT NOT NULL, + "text" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + + FOREIGN KEY ("id") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY ("id") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE, +PRIMARY KEY ("id") +) + +CREATE UNIQUE INDEX "User.email_unique" ON "User"("email") + +CREATE UNIQUE INDEX "Part.id_unique" ON "Part"("id") + +CREATE UNIQUE INDEX "Part.title_authorUserName_unique" ON "Part"("title", "authorUserName") + +CREATE UNIQUE INDEX "PartReaction.emote_userId_partId_unique" ON "PartReaction"("emote", "userId", "partId") +``` + +## Changes + +```diff +diff --git schema.prisma schema.prisma +migration 20201029214206-rejig-schema..20201030061957-rejig-schema +--- datamodel.dml ++++ datamodel.dml +@@ -1,7 +1,7 @@ + datasource DS { + provider = ["sqlite", "postgresql"] +- url = "***" ++ url = "***" + } + generator client { + provider = "prisma-client-js" +@@ -19,9 +19,9 @@ + // JSCAD + // } + model User { +- userName String @id @default(uuid()) ++ userName String @id + email String @unique + // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev + // maybe let netlify handle roles for now. + // role String @default("user") +``` + + diff --git a/api/prisma/migrations/20201030061957-rejig-schema/schema.prisma b/api/prisma/migrations/20201030061957-rejig-schema/schema.prisma new file mode 100644 index 0000000..5515849 --- /dev/null +++ b/api/prisma/migrations/20201030061957-rejig-schema/schema.prisma @@ -0,0 +1,76 @@ +datasource DS { + provider = ["sqlite", "postgresql"] + url = "***" +} + +generator client { + provider = "prisma-client-js" + binaryTargets = "native" +} + +// sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode +// enum Role { +// USER +// ADMIN +// } + +// enum PartType { +// CASCADESTUDIO +// JSCAD +// } + +model User { + userName String @id + email String @unique + // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev + // maybe let netlify handle roles for now. + // role String @default("user") + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + image String? // url maybe id or file storage service? cloudinary? + bio String? //mark down + Part Part[] + Reaction PartReaction[] + Comment Comment[] +} + +model Part { + id String @unique @default(uuid()) + title String + description String? // markdown string + code String? + mainImage String? // link to cloudinary + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + author User @relation(fields: [authorUserName], references: [userName]) + authorUserName String + + Comment Comment[] + Reaction PartReaction[] + @@id([title, authorUserName]) + @@unique([title, authorUserName]) +} + +model PartReaction { + emote String // an emoji + userId String + user User @relation(fields: [userId], references: [userName]) + partId String + part Part @relation(fields: [partId], references: [id]) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + @@unique([emote, userId, partId]) +} + +model Comment { + id String @id @default(uuid()) + text String // the comment, should I allow mark down? + user User @relation(fields: [id], references: [userName]) + part Part @relation(fields: [id], references: [id]) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} diff --git a/api/prisma/migrations/20201030061957-rejig-schema/steps.json b/api/prisma/migrations/20201030061957-rejig-schema/steps.json new file mode 100644 index 0000000..17d5f9e --- /dev/null +++ b/api/prisma/migrations/20201030061957-rejig-schema/steps.json @@ -0,0 +1,38 @@ +{ + "version": "0.3.14-fixed", + "steps": [ + { + "tag": "DeleteDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "updatedAt" + }, + "directive": "default" + } + }, + { + "tag": "DeleteDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "authorUserName" + }, + "directive": "default" + } + }, + { + "tag": "DeleteDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "userName" + }, + "directive": "default" + } + } + ] +} \ No newline at end of file diff --git a/api/prisma/migrations/migrate.lock b/api/prisma/migrations/migrate.lock index dddc03e..66735c0 100644 --- a/api/prisma/migrations/migrate.lock +++ b/api/prisma/migrations/migrate.lock @@ -6,4 +6,6 @@ 20201011082558-add-code-not-needed-upon-create 20201011095227-create-contact 20201018233330-add-simple-user-model -20201019072122-add-simplify-user-model \ No newline at end of file +20201019072122-add-simplify-user-model +20201029214206-rejig-schema +20201030061957-rejig-schema \ No newline at end of file diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index baecb2a..a786c36 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -8,41 +8,69 @@ generator client { binaryTargets = "native" } -model Post { - id Int @id @default(autoincrement()) - title String - body String - createdAt DateTime @default(now()) -} +// sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode +// enum Role { +// USER +// ADMIN +// } -model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string - code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -} - -model Contact { - id Int @id @default(autoincrement()) - name String - email String - message String - createdAt DateTime @default(now()) -} +// enum PartType { +// CASCADESTUDIO +// JSCAD +// } model User { - id Int @id @default(autoincrement()) - email String @unique - // userName String @unique - // issuer String @unique + userName String @id + email String @unique + // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev + // maybe let netlify handle roles for now. + // role String @default("user") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - image String? // url maybe id or file storage service? cloudinary? - bio String? //mark down + image String? // url maybe id or file storage service? cloudinary? + bio String? //mark down + Part Part[] + Reaction PartReaction[] + Comment Comment[] +} + +model Part { + id String @unique @default(uuid()) + title String + description String? // markdown string + code String? + mainImage String? // link to cloudinary + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + author User @relation(fields: [authorUserName], references: [userName]) + authorUserName String + + Comment Comment[] + Reaction PartReaction[] + @@id([title, authorUserName]) + @@unique([title, authorUserName]) +} + +model PartReaction { + emote String // an emoji + userId String + user User @relation(fields: [userId], references: [userName]) + partId String + part Part @relation(fields: [partId], references: [id]) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + @@unique([emote, userId, partId]) +} + +model Comment { + id String @id @default(uuid()) + text String // the comment, should I allow mark down? + user User @relation(fields: [id], references: [userName]) + part Part @relation(fields: [id], references: [id]) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } From 55f9dfd6dea2ad6e0f9ea9a47d07b39cee7e594f Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Sun, 1 Nov 2020 18:05:19 +1100 Subject: [PATCH 02/24] Wipe slate clean --- api/src/graphql/contacts.sdl.js | 29 ----- api/src/graphql/parts.sdl.js | 35 ------ api/src/graphql/posts.sdl.js | 29 ----- api/src/graphql/users.sdl.js | 35 ------ api/src/services/contacts/contacts.js | 24 ---- api/src/services/contacts/contacts.test.js | 9 -- api/src/services/parts/parts.js | 30 ----- api/src/services/parts/parts.test.js | 9 -- api/src/services/posts/posts.js | 34 ------ api/src/services/posts/posts.test.js | 9 -- api/src/services/users/users.js | 40 ------- api/src/services/users/users.test.js | 9 -- web/src/Routes.js | 24 +--- web/src/components/BlogPost/BlogPost.js | 16 --- .../components/BlogPost/BlogPost.stories.js | 7 -- web/src/components/BlogPost/BlogPost.test.js | 11 -- .../components/BlogPostCell/BlogPostCell.js | 22 ---- .../BlogPostCell/BlogPostCell.mock.js | 6 - .../BlogPostCell/BlogPostCell.stories.js | 20 ---- .../BlogPostCell/BlogPostCell.test.js | 26 ----- .../components/BlogPostsCell/BlogPostsCell.js | 23 ---- .../BlogPostsCell/BlogPostsCell.mock.js | 6 - .../BlogPostsCell/BlogPostsCell.stories.js | 20 ---- .../BlogPostsCell/BlogPostsCell.test.js | 26 ----- .../components/EditPartCell/EditPartCell.js | 35 ------ .../components/EditPostCell/EditPostCell.js | 48 -------- .../components/EditUserCell/EditUserCell.js | 50 -------- web/src/components/NewPart/NewPart.js | 38 ------ web/src/components/NewPost/NewPost.js | 38 ------ web/src/components/NewUser/NewUser.js | 38 ------ web/src/components/Part/Part.js | 110 ------------------ web/src/components/PartCell/PartCell.js | 32 ----- web/src/components/PartForm/PartForm.js | 93 --------------- web/src/components/Parts/Parts.js | 89 -------------- web/src/components/PartsCell/PartsCell.js | 33 ------ web/src/components/Post/Post.js | 95 --------------- web/src/components/PostCell/PostCell.js | 20 ---- web/src/components/PostForm/PostForm.js | 67 ----------- web/src/components/Posts/Posts.js | 105 ----------------- web/src/components/PostsCell/PostsCell.js | 31 ----- web/src/components/User/User.js | 109 ----------------- web/src/components/UserCell/UserCell.js | 22 ---- web/src/components/UserForm/UserForm.js | 79 ------------- web/src/components/UserPart/UserPart.js | 16 --- web/src/components/Users/Users.js | 109 ----------------- web/src/components/UsersCell/UsersCell.js | 33 ------ web/src/index.html | 2 +- web/src/layouts/BlogLayout/BlogLayout.js | 24 ---- .../layouts/BlogLayout/BlogLayout.stories.js | 7 -- web/src/layouts/BlogLayout/BlogLayout.test.js | 11 -- web/src/layouts/PartsLayout/PartsLayout.js | 11 -- web/src/layouts/PostsLayout/PostsLayout.js | 23 ---- web/src/pages/AboutPage/AboutPage.js | 19 --- web/src/pages/AboutPage/AboutPage.stories.js | 7 -- web/src/pages/AboutPage/AboutPage.test.js | 11 -- web/src/pages/BlogPostPage/BlogPostPage.js | 12 -- .../BlogPostPage/BlogPostPage.stories.js | 7 -- .../pages/BlogPostPage/BlogPostPage.test.js | 11 -- web/src/pages/ContactPage/ContactPage.js | 59 ---------- .../pages/ContactPage/ContactPage.stories.js | 7 -- web/src/pages/ContactPage/ContactPage.test.js | 11 -- web/src/pages/EditPartPage/EditPartPage.js | 12 -- web/src/pages/EditPostPage/EditPostPage.js | 12 -- web/src/pages/EditUserPage/EditUserPage.js | 12 -- .../pages/IdePartPage/IdePartPage.stories.js | 7 -- web/src/pages/NewPartPage/NewPartPage.js | 12 -- web/src/pages/NewPostPage/NewPostPage.js | 12 -- web/src/pages/NewUserPage/NewUserPage.js | 12 -- web/src/pages/PartPage/PartPage.js | 15 --- web/src/pages/PartsPage/PartsPage.js | 15 --- web/src/pages/PostPage/PostPage.js | 12 -- web/src/pages/PostsPage/PostsPage.js | 15 --- web/src/pages/UserPage/UserPage.js | 12 -- web/src/pages/UsersPage/UsersPage.js | 12 -- 74 files changed, 2 insertions(+), 2169 deletions(-) delete mode 100644 api/src/graphql/contacts.sdl.js delete mode 100644 api/src/graphql/parts.sdl.js delete mode 100644 api/src/graphql/posts.sdl.js delete mode 100644 api/src/graphql/users.sdl.js delete mode 100644 api/src/services/contacts/contacts.js delete mode 100644 api/src/services/contacts/contacts.test.js delete mode 100644 api/src/services/parts/parts.js delete mode 100644 api/src/services/parts/parts.test.js delete mode 100644 api/src/services/posts/posts.js delete mode 100644 api/src/services/posts/posts.test.js delete mode 100644 api/src/services/users/users.js delete mode 100644 api/src/services/users/users.test.js delete mode 100644 web/src/components/BlogPost/BlogPost.js delete mode 100644 web/src/components/BlogPost/BlogPost.stories.js delete mode 100644 web/src/components/BlogPost/BlogPost.test.js delete mode 100644 web/src/components/BlogPostCell/BlogPostCell.js delete mode 100644 web/src/components/BlogPostCell/BlogPostCell.mock.js delete mode 100644 web/src/components/BlogPostCell/BlogPostCell.stories.js delete mode 100644 web/src/components/BlogPostCell/BlogPostCell.test.js delete mode 100644 web/src/components/BlogPostsCell/BlogPostsCell.js delete mode 100644 web/src/components/BlogPostsCell/BlogPostsCell.mock.js delete mode 100644 web/src/components/BlogPostsCell/BlogPostsCell.stories.js delete mode 100644 web/src/components/BlogPostsCell/BlogPostsCell.test.js delete mode 100644 web/src/components/EditPartCell/EditPartCell.js delete mode 100644 web/src/components/EditPostCell/EditPostCell.js delete mode 100644 web/src/components/EditUserCell/EditUserCell.js delete mode 100644 web/src/components/NewPart/NewPart.js delete mode 100644 web/src/components/NewPost/NewPost.js delete mode 100644 web/src/components/NewUser/NewUser.js delete mode 100644 web/src/components/Part/Part.js delete mode 100644 web/src/components/PartCell/PartCell.js delete mode 100644 web/src/components/PartForm/PartForm.js delete mode 100644 web/src/components/Parts/Parts.js delete mode 100644 web/src/components/PartsCell/PartsCell.js delete mode 100644 web/src/components/Post/Post.js delete mode 100644 web/src/components/PostCell/PostCell.js delete mode 100644 web/src/components/PostForm/PostForm.js delete mode 100644 web/src/components/Posts/Posts.js delete mode 100644 web/src/components/PostsCell/PostsCell.js delete mode 100644 web/src/components/User/User.js delete mode 100644 web/src/components/UserCell/UserCell.js delete mode 100644 web/src/components/UserForm/UserForm.js delete mode 100644 web/src/components/UserPart/UserPart.js delete mode 100644 web/src/components/Users/Users.js delete mode 100644 web/src/components/UsersCell/UsersCell.js delete mode 100644 web/src/layouts/BlogLayout/BlogLayout.js delete mode 100644 web/src/layouts/BlogLayout/BlogLayout.stories.js delete mode 100644 web/src/layouts/BlogLayout/BlogLayout.test.js delete mode 100644 web/src/layouts/PartsLayout/PartsLayout.js delete mode 100644 web/src/layouts/PostsLayout/PostsLayout.js delete mode 100644 web/src/pages/AboutPage/AboutPage.js delete mode 100644 web/src/pages/AboutPage/AboutPage.stories.js delete mode 100644 web/src/pages/AboutPage/AboutPage.test.js delete mode 100644 web/src/pages/BlogPostPage/BlogPostPage.js delete mode 100644 web/src/pages/BlogPostPage/BlogPostPage.stories.js delete mode 100644 web/src/pages/BlogPostPage/BlogPostPage.test.js delete mode 100644 web/src/pages/ContactPage/ContactPage.js delete mode 100644 web/src/pages/ContactPage/ContactPage.stories.js delete mode 100644 web/src/pages/ContactPage/ContactPage.test.js delete mode 100644 web/src/pages/EditPartPage/EditPartPage.js delete mode 100644 web/src/pages/EditPostPage/EditPostPage.js delete mode 100644 web/src/pages/EditUserPage/EditUserPage.js delete mode 100644 web/src/pages/IdePartPage/IdePartPage.stories.js delete mode 100644 web/src/pages/NewPartPage/NewPartPage.js delete mode 100644 web/src/pages/NewPostPage/NewPostPage.js delete mode 100644 web/src/pages/NewUserPage/NewUserPage.js delete mode 100644 web/src/pages/PartPage/PartPage.js delete mode 100644 web/src/pages/PartsPage/PartsPage.js delete mode 100644 web/src/pages/PostPage/PostPage.js delete mode 100644 web/src/pages/PostsPage/PostsPage.js delete mode 100644 web/src/pages/UserPage/UserPage.js delete mode 100644 web/src/pages/UsersPage/UsersPage.js diff --git a/api/src/graphql/contacts.sdl.js b/api/src/graphql/contacts.sdl.js deleted file mode 100644 index c4153b6..0000000 --- a/api/src/graphql/contacts.sdl.js +++ /dev/null @@ -1,29 +0,0 @@ -export const schema = gql` - type Contact { - id: Int! - name: String! - email: String! - message: String! - createdAt: DateTime! - } - - type Query { - contacts: [Contact!]! - } - - input CreateContactInput { - name: String! - email: String! - message: String! - } - - input UpdateContactInput { - name: String - email: String - message: String - } - - type Mutation { - createContact(input: CreateContactInput!): Contact - } -` diff --git a/api/src/graphql/parts.sdl.js b/api/src/graphql/parts.sdl.js deleted file mode 100644 index bec69fa..0000000 --- a/api/src/graphql/parts.sdl.js +++ /dev/null @@ -1,35 +0,0 @@ -export const schema = gql` - type Part { - id: Int! - title: String! - description: String! - code: String! - mainImage: String! - createdAt: DateTime! - } - - type Query { - parts: [Part!]! - part(id: Int!): Part - } - - input CreatePartInput { - title: String! - description: String! - code: String - mainImage: String - } - - input UpdatePartInput { - title: String - description: String - code: String - mainImage: String - } - - type Mutation { - createPart(input: CreatePartInput!): Part! - updatePart(id: Int!, input: UpdatePartInput!): Part! - deletePart(id: Int!): Part! - } -` diff --git a/api/src/graphql/posts.sdl.js b/api/src/graphql/posts.sdl.js deleted file mode 100644 index ad384ff..0000000 --- a/api/src/graphql/posts.sdl.js +++ /dev/null @@ -1,29 +0,0 @@ -export const schema = gql` - type Post { - id: Int! - title: String! - body: String! - createdAt: DateTime! - } - - type Query { - posts: [Post!]! - post(id: Int!): Post - } - - input CreatePostInput { - title: String! - body: String! - } - - input UpdatePostInput { - title: String - body: String - } - - type Mutation { - createPost(input: CreatePostInput!): Post! - updatePost(id: Int!, input: UpdatePostInput!): Post! - deletePost(id: Int!): Post! - } -` diff --git a/api/src/graphql/users.sdl.js b/api/src/graphql/users.sdl.js deleted file mode 100644 index 366075d..0000000 --- a/api/src/graphql/users.sdl.js +++ /dev/null @@ -1,35 +0,0 @@ -export const schema = gql` - type User { - id: Int! - email: String! - createdAt: DateTime! - updatedAt: DateTime! - image: String - bio: String - } - - type Query { - users: [User!]! - user(id: Int!): User - } - - input CreateUserInput { - email: String! - # issuer: String! - image: String - bio: String - } - - input UpdateUserInput { - email: String - # issuer: String - image: String - bio: String - } - - type Mutation { - createUser(input: CreateUserInput!): User! - updateUser(id: Int!, input: UpdateUserInput!): User! - deleteUser(id: Int!): User! - } -` diff --git a/api/src/services/contacts/contacts.js b/api/src/services/contacts/contacts.js deleted file mode 100644 index 3481975..0000000 --- a/api/src/services/contacts/contacts.js +++ /dev/null @@ -1,24 +0,0 @@ -import { UserInputError } from '@redwoodjs/api' - -import { db } from 'src/lib/db' - - -const validate = (input) => { - if (input.email && !input.email.match(/[^@]+@[^.]+\..+/)) { - throw new UserInputError("Can't create new contact", { - messages: { - email: ['is not formatted like an email address'], - }, - }) - } -} - -export const contacts = () => { - return db.contact.findMany() -} - -export const createContact = ({ input }) => { - - validate(input) - return db.contact.create({ data: input }) -} diff --git a/api/src/services/contacts/contacts.test.js b/api/src/services/contacts/contacts.test.js deleted file mode 100644 index fbbbc1e..0000000 --- a/api/src/services/contacts/contacts.test.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -import { contacts } from './contacts' -*/ - -describe('contacts', () => { - it('returns true', () => { - expect(true).toBe(true) - }) -}) diff --git a/api/src/services/parts/parts.js b/api/src/services/parts/parts.js deleted file mode 100644 index 98c6243..0000000 --- a/api/src/services/parts/parts.js +++ /dev/null @@ -1,30 +0,0 @@ -import { db } from 'src/lib/db' - -export const parts = () => { - return db.part.findMany() -} - -export const part = ({ id }) => { - return db.part.findOne({ - where: { id }, - }) -} - -export const createPart = ({ input }) => { - return db.part.create({ - data: input, - }) -} - -export const updatePart = ({ id, input }) => { - return db.part.update({ - data: input, - where: { id }, - }) -} - -export const deletePart = ({ id }) => { - return db.part.delete({ - where: { id }, - }) -} diff --git a/api/src/services/parts/parts.test.js b/api/src/services/parts/parts.test.js deleted file mode 100644 index e8b80ce..0000000 --- a/api/src/services/parts/parts.test.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -import { parts } from './parts' -*/ - -describe('parts', () => { - it('returns true', () => { - expect(true).toBe(true) - }) -}) diff --git a/api/src/services/posts/posts.js b/api/src/services/posts/posts.js deleted file mode 100644 index 8912a71..0000000 --- a/api/src/services/posts/posts.js +++ /dev/null @@ -1,34 +0,0 @@ -import { db } from 'src/lib/db' -import { requireAuth } from 'src/lib/auth' - -export const posts = () => { - return db.post.findMany() -} - -export const post = ({ id }) => { - return db.post.findOne({ - where: { id }, - }) -} - -export const createPost = ({ input }) => { - requireAuth() - return db.post.create({ - data: input, - }) -} - -export const updatePost = ({ id, input }) => { - requireAuth() - return db.post.update({ - data: input, - where: { id }, - }) -} - -export const deletePost = ({ id }) => { - requireAuth() - return db.post.delete({ - where: { id }, - }) -} diff --git a/api/src/services/posts/posts.test.js b/api/src/services/posts/posts.test.js deleted file mode 100644 index f23483a..0000000 --- a/api/src/services/posts/posts.test.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -import { posts } from './posts' -*/ - -describe('posts', () => { - it('returns true', () => { - expect(true).toBe(true) - }) -}) diff --git a/api/src/services/users/users.js b/api/src/services/users/users.js deleted file mode 100644 index 3d3675c..0000000 --- a/api/src/services/users/users.js +++ /dev/null @@ -1,40 +0,0 @@ -import { db } from 'src/lib/db' -import { requireAuth } from 'src/lib/auth' - -export const users = () => { - requireAuth({ role: 'admin' }) - return db.user.findMany() -} - -export const user = ({ id }) => { - requireAuth() - return db.user.findOne({ - where: { id }, - }) -} - -export const createUser = ({ input }) => { - requireAuth({ role: 'admin' }) - return createUserInsecure({input}) -} - -export const createUserInsecure = ({ input }) => { - return db.user.create({ - data: input, - }) -} - -export const updateUser = ({ id, input }) => { - requireAuth() - return db.user.update({ - data: input, - where: { id }, - }) -} - -export const deleteUser = ({ id }) => { - requireAuth({ role: 'admin' }) - return db.user.delete({ - where: { id }, - }) -} diff --git a/api/src/services/users/users.test.js b/api/src/services/users/users.test.js deleted file mode 100644 index bac7cb4..0000000 --- a/api/src/services/users/users.test.js +++ /dev/null @@ -1,9 +0,0 @@ -/* -import { users } from './users' -*/ - -describe('users', () => { - it('returns true', () => { - expect(true).toBe(true) - }) -}) diff --git a/web/src/Routes.js b/web/src/Routes.js index 8255681..c9ebd82 100644 --- a/web/src/Routes.js +++ b/web/src/Routes.js @@ -12,30 +12,8 @@ import { Router, Route, Private } from '@redwoodjs/router' const Routes = () => { return ( - {/* TODO add add min role to users and users/new */} - - - - - - - - - - - - - - - - - - - - - - + ) diff --git a/web/src/components/BlogPost/BlogPost.js b/web/src/components/BlogPost/BlogPost.js deleted file mode 100644 index 524ee4b..0000000 --- a/web/src/components/BlogPost/BlogPost.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' - -const BlogPost = ({ post }) => { - return ( -
-
-

- {post.title} -

-
-
{post.body}
-
- ) -} - -export default BlogPost \ No newline at end of file diff --git a/web/src/components/BlogPost/BlogPost.stories.js b/web/src/components/BlogPost/BlogPost.stories.js deleted file mode 100644 index 03e9f5f..0000000 --- a/web/src/components/BlogPost/BlogPost.stories.js +++ /dev/null @@ -1,7 +0,0 @@ -import BlogPost from './BlogPost' - -export const generated = () => { - return -} - -export default { title: 'Components/BlogPost' } diff --git a/web/src/components/BlogPost/BlogPost.test.js b/web/src/components/BlogPost/BlogPost.test.js deleted file mode 100644 index 87f976f..0000000 --- a/web/src/components/BlogPost/BlogPost.test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { render } from '@redwoodjs/testing' - -import BlogPost from './BlogPost' - -describe('BlogPost', () => { - it('renders successfully', () => { - expect(() => { - render() - }).not.toThrow() - }) -}) diff --git a/web/src/components/BlogPostCell/BlogPostCell.js b/web/src/components/BlogPostCell/BlogPostCell.js deleted file mode 100644 index fd7987f..0000000 --- a/web/src/components/BlogPostCell/BlogPostCell.js +++ /dev/null @@ -1,22 +0,0 @@ -import BlogPost from 'src/components/BlogPost' - -export const QUERY = gql` - query BlogPostQuery($id: Int!) { - post(id: $id) { - id - title - body - createdAt - } - } -` - -export const Loading = () =>
Loading...
- -export const Empty = () =>
Empty
- -export const Failure = ({ error }) =>
Error: {error.message}
- -export const Success = ({ post }) => { - return -} diff --git a/web/src/components/BlogPostCell/BlogPostCell.mock.js b/web/src/components/BlogPostCell/BlogPostCell.mock.js deleted file mode 100644 index c689622..0000000 --- a/web/src/components/BlogPostCell/BlogPostCell.mock.js +++ /dev/null @@ -1,6 +0,0 @@ -// Define your own mock data here: -export const standard = (/* vars, { ctx, req } */) => ({ - blogPost: { - id: 42, - }, -}) diff --git a/web/src/components/BlogPostCell/BlogPostCell.stories.js b/web/src/components/BlogPostCell/BlogPostCell.stories.js deleted file mode 100644 index 597ce5f..0000000 --- a/web/src/components/BlogPostCell/BlogPostCell.stories.js +++ /dev/null @@ -1,20 +0,0 @@ -import { Loading, Empty, Failure, Success } from './BlogPostCell' -import { standard } from './BlogPostCell.mock' - -export const loading = () => { - return Loading ? : null -} - -export const empty = () => { - return Empty ? : null -} - -export const failure = () => { - return Failure ? : null -} - -export const success = () => { - return Success ? : null -} - -export default { title: 'Cells/BlogPostCell' } diff --git a/web/src/components/BlogPostCell/BlogPostCell.test.js b/web/src/components/BlogPostCell/BlogPostCell.test.js deleted file mode 100644 index 61adcd6..0000000 --- a/web/src/components/BlogPostCell/BlogPostCell.test.js +++ /dev/null @@ -1,26 +0,0 @@ -import { render, screen } from '@redwoodjs/testing' -import { Loading, Empty, Failure, Success } from './BlogPostCell' -import { standard } from './BlogPostCell.mock' - -describe('BlogPostCell', () => { - test('Loading renders successfully', () => { - render() - // Use screen.debug() to see output - expect(screen.getByText('Loading...')).toBeInTheDocument() - }) - - test('Empty renders successfully', async () => { - render() - expect(screen.getByText('Empty')).toBeInTheDocument() - }) - - test('Failure renders successfully', async () => { - render() - expect(screen.getByText(/Oh no/i)).toBeInTheDocument() - }) - - test('Success renders successfully', async () => { - render() - expect(screen.getByText(/42/i)).toBeInTheDocument() - }) -}) diff --git a/web/src/components/BlogPostsCell/BlogPostsCell.js b/web/src/components/BlogPostsCell/BlogPostsCell.js deleted file mode 100644 index 1d4cb61..0000000 --- a/web/src/components/BlogPostsCell/BlogPostsCell.js +++ /dev/null @@ -1,23 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' -import BlogPost from 'src/components/BlogPost' - -export const QUERY = gql` - query BlogPostsQuery { - posts { - id - title - body - createdAt - } - } -` - -export const Loading = () =>
Loading...
- -export const Empty = () =>
Empty
- -export const Failure = ({ error }) =>
Error: {error.message}
- -export const Success = ({ posts }) => { - return posts.map((post) => ) -} diff --git a/web/src/components/BlogPostsCell/BlogPostsCell.mock.js b/web/src/components/BlogPostsCell/BlogPostsCell.mock.js deleted file mode 100644 index 70d4d6a..0000000 --- a/web/src/components/BlogPostsCell/BlogPostsCell.mock.js +++ /dev/null @@ -1,6 +0,0 @@ -// Define your own mock data here: -export const standard = (/* vars, { ctx, req } */) => ({ - blogPosts: { - id: 42, - }, -}) diff --git a/web/src/components/BlogPostsCell/BlogPostsCell.stories.js b/web/src/components/BlogPostsCell/BlogPostsCell.stories.js deleted file mode 100644 index 841d3b2..0000000 --- a/web/src/components/BlogPostsCell/BlogPostsCell.stories.js +++ /dev/null @@ -1,20 +0,0 @@ -import { Loading, Empty, Failure, Success } from './BlogPostsCell' -import { standard } from './BlogPostsCell.mock' - -export const loading = () => { - return Loading ? : null -} - -export const empty = () => { - return Empty ? : null -} - -export const failure = () => { - return Failure ? : null -} - -export const success = () => { - return Success ? : null -} - -export default { title: 'Cells/BlogPostsCell' } diff --git a/web/src/components/BlogPostsCell/BlogPostsCell.test.js b/web/src/components/BlogPostsCell/BlogPostsCell.test.js deleted file mode 100644 index 0d1fc66..0000000 --- a/web/src/components/BlogPostsCell/BlogPostsCell.test.js +++ /dev/null @@ -1,26 +0,0 @@ -import { render, screen } from '@redwoodjs/testing' -import { Loading, Empty, Failure, Success } from './BlogPostsCell' -import { standard } from './BlogPostsCell.mock' - -describe('BlogPostsCell', () => { - test('Loading renders successfully', () => { - render() - // Use screen.debug() to see output - expect(screen.getByText('Loading...')).toBeInTheDocument() - }) - - test('Empty renders successfully', async () => { - render() - expect(screen.getByText('Empty')).toBeInTheDocument() - }) - - test('Failure renders successfully', async () => { - render() - expect(screen.getByText(/Oh no/i)).toBeInTheDocument() - }) - - test('Success renders successfully', async () => { - render() - expect(screen.getByText(/42/i)).toBeInTheDocument() - }) -}) diff --git a/web/src/components/EditPartCell/EditPartCell.js b/web/src/components/EditPartCell/EditPartCell.js deleted file mode 100644 index b434a62..0000000 --- a/web/src/components/EditPartCell/EditPartCell.js +++ /dev/null @@ -1,35 +0,0 @@ -import { useMutation } from '@redwoodjs/web' -import PartForm from 'src/components/PartForm' - -export const QUERY = gql` - query FIND_PART_BY_ID($id: Int!) { - part: part(id: $id) { - id - title - description - code - mainImage - createdAt - } - } -` -const UPDATE_PART_MUTATION = gql` - mutation UpdatePartMutation($id: Int!, $input: UpdatePartInput!) { - updatePart(id: $id, input: $input) { - id - code - } - } -` - -export const Loading = () =>
Loading...
- -export const Success = ({ part }) => { - const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION) - - const onSave = (input, id) => updatePart({ variables: { id, input } }) - - return ( - - ) -} diff --git a/web/src/components/EditPostCell/EditPostCell.js b/web/src/components/EditPostCell/EditPostCell.js deleted file mode 100644 index 904e44a..0000000 --- a/web/src/components/EditPostCell/EditPostCell.js +++ /dev/null @@ -1,48 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { navigate, routes } from '@redwoodjs/router' -import PostForm from 'src/components/PostForm' - -export const QUERY = gql` - query FIND_POST_BY_ID($id: Int!) { - post: post(id: $id) { - id - title - body - createdAt - } - } -` -const UPDATE_POST_MUTATION = gql` - mutation UpdatePostMutation($id: Int!, $input: UpdatePostInput!) { - updatePost(id: $id, input: $input) { - id - } - } -` - -export const Loading = () =>
Loading...
- -export const Success = ({ post }) => { - const { addMessage } = useFlash() - const [updatePost, { loading, error }] = useMutation(UPDATE_POST_MUTATION, { - onCompleted: () => { - navigate(routes.posts()) - addMessage('Post updated.', { classes: 'rw-flash-success' }) - }, - }) - - const onSave = (input, id) => { - updatePost({ variables: { id, input } }) - } - - return ( -
-
-

Edit Post {post.id}

-
-
- -
-
- ) -} diff --git a/web/src/components/EditUserCell/EditUserCell.js b/web/src/components/EditUserCell/EditUserCell.js deleted file mode 100644 index 34f940c..0000000 --- a/web/src/components/EditUserCell/EditUserCell.js +++ /dev/null @@ -1,50 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { navigate, routes } from '@redwoodjs/router' -import UserForm from 'src/components/UserForm' - -export const QUERY = gql` - query FIND_USER_BY_ID($id: Int!) { - user: user(id: $id) { - id - email - createdAt - updatedAt - image - bio - } - } -` -const UPDATE_USER_MUTATION = gql` - mutation UpdateUserMutation($id: Int!, $input: UpdateUserInput!) { - updateUser(id: $id, input: $input) { - id - } - } -` - -export const Loading = () =>
Loading...
- -export const Success = ({ user }) => { - const { addMessage } = useFlash() - const [updateUser, { loading, error }] = useMutation(UPDATE_USER_MUTATION, { - onCompleted: () => { - navigate(routes.users()) - addMessage('User updated.', { classes: 'rw-flash-success' }) - }, - }) - - const onSave = (input, id) => { - updateUser({ variables: { id, input } }) - } - - return ( -
-
-

Edit User {user.id}

-
-
- -
-
- ) -} diff --git a/web/src/components/NewPart/NewPart.js b/web/src/components/NewPart/NewPart.js deleted file mode 100644 index 3b7e5ed..0000000 --- a/web/src/components/NewPart/NewPart.js +++ /dev/null @@ -1,38 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { navigate, routes } from '@redwoodjs/router' -import PartForm from 'src/components/PartForm' - -const CREATE_PART_MUTATION = gql` - mutation CreatePartMutation($input: CreatePartInput!) { - createPart(input: $input) { - id - } - } -` - -const NewPart = () => { - const { addMessage } = useFlash() - const [createPart, { loading, error }] = useMutation(CREATE_PART_MUTATION, { - onCompleted: () => { - navigate(routes.parts()) - addMessage('Part created.', { classes: 'rw-flash-success' }) - }, - }) - - const onSave = (input) => { - createPart({ variables: { input } }) - } - - return ( -
-
-

New Part

-
-
- -
-
- ) -} - -export default NewPart diff --git a/web/src/components/NewPost/NewPost.js b/web/src/components/NewPost/NewPost.js deleted file mode 100644 index ff4eec2..0000000 --- a/web/src/components/NewPost/NewPost.js +++ /dev/null @@ -1,38 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { navigate, routes } from '@redwoodjs/router' -import PostForm from 'src/components/PostForm' - -const CREATE_POST_MUTATION = gql` - mutation CreatePostMutation($input: CreatePostInput!) { - createPost(input: $input) { - id - } - } -` - -const NewPost = () => { - const { addMessage } = useFlash() - const [createPost, { loading, error }] = useMutation(CREATE_POST_MUTATION, { - onCompleted: () => { - navigate(routes.posts()) - addMessage('Post created.', { classes: 'rw-flash-success' }) - }, - }) - - const onSave = (input) => { - createPost({ variables: { input } }) - } - - return ( -
-
-

New Post

-
-
- -
-
- ) -} - -export default NewPost diff --git a/web/src/components/NewUser/NewUser.js b/web/src/components/NewUser/NewUser.js deleted file mode 100644 index 6f89a18..0000000 --- a/web/src/components/NewUser/NewUser.js +++ /dev/null @@ -1,38 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { navigate, routes } from '@redwoodjs/router' -import UserForm from 'src/components/UserForm' - -const CREATE_USER_MUTATION = gql` - mutation CreateUserMutation($input: CreateUserInput!) { - createUser(input: $input) { - id - } - } -` - -const NewUser = () => { - const { addMessage } = useFlash() - const [createUser, { loading, error }] = useMutation(CREATE_USER_MUTATION, { - onCompleted: () => { - navigate(routes.users()) - addMessage('User created.', { classes: 'rw-flash-success' }) - }, - }) - - const onSave = (input) => { - createUser({ variables: { input } }) - } - - return ( -
-
-

New User

-
-
- -
-
- ) -} - -export default NewUser diff --git a/web/src/components/Part/Part.js b/web/src/components/Part/Part.js deleted file mode 100644 index b132dbc..0000000 --- a/web/src/components/Part/Part.js +++ /dev/null @@ -1,110 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { Link, routes, navigate } from '@redwoodjs/router' -import { initialize } from 'src/cascade/js/MainPage/CascadeMain' -import { useEffect, useState } from 'react' - -const DELETE_PART_MUTATION = gql` - mutation DeletePartMutation($id: Int!) { - deletePart(id: $id) { - id - } - } -` - -const Part = ({ part, saveCode, loading, error}) => { - const [code, setCode] = useState(part.code) - useEffect(() => { - const sickCallback = (code) => setCode(code) - initialize(sickCallback, part.code) - }, []) - const hasChanges = code !== part.code - const { addMessage } = useFlash() - const [deletePart] = useMutation(DELETE_PART_MUTATION, { - onCompleted: () => { - navigate(routes.parts()) - addMessage('Part deleted.', { classes: 'rw-flash-success' }) - }, - }) - - const onDeleteClick = (id) => { - if (confirm('Are you sure you want to delete part ' + id + '?')) { - deletePart({ variables: { id } }) - } - } - - return ( - <> -
-
-

- Part {part.id} Detail -

-
- - - - - - - - - - - {/* - - - */} - {/* - - - */} - {/* - - - */} - -
Title{part.title}
Description{part.description}
Code{part.code}
Main image{part.mainImage}
Created at{timeTag(part.createdAt)}
- -
- - - - ) -} - -export default Part diff --git a/web/src/components/PartCell/PartCell.js b/web/src/components/PartCell/PartCell.js deleted file mode 100644 index 22044f0..0000000 --- a/web/src/components/PartCell/PartCell.js +++ /dev/null @@ -1,32 +0,0 @@ - -import {QUERY as reExportQuery} from 'src/components/EditPartCell' -import Editor from "rich-markdown-editor"; - -export const QUERY = reExportQuery - -export const Loading = () =>
Loading...
- -export const Empty = () =>
Empty
- -export const Failure = ({ error }) =>
Error: {error.message}
- -export const Success = ({ part }) => { - console.log(part) - return ( - <> -
-
- -
-
-

{part.title}

- -
-
- - ) -} diff --git a/web/src/components/PartForm/PartForm.js b/web/src/components/PartForm/PartForm.js deleted file mode 100644 index daecc16..0000000 --- a/web/src/components/PartForm/PartForm.js +++ /dev/null @@ -1,93 +0,0 @@ -import { - Form, - FormError, - FieldError, - Label, - TextField, - Submit, -} from '@redwoodjs/forms' -import { useState } from 'react'; -import { navigate, routes } from '@redwoodjs/router' -import { useFlash } from '@redwoodjs/web' -import ImageUploader from './ImageUploader.js' - - -import Editor from "rich-markdown-editor"; - -const PartForm = (props) => { - const { addMessage } = useFlash() - const [description, setDescription] = useState(props?.part?.description) - const [imageUrl, setImageUrl] = useState(props?.part?.mainImage) - const onSubmit = async (data, e) => { - - await props.onSave({ - ...data, - description, - mainImage: imageUrl - }, props?.part?.id) - const shouldOpenIde = e?.nativeEvent?.submitter?.dataset?.openIde - if(shouldOpenIde) { - navigate(routes.partIde({id: props?.part?.id})) - } else { - navigate(routes.part({id: props?.part?.id})) - } - addMessage('Part updated.', { classes: 'rw-flash-success' }) - } - - return ( -
-
- - - - - - - setImageUrl(cloudinaryPublicId)} /> - - - -
- setDescription(valueFn())} - /> -
- -
- - Save - - - Save and open IDE - -
- -
- ) -} - -export default PartForm diff --git a/web/src/components/Parts/Parts.js b/web/src/components/Parts/Parts.js deleted file mode 100644 index 8f49c7b..0000000 --- a/web/src/components/Parts/Parts.js +++ /dev/null @@ -1,89 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { Link, routes } from '@redwoodjs/router' -import { Image as CloudinaryImage } from 'cloudinary-react' - -import avatar from 'src/assets/harold.jpg' - -const DELETE_PART_MUTATION = gql` - mutation DeletePartMutation($id: Int!) { - deletePart(id: $id) { - id - } - } -` - -const MAX_STRING_LENGTH = 150 - -const truncate = (text) => { - let output = text - if (text && text.length > MAX_STRING_LENGTH) { - output = output.substring(0, MAX_STRING_LENGTH) + '...' - } - return output -} - -const jsonTruncate = (obj) => { - return truncate(JSON.stringify(obj, null, 2)) -} - -const timeTag = (datetime) => { - return ( - - ) -} - -const checkboxInputTag = (checked) => { - return -} - -const PartsList = ({ parts }) => { - const { addMessage } = useFlash() - const [deletePart] = useMutation(DELETE_PART_MUTATION, { - onCompleted: () => { - addMessage('Part deleted.', { classes: 'rw-flash-success' }) - }, - }) - - const onDeleteClick = (id) => { - if (confirm('Are you sure you want to delete part ' + id + '?')) { - deletePart({ variables: { id }, refetchQueries: ['PARTS'] }) - } - } - - return ( -
- {parts.map((part) => { - return ( - -
-
-
?
-
- -
-

{part.title}

-
-
- -
-
- - )})} -
- ) -} - -export default PartsList diff --git a/web/src/components/PartsCell/PartsCell.js b/web/src/components/PartsCell/PartsCell.js deleted file mode 100644 index 98380e8..0000000 --- a/web/src/components/PartsCell/PartsCell.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' - -import Parts from 'src/components/Parts' - -export const QUERY = gql` - query PARTS { - parts { - id - title - description - code - mainImage - createdAt - } - } -` - -export const Loading = () =>
Loading...
- -export const Empty = () => { - return ( -
- {'No parts yet. '} - - {'Create one?'} - -
- ) -} - -export const Success = ({ parts }) => { - return -} diff --git a/web/src/components/Post/Post.js b/web/src/components/Post/Post.js deleted file mode 100644 index ff9c448..0000000 --- a/web/src/components/Post/Post.js +++ /dev/null @@ -1,95 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { Link, routes, navigate } from '@redwoodjs/router' - -const DELETE_POST_MUTATION = gql` - mutation DeletePostMutation($id: Int!) { - deletePost(id: $id) { - id - } - } -` - -const jsonDisplay = (obj) => { - return ( -
-      {JSON.stringify(obj, null, 2)}
-    
- ) -} - -const timeTag = (datetime) => { - return ( - - ) -} - -const checkboxInputTag = (checked) => { - return -} - -const Post = ({ post }) => { - const { addMessage } = useFlash() - const [deletePost] = useMutation(DELETE_POST_MUTATION, { - onCompleted: () => { - navigate(routes.posts()) - addMessage('Post deleted.', { classes: 'rw-flash-success' }) - }, - }) - - const onDeleteClick = (id) => { - if (confirm('Are you sure you want to delete post ' + id + '?')) { - deletePost({ variables: { id } }) - } - } - - return ( - <> -
-
-

- Post {post.id} Detail -

-
- - - - - - - - - - - - - - - - - - - -
Id{post.id}
Title{post.title}
Body{post.body}
Created at{timeTag(post.createdAt)}
-
- - - ) -} - -export default Post diff --git a/web/src/components/PostCell/PostCell.js b/web/src/components/PostCell/PostCell.js deleted file mode 100644 index 65a507b..0000000 --- a/web/src/components/PostCell/PostCell.js +++ /dev/null @@ -1,20 +0,0 @@ -import Post from 'src/components/Post' - -export const QUERY = gql` - query FIND_POST_BY_ID($id: Int!) { - post: post(id: $id) { - id - title - body - createdAt - } - } -` - -export const Loading = () =>
Loading...
- -export const Empty = () =>
Post not found
- -export const Success = ({ post }) => { - return -} diff --git a/web/src/components/PostForm/PostForm.js b/web/src/components/PostForm/PostForm.js deleted file mode 100644 index 90f5ff4..0000000 --- a/web/src/components/PostForm/PostForm.js +++ /dev/null @@ -1,67 +0,0 @@ -import { - Form, - FormError, - FieldError, - Label, - TextField, - Submit, -} from '@redwoodjs/forms' - -const PostForm = (props) => { - const onSubmit = (data) => { - props.onSave(data, props?.post?.id) - } - - return ( -
-
- - - - - - - - - - -
- - Save - -
- -
- ) -} - -export default PostForm diff --git a/web/src/components/Posts/Posts.js b/web/src/components/Posts/Posts.js deleted file mode 100644 index 81f4b76..0000000 --- a/web/src/components/Posts/Posts.js +++ /dev/null @@ -1,105 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { Link, routes } from '@redwoodjs/router' - -const DELETE_POST_MUTATION = gql` - mutation DeletePostMutation($id: Int!) { - deletePost(id: $id) { - id - } - } -` - -const MAX_STRING_LENGTH = 150 - -const truncate = (text) => { - let output = text - if (text && text.length > MAX_STRING_LENGTH) { - output = output.substring(0, MAX_STRING_LENGTH) + '...' - } - return output -} - -const jsonTruncate = (obj) => { - return truncate(JSON.stringify(obj, null, 2)) -} - -const timeTag = (datetime) => { - return ( - - ) -} - -const checkboxInputTag = (checked) => { - return -} - -const PostsList = ({ posts }) => { - const { addMessage } = useFlash() - const [deletePost] = useMutation(DELETE_POST_MUTATION, { - onCompleted: () => { - addMessage('Post deleted.', { classes: 'rw-flash-success' }) - }, - }) - - const onDeleteClick = (id) => { - if (confirm('Are you sure you want to delete post ' + id + '?')) { - deletePost({ variables: { id }, refetchQueries: ['POSTS'] }) - } - } - - return ( -
- - - - - - - - - - - - {posts.map((post) => ( - - - - - - - - ))} - -
IdTitleBodyCreated at 
{truncate(post.id)}{truncate(post.title)}{truncate(post.body)}{timeTag(post.createdAt)} - -
-
- ) -} - -export default PostsList diff --git a/web/src/components/PostsCell/PostsCell.js b/web/src/components/PostsCell/PostsCell.js deleted file mode 100644 index ddf49cd..0000000 --- a/web/src/components/PostsCell/PostsCell.js +++ /dev/null @@ -1,31 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' - -import Posts from 'src/components/Posts' - -export const QUERY = gql` - query POSTS { - posts { - id - title - body - createdAt - } - } -` - -export const Loading = () =>
Loading...
- -export const Empty = () => { - return ( -
- {'No posts yet. '} - - {'Create one?'} - -
- ) -} - -export const Success = ({ posts }) => { - return -} diff --git a/web/src/components/User/User.js b/web/src/components/User/User.js deleted file mode 100644 index bc23faf..0000000 --- a/web/src/components/User/User.js +++ /dev/null @@ -1,109 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { Link, routes, navigate } from '@redwoodjs/router' -import { Image as CloudinaryImage } from 'cloudinary-react' -const DELETE_USER_MUTATION = gql` - mutation DeleteUserMutation($id: Int!) { - deleteUser(id: $id) { - id - } - } -` - -const jsonDisplay = (obj) => { - return ( -
-      {JSON.stringify(obj, null, 2)}
-    
- ) -} - -const timeTag = (datetime) => { - return ( - - ) -} - -const checkboxInputTag = (checked) => { - return -} - -const User = ({ user }) => { - const { addMessage } = useFlash() - const [deleteUser] = useMutation(DELETE_USER_MUTATION, { - onCompleted: () => { - navigate(routes.users()) - addMessage('User deleted.', { classes: 'rw-flash-success' }) - }, - }) - - const onDeleteClick = (id) => { - if (confirm('Are you sure you want to delete user ' + id + '?')) { - deleteUser({ variables: { id } }) - } - } - - return ( - <> -
-
-

- User {user.id} Detail -

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Id{user.id}
Email{user.email}
Created at{timeTag(user.createdAt)}
Updated at{timeTag(user.updatedAt)}
Image
Bio{user.bio}
-
- - - ) -} - -export default User diff --git a/web/src/components/UserCell/UserCell.js b/web/src/components/UserCell/UserCell.js deleted file mode 100644 index f89a7fd..0000000 --- a/web/src/components/UserCell/UserCell.js +++ /dev/null @@ -1,22 +0,0 @@ -import User from 'src/components/User' - -export const QUERY = gql` - query FIND_USER_BY_ID($id: Int!) { - user: user(id: $id) { - id - email - createdAt - updatedAt - image - bio - } - } -` - -export const Loading = () =>
Loading...
- -export const Empty = () =>
User not found
- -export const Success = ({ user }) => { - return -} diff --git a/web/src/components/UserForm/UserForm.js b/web/src/components/UserForm/UserForm.js deleted file mode 100644 index fdc74c2..0000000 --- a/web/src/components/UserForm/UserForm.js +++ /dev/null @@ -1,79 +0,0 @@ -import { - Form, - FormError, - FieldError, - Label, - TextField, - Submit, -} from '@redwoodjs/forms' -import { useState } from 'react'; -import { navigate, routes } from '@redwoodjs/router' -import { useFlash } from '@redwoodjs/web' -import ImageUploader from '../PartForm/ImageUploader' -const UserForm = (props) => { - const { addMessage } = useFlash() - // const [bio, setBio] = useState(props?.user?.bio) - const [imageUrl, setImageUrl] = useState(props?.user?.image) - const onSubmit = async (data, e) => { - - await props.onSave({ - ...data, - image: imageUrl - }, props?.user?.id) - addMessage('User updated.', { classes: 'rw-flash-success' }) - } - - return ( -
-
- - - - - - setImageUrl(cloudinaryPublicId)} /> - - - - - -
- - Save - -
- -
- ) -} - -export default UserForm diff --git a/web/src/components/UserPart/UserPart.js b/web/src/components/UserPart/UserPart.js deleted file mode 100644 index 83256b2..0000000 --- a/web/src/components/UserPart/UserPart.js +++ /dev/null @@ -1,16 +0,0 @@ -function UserPart({ userName, partName }) { - return ( -

-
.
- - {userName} - -
.
- - {partName} - -

- ) -} - -export default UserPart diff --git a/web/src/components/Users/Users.js b/web/src/components/Users/Users.js deleted file mode 100644 index 427139e..0000000 --- a/web/src/components/Users/Users.js +++ /dev/null @@ -1,109 +0,0 @@ -import { useMutation, useFlash } from '@redwoodjs/web' -import { Link, routes } from '@redwoodjs/router' - -const DELETE_USER_MUTATION = gql` - mutation DeleteUserMutation($id: Int!) { - deleteUser(id: $id) { - id - } - } -` - -const MAX_STRING_LENGTH = 150 - -const truncate = (text) => { - let output = text - if (text && text.length > MAX_STRING_LENGTH) { - output = output.substring(0, MAX_STRING_LENGTH) + '...' - } - return output -} - -const jsonTruncate = (obj) => { - return truncate(JSON.stringify(obj, null, 2)) -} - -const timeTag = (datetime) => { - return ( - - ) -} - -const checkboxInputTag = (checked) => { - return -} - -const UsersList = ({ users }) => { - const { addMessage } = useFlash() - const [deleteUser] = useMutation(DELETE_USER_MUTATION, { - onCompleted: () => { - addMessage('User deleted.', { classes: 'rw-flash-success' }) - }, - }) - - const onDeleteClick = (id) => { - if (confirm('Are you sure you want to delete user ' + id + '?')) { - deleteUser({ variables: { id }, refetchQueries: ['USERS'] }) - } - } - - return ( -
- - - - - - - - - - - - - - {users.map((user) => ( - - - - - - - - - - ))} - -
IdEmailCreated atUpdated atImageBio 
{truncate(user.id)}{truncate(user.email)}{timeTag(user.createdAt)}{timeTag(user.updatedAt)}{truncate(user.image)}{truncate(user.bio)} - -
-
- ) -} - -export default UsersList diff --git a/web/src/components/UsersCell/UsersCell.js b/web/src/components/UsersCell/UsersCell.js deleted file mode 100644 index 9fb8655..0000000 --- a/web/src/components/UsersCell/UsersCell.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' - -import Users from 'src/components/Users' - -export const QUERY = gql` - query USERS { - users { - id - email - createdAt - updatedAt - image - bio - } - } -` - -export const Loading = () =>
Loading...
- -export const Empty = () => { - return ( -
- {'No users yet. '} - - {'Create one?'} - -
- ) -} - -export const Success = ({ users }) => { - return -} diff --git a/web/src/index.html b/web/src/index.html index b13cef6..947ea10 100644 --- a/web/src/index.html +++ b/web/src/index.html @@ -38,7 +38,7 @@ } } } - coolGuy() + // coolGuy() diff --git a/web/src/layouts/BlogLayout/BlogLayout.js b/web/src/layouts/BlogLayout/BlogLayout.js deleted file mode 100644 index 54134d9..0000000 --- a/web/src/layouts/BlogLayout/BlogLayout.js +++ /dev/null @@ -1,24 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' - -const BlogLayout = ({ children }) => { - return ( - <> -
-

Redwood Blog

- -
-
{children}
- - ) -} - -export default BlogLayout diff --git a/web/src/layouts/BlogLayout/BlogLayout.stories.js b/web/src/layouts/BlogLayout/BlogLayout.stories.js deleted file mode 100644 index 4e249ec..0000000 --- a/web/src/layouts/BlogLayout/BlogLayout.stories.js +++ /dev/null @@ -1,7 +0,0 @@ -import BlogLayout from './BlogLayout' - -export const generated = () => { - return -} - -export default { title: 'Layouts/BlogLayout' } diff --git a/web/src/layouts/BlogLayout/BlogLayout.test.js b/web/src/layouts/BlogLayout/BlogLayout.test.js deleted file mode 100644 index b87e730..0000000 --- a/web/src/layouts/BlogLayout/BlogLayout.test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { render } from '@redwoodjs/testing' - -import BlogLayout from './BlogLayout' - -describe('BlogLayout', () => { - it('renders successfully', () => { - expect(() => { - render() - }).not.toThrow() - }) -}) diff --git a/web/src/layouts/PartsLayout/PartsLayout.js b/web/src/layouts/PartsLayout/PartsLayout.js deleted file mode 100644 index 7234e1d..0000000 --- a/web/src/layouts/PartsLayout/PartsLayout.js +++ /dev/null @@ -1,11 +0,0 @@ - - -const PartsLayout = (props) => { - return ( -
-
{props.children}
-
- ) -} - -export default PartsLayout diff --git a/web/src/layouts/PostsLayout/PostsLayout.js b/web/src/layouts/PostsLayout/PostsLayout.js deleted file mode 100644 index 45578ce..0000000 --- a/web/src/layouts/PostsLayout/PostsLayout.js +++ /dev/null @@ -1,23 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' -import { Flash } from '@redwoodjs/web' - -const PostsLayout = (props) => { - return ( -
- -
-

- - Posts - -

- -
+
New Post - -
-
{props.children}
-
- ) -} - -export default PostsLayout diff --git a/web/src/pages/AboutPage/AboutPage.js b/web/src/pages/AboutPage/AboutPage.js deleted file mode 100644 index 71a730c..0000000 --- a/web/src/pages/AboutPage/AboutPage.js +++ /dev/null @@ -1,19 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' -import BlogLayout from 'src/layouts/BlogLayout' - -const AboutPage = () => { - return ( - -

AboutPage

-

- Find me in ./web/src/pages/AboutPage/AboutPage.js -

-

- My default route is named about, link to me with ` - About` -

-
- ) -} - -export default AboutPage diff --git a/web/src/pages/AboutPage/AboutPage.stories.js b/web/src/pages/AboutPage/AboutPage.stories.js deleted file mode 100644 index 3ca853b..0000000 --- a/web/src/pages/AboutPage/AboutPage.stories.js +++ /dev/null @@ -1,7 +0,0 @@ -import AboutPage from './AboutPage' - -export const generated = () => { - return -} - -export default { title: 'Pages/AboutPage' } diff --git a/web/src/pages/AboutPage/AboutPage.test.js b/web/src/pages/AboutPage/AboutPage.test.js deleted file mode 100644 index 6878394..0000000 --- a/web/src/pages/AboutPage/AboutPage.test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { render } from '@redwoodjs/testing' - -import AboutPage from './AboutPage' - -describe('AboutPage', () => { - it('renders successfully', () => { - expect(() => { - render() - }).not.toThrow() - }) -}) diff --git a/web/src/pages/BlogPostPage/BlogPostPage.js b/web/src/pages/BlogPostPage/BlogPostPage.js deleted file mode 100644 index 7f1e9c3..0000000 --- a/web/src/pages/BlogPostPage/BlogPostPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import BlogLayout from 'src/layouts/BlogLayout' -import BlogPostCell from 'src/components/BlogPostCell' - -const BlogPostPage = ({id}) => { - return ( - - - - ) -} - -export default BlogPostPage diff --git a/web/src/pages/BlogPostPage/BlogPostPage.stories.js b/web/src/pages/BlogPostPage/BlogPostPage.stories.js deleted file mode 100644 index 5e9fa74..0000000 --- a/web/src/pages/BlogPostPage/BlogPostPage.stories.js +++ /dev/null @@ -1,7 +0,0 @@ -import BlogPostPage from './BlogPostPage' - -export const generated = () => { - return -} - -export default { title: 'Pages/BlogPostPage' } diff --git a/web/src/pages/BlogPostPage/BlogPostPage.test.js b/web/src/pages/BlogPostPage/BlogPostPage.test.js deleted file mode 100644 index cb14ea6..0000000 --- a/web/src/pages/BlogPostPage/BlogPostPage.test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { render } from '@redwoodjs/testing' - -import BlogPostPage from './BlogPostPage' - -describe('BlogPostPage', () => { - it('renders successfully', () => { - expect(() => { - render() - }).not.toThrow() - }) -}) diff --git a/web/src/pages/ContactPage/ContactPage.js b/web/src/pages/ContactPage/ContactPage.js deleted file mode 100644 index 088f0b6..0000000 --- a/web/src/pages/ContactPage/ContactPage.js +++ /dev/null @@ -1,59 +0,0 @@ -import { Form, TextField, Submit, TextAreaField, FieldError, FormError } from '@redwoodjs/forms' -import { useMutation, Flash, useFlash } from '@redwoodjs/web' -import MainLayout from 'src/layouts/MainLayout' -import { useForm } from 'react-hook-form' - -const CREATE_CONTACT = gql` - mutation CreateContactMutation($input: CreateContactInput!) { - createContact(input: $input) { - id - } - } -` - -const ContactPage = () => { - const formMethods = useForm() - const { addMessage } = useFlash() - const [create, {loading, error}] = useMutation(CREATE_CONTACT, { - onCompleted: () => { - addMessage('Thank you for your submission!', { - style: { backgroundColor: 'green', color: 'white', padding: '1rem' } - }) - formMethods.reset() - }, - }) - const onSubmit = async (data) => { - try { - await create({ variables: { input: data } }) - } catch (error) { - console.log(error) - } - } - - return ( - - -
- - - - - - - - - - - - - - Save - -
- ) -} - -export default ContactPage diff --git a/web/src/pages/ContactPage/ContactPage.stories.js b/web/src/pages/ContactPage/ContactPage.stories.js deleted file mode 100644 index 0894c0b..0000000 --- a/web/src/pages/ContactPage/ContactPage.stories.js +++ /dev/null @@ -1,7 +0,0 @@ -import ContactPage from './ContactPage' - -export const generated = () => { - return -} - -export default { title: 'Pages/ContactPage' } diff --git a/web/src/pages/ContactPage/ContactPage.test.js b/web/src/pages/ContactPage/ContactPage.test.js deleted file mode 100644 index d31f442..0000000 --- a/web/src/pages/ContactPage/ContactPage.test.js +++ /dev/null @@ -1,11 +0,0 @@ -import { render } from '@redwoodjs/testing' - -import ContactPage from './ContactPage' - -describe('ContactPage', () => { - it('renders successfully', () => { - expect(() => { - render() - }).not.toThrow() - }) -}) diff --git a/web/src/pages/EditPartPage/EditPartPage.js b/web/src/pages/EditPartPage/EditPartPage.js deleted file mode 100644 index 82d3b66..0000000 --- a/web/src/pages/EditPartPage/EditPartPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import EditPartCell from 'src/components/EditPartCell' -import MainLayout from 'src/layouts/MainLayout' - -const EditPartPage = ({ id }) => { - return ( - - - - ) -} - -export default EditPartPage diff --git a/web/src/pages/EditPostPage/EditPostPage.js b/web/src/pages/EditPostPage/EditPostPage.js deleted file mode 100644 index 419af6b..0000000 --- a/web/src/pages/EditPostPage/EditPostPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import PostsLayout from 'src/layouts/PostsLayout' -import EditPostCell from 'src/components/EditPostCell' - -const EditPostPage = ({ id }) => { - return ( - - - - ) -} - -export default EditPostPage diff --git a/web/src/pages/EditUserPage/EditUserPage.js b/web/src/pages/EditUserPage/EditUserPage.js deleted file mode 100644 index 5c8fa8d..0000000 --- a/web/src/pages/EditUserPage/EditUserPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import MainLayout from 'src/layouts/MainLayout' -import EditUserCell from 'src/components/EditUserCell' - -const EditUserPage = ({ id }) => { - return ( - - - - ) -} - -export default EditUserPage diff --git a/web/src/pages/IdePartPage/IdePartPage.stories.js b/web/src/pages/IdePartPage/IdePartPage.stories.js deleted file mode 100644 index 6bfa9a4..0000000 --- a/web/src/pages/IdePartPage/IdePartPage.stories.js +++ /dev/null @@ -1,7 +0,0 @@ -import IdePartPage from './IdePartPage' - -export const generated = () => { - return -} - -export default { title: 'Pages/IdePartPage' } diff --git a/web/src/pages/NewPartPage/NewPartPage.js b/web/src/pages/NewPartPage/NewPartPage.js deleted file mode 100644 index 4f39148..0000000 --- a/web/src/pages/NewPartPage/NewPartPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import PartsLayout from 'src/layouts/PartsLayout' -import NewPart from 'src/components/NewPart' - -const NewPartPage = () => { - return ( - - - - ) -} - -export default NewPartPage diff --git a/web/src/pages/NewPostPage/NewPostPage.js b/web/src/pages/NewPostPage/NewPostPage.js deleted file mode 100644 index 7a41350..0000000 --- a/web/src/pages/NewPostPage/NewPostPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import PostsLayout from 'src/layouts/PostsLayout' -import NewPost from 'src/components/NewPost' - -const NewPostPage = () => { - return ( - - - - ) -} - -export default NewPostPage diff --git a/web/src/pages/NewUserPage/NewUserPage.js b/web/src/pages/NewUserPage/NewUserPage.js deleted file mode 100644 index 0368b02..0000000 --- a/web/src/pages/NewUserPage/NewUserPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import MainLayout from 'src/layouts/MainLayout' -import NewUser from 'src/components/NewUser' - -const NewUserPage = () => { - return ( - - - - ) -} - -export default NewUserPage diff --git a/web/src/pages/PartPage/PartPage.js b/web/src/pages/PartPage/PartPage.js deleted file mode 100644 index b9bcd31..0000000 --- a/web/src/pages/PartPage/PartPage.js +++ /dev/null @@ -1,15 +0,0 @@ -import PartsLayout from 'src/layouts/PartsLayout' -import MainLayout from 'src/layouts/MainLayout' -import PartCell from 'src/components/PartCell' - -const PartPage = ({ id }) => { - return ( - - - - - - ) -} - -export default PartPage diff --git a/web/src/pages/PartsPage/PartsPage.js b/web/src/pages/PartsPage/PartsPage.js deleted file mode 100644 index ae36f11..0000000 --- a/web/src/pages/PartsPage/PartsPage.js +++ /dev/null @@ -1,15 +0,0 @@ -import MainLayout from 'src/layouts/MainLayout' -import PartsLayout from 'src/layouts/PartsLayout' -import PartsCell from 'src/components/PartsCell' - -const PartsPage = () => { - return ( - - - - - - ) -} - -export default PartsPage diff --git a/web/src/pages/PostPage/PostPage.js b/web/src/pages/PostPage/PostPage.js deleted file mode 100644 index 8b9eec3..0000000 --- a/web/src/pages/PostPage/PostPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import PostsLayout from 'src/layouts/PostsLayout' -import PostCell from 'src/components/PostCell' - -const PostPage = ({ id }) => { - return ( - - - - ) -} - -export default PostPage diff --git a/web/src/pages/PostsPage/PostsPage.js b/web/src/pages/PostsPage/PostsPage.js deleted file mode 100644 index b5392dc..0000000 --- a/web/src/pages/PostsPage/PostsPage.js +++ /dev/null @@ -1,15 +0,0 @@ -import MainLayout from 'src/layouts/MainLayout' -import PostsLayout from 'src/layouts/PostsLayout' -import PostsCell from 'src/components/PostsCell' - -const PostsPage = () => { - return ( - - - - - - ) -} - -export default PostsPage diff --git a/web/src/pages/UserPage/UserPage.js b/web/src/pages/UserPage/UserPage.js deleted file mode 100644 index cf81dc9..0000000 --- a/web/src/pages/UserPage/UserPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import MainLayout from 'src/layouts/MainLayout' -import UserCell from 'src/components/UserCell' - -const UserPage = ({ id }) => { - return ( - - - - ) -} - -export default UserPage diff --git a/web/src/pages/UsersPage/UsersPage.js b/web/src/pages/UsersPage/UsersPage.js deleted file mode 100644 index 7331b05..0000000 --- a/web/src/pages/UsersPage/UsersPage.js +++ /dev/null @@ -1,12 +0,0 @@ -import MainLayout from 'src/layouts/MainLayout' -import UsersCell from 'src/components/UsersCell' - -const UsersPage = () => { - return ( - - - - ) -} - -export default UsersPage From 86df1d501df759182f4453a1cfe112473446845a Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Mon, 2 Nov 2020 07:02:11 +1100 Subject: [PATCH 03/24] Re-init DB and scaffold all models --- .../20201009213512-create-posts/README.md | 45 - .../20201009213512-create-posts/schema.prisma | 18 - .../20201009213512-create-posts/steps.json | 120 --- .../20201011043647-create-parts/README.md | 52 -- .../20201011043647-create-parts/schema.prisma | 28 - .../20201011043647-create-parts/steps.json | 105 --- .../20201011052155-add-code-to-part/README.md | 65 -- .../schema.prisma | 29 - .../steps.json | 37 - .../README.md | 69 -- .../schema.prisma | 29 - .../steps.json | 19 - .../20201011095227-create-contact/README.md | 50 -- .../schema.prisma | 37 - .../20201011095227-create-contact/steps.json | 105 --- .../README.md | 65 -- .../schema.prisma | 48 -- .../steps.json | 179 ---- .../README.md | 61 -- .../schema.prisma | 48 -- .../steps.json | 15 - .../20201029214206-rejig-schema/README.md | 188 ----- .../20201029214206-rejig-schema/schema.prisma | 76 -- .../20201030061957-rejig-schema/README.md | 91 -- .../20201030061957-rejig-schema/steps.json | 38 - .../20201101183848-db-init/README.md | 158 ++++ .../schema.prisma | 39 +- .../steps.json | 791 ++++++++++-------- api/prisma/migrations/migrate.lock | 10 +- api/prisma/schema.prisma | 39 +- api/src/functions/identity-signup.js | 4 +- api/src/graphql/comments.sdl.js | 35 + api/src/graphql/partReactions.sdl.js | 38 + api/src/graphql/parts.sdl.js | 42 + api/src/graphql/users.sdl.js | 39 + api/src/services/comments/comments.js | 38 + api/src/services/comments/comments.test.js | 9 + api/src/services/helpers.js | 13 + .../services/partReactions/partReactions.js | 38 + .../partReactions/partReactions.test.js | 9 + api/src/services/parts/parts.js | 40 + api/src/services/parts/parts.test.js | 9 + api/src/services/users/users.js | 38 + api/src/services/users/users.test.js | 9 + web/src/Routes.js | 20 +- web/src/components/Comment/Comment.js | 103 +++ web/src/components/CommentCell/CommentCell.js | 22 + web/src/components/CommentForm/CommentForm.js | 83 ++ web/src/components/Comments/Comments.js | 109 +++ .../components/CommentsCell/CommentsCell.js | 33 + .../EditCommentCell/EditCommentCell.js | 60 ++ .../components/EditPartCell/EditPartCell.js | 52 ++ .../EditPartReactionCell.js | 63 ++ .../components/EditUserCell/EditUserCell.js | 51 ++ web/src/components/IdePartCell/IdePartCell.js | 5 +- web/src/components/NewComment/NewComment.js | 41 + web/src/components/NewPart/NewPart.js | 38 + .../NewPartReaction/NewPartReaction.js | 41 + web/src/components/NewUser/NewUser.js | 38 + web/src/components/Part/Part.js | 111 +++ web/src/components/PartCell/PartCell.js | 24 + web/src/components/PartForm/ImageUploader.js | 120 --- web/src/components/PartForm/PartForm.js | 115 +++ .../components/PartReaction/PartReaction.js | 103 +++ .../PartReactionCell/PartReactionCell.js | 22 + .../PartReactionForm/PartReactionForm.js | 83 ++ .../components/PartReactions/PartReactions.js | 112 +++ .../PartReactionsCell/PartReactionsCell.js | 33 + web/src/components/Parts/Parts.js | 113 +++ web/src/components/PartsCell/PartsCell.js | 35 + web/src/components/User/User.js | 107 +++ web/src/components/UserCell/UserCell.js | 23 + web/src/components/UserForm/UserForm.js | 99 +++ web/src/components/Users/Users.js | 111 +++ web/src/components/UsersCell/UsersCell.js | 34 + .../layouts/CommentsLayout/CommentsLayout.js | 23 + web/src/layouts/MainLayout/MainLayout.js | 6 +- .../PartReactionsLayout.js | 26 + web/src/layouts/PartsLayout/PartsLayout.js | 23 + web/src/layouts/UsersLayout/UsersLayout.js | 23 + web/src/pages/CommentPage/CommentPage.js | 12 + web/src/pages/CommentsPage/CommentsPage.js | 12 + .../pages/EditCommentPage/EditCommentPage.js | 12 + web/src/pages/EditPartPage/EditPartPage.js | 12 + .../EditPartReactionPage.js | 12 + web/src/pages/EditUserPage/EditUserPage.js | 12 + web/src/pages/HomePage/HomePage.js | 12 +- .../pages/NewCommentPage/NewCommentPage.js | 12 + web/src/pages/NewPartPage/NewPartPage.js | 12 + .../NewPartReactionPage.js | 12 + web/src/pages/NewUserPage/NewUserPage.js | 12 + web/src/pages/PartPage/PartPage.js | 12 + .../PartReactionPage/PartReactionPage.js | 12 + .../PartReactionsPage/PartReactionsPage.js | 12 + web/src/pages/PartsPage/PartsPage.js | 12 + web/src/pages/UserPage/UserPage.js | 12 + web/src/pages/UsersPage/UsersPage.js | 12 + 97 files changed, 3202 insertions(+), 2122 deletions(-) delete mode 100644 api/prisma/migrations/20201009213512-create-posts/README.md delete mode 100644 api/prisma/migrations/20201009213512-create-posts/schema.prisma delete mode 100644 api/prisma/migrations/20201009213512-create-posts/steps.json delete mode 100644 api/prisma/migrations/20201011043647-create-parts/README.md delete mode 100644 api/prisma/migrations/20201011043647-create-parts/schema.prisma delete mode 100644 api/prisma/migrations/20201011043647-create-parts/steps.json delete mode 100644 api/prisma/migrations/20201011052155-add-code-to-part/README.md delete mode 100644 api/prisma/migrations/20201011052155-add-code-to-part/schema.prisma delete mode 100644 api/prisma/migrations/20201011052155-add-code-to-part/steps.json delete mode 100644 api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/README.md delete mode 100644 api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/schema.prisma delete mode 100644 api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/steps.json delete mode 100644 api/prisma/migrations/20201011095227-create-contact/README.md delete mode 100644 api/prisma/migrations/20201011095227-create-contact/schema.prisma delete mode 100644 api/prisma/migrations/20201011095227-create-contact/steps.json delete mode 100644 api/prisma/migrations/20201018233330-add-simple-user-model/README.md delete mode 100644 api/prisma/migrations/20201018233330-add-simple-user-model/schema.prisma delete mode 100644 api/prisma/migrations/20201018233330-add-simple-user-model/steps.json delete mode 100644 api/prisma/migrations/20201019072122-add-simplify-user-model/README.md delete mode 100644 api/prisma/migrations/20201019072122-add-simplify-user-model/schema.prisma delete mode 100644 api/prisma/migrations/20201019072122-add-simplify-user-model/steps.json delete mode 100644 api/prisma/migrations/20201029214206-rejig-schema/README.md delete mode 100644 api/prisma/migrations/20201029214206-rejig-schema/schema.prisma delete mode 100644 api/prisma/migrations/20201030061957-rejig-schema/README.md delete mode 100644 api/prisma/migrations/20201030061957-rejig-schema/steps.json create mode 100644 api/prisma/migrations/20201101183848-db-init/README.md rename api/prisma/migrations/{20201030061957-rejig-schema => 20201101183848-db-init}/schema.prisma (60%) rename api/prisma/migrations/{20201029214206-rejig-schema => 20201101183848-db-init}/steps.json (77%) create mode 100644 api/src/graphql/comments.sdl.js create mode 100644 api/src/graphql/partReactions.sdl.js create mode 100644 api/src/graphql/parts.sdl.js create mode 100644 api/src/graphql/users.sdl.js create mode 100644 api/src/services/comments/comments.js create mode 100644 api/src/services/comments/comments.test.js create mode 100644 api/src/services/helpers.js create mode 100644 api/src/services/partReactions/partReactions.js create mode 100644 api/src/services/partReactions/partReactions.test.js create mode 100644 api/src/services/parts/parts.js create mode 100644 api/src/services/parts/parts.test.js create mode 100644 api/src/services/users/users.js create mode 100644 api/src/services/users/users.test.js create mode 100644 web/src/components/Comment/Comment.js create mode 100644 web/src/components/CommentCell/CommentCell.js create mode 100644 web/src/components/CommentForm/CommentForm.js create mode 100644 web/src/components/Comments/Comments.js create mode 100644 web/src/components/CommentsCell/CommentsCell.js create mode 100644 web/src/components/EditCommentCell/EditCommentCell.js create mode 100644 web/src/components/EditPartCell/EditPartCell.js create mode 100644 web/src/components/EditPartReactionCell/EditPartReactionCell.js create mode 100644 web/src/components/EditUserCell/EditUserCell.js create mode 100644 web/src/components/NewComment/NewComment.js create mode 100644 web/src/components/NewPart/NewPart.js create mode 100644 web/src/components/NewPartReaction/NewPartReaction.js create mode 100644 web/src/components/NewUser/NewUser.js create mode 100644 web/src/components/Part/Part.js create mode 100644 web/src/components/PartCell/PartCell.js delete mode 100644 web/src/components/PartForm/ImageUploader.js create mode 100644 web/src/components/PartForm/PartForm.js create mode 100644 web/src/components/PartReaction/PartReaction.js create mode 100644 web/src/components/PartReactionCell/PartReactionCell.js create mode 100644 web/src/components/PartReactionForm/PartReactionForm.js create mode 100644 web/src/components/PartReactions/PartReactions.js create mode 100644 web/src/components/PartReactionsCell/PartReactionsCell.js create mode 100644 web/src/components/Parts/Parts.js create mode 100644 web/src/components/PartsCell/PartsCell.js create mode 100644 web/src/components/User/User.js create mode 100644 web/src/components/UserCell/UserCell.js create mode 100644 web/src/components/UserForm/UserForm.js create mode 100644 web/src/components/Users/Users.js create mode 100644 web/src/components/UsersCell/UsersCell.js create mode 100644 web/src/layouts/CommentsLayout/CommentsLayout.js create mode 100644 web/src/layouts/PartReactionsLayout/PartReactionsLayout.js create mode 100644 web/src/layouts/PartsLayout/PartsLayout.js create mode 100644 web/src/layouts/UsersLayout/UsersLayout.js create mode 100644 web/src/pages/CommentPage/CommentPage.js create mode 100644 web/src/pages/CommentsPage/CommentsPage.js create mode 100644 web/src/pages/EditCommentPage/EditCommentPage.js create mode 100644 web/src/pages/EditPartPage/EditPartPage.js create mode 100644 web/src/pages/EditPartReactionPage/EditPartReactionPage.js create mode 100644 web/src/pages/EditUserPage/EditUserPage.js create mode 100644 web/src/pages/NewCommentPage/NewCommentPage.js create mode 100644 web/src/pages/NewPartPage/NewPartPage.js create mode 100644 web/src/pages/NewPartReactionPage/NewPartReactionPage.js create mode 100644 web/src/pages/NewUserPage/NewUserPage.js create mode 100644 web/src/pages/PartPage/PartPage.js create mode 100644 web/src/pages/PartReactionPage/PartReactionPage.js create mode 100644 web/src/pages/PartReactionsPage/PartReactionsPage.js create mode 100644 web/src/pages/PartsPage/PartsPage.js create mode 100644 web/src/pages/UserPage/UserPage.js create mode 100644 web/src/pages/UsersPage/UsersPage.js diff --git a/api/prisma/migrations/20201009213512-create-posts/README.md b/api/prisma/migrations/20201009213512-create-posts/README.md deleted file mode 100644 index f52912a..0000000 --- a/api/prisma/migrations/20201009213512-create-posts/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Migration `20201009213512-create-posts` - -This migration has been generated by Kurt Hutten at 10/10/2020, 8:35:12 AM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -## Database Steps - -```sql -CREATE TABLE "Post" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "title" TEXT NOT NULL, - "body" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -) -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration ..20201009213512-create-posts ---- datamodel.dml -+++ datamodel.dml -@@ -1,0 +1,18 @@ -+datasource DS { -+ // optionally set multiple providers -+ // example: provider = ["sqlite", "postgresql"] -+ provider = "sqlite" -+ url = "***" -+} -+ -+generator client { -+ provider = "prisma-client-js" -+ binaryTargets = "native" -+} -+ -+model Post { -+ id Int @id @default(autoincrement()) -+ title String -+ body String -+ createdAt DateTime @default(now()) -+} -``` - - diff --git a/api/prisma/migrations/20201009213512-create-posts/schema.prisma b/api/prisma/migrations/20201009213512-create-posts/schema.prisma deleted file mode 100644 index 624cbdb..0000000 --- a/api/prisma/migrations/20201009213512-create-posts/schema.prisma +++ /dev/null @@ -1,18 +0,0 @@ -datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" - url = "***" -} - -generator client { - provider = "prisma-client-js" - binaryTargets = "native" -} - -model Post { - id Int @id @default(autoincrement()) - title String - body String - createdAt DateTime @default(now()) -} diff --git a/api/prisma/migrations/20201009213512-create-posts/steps.json b/api/prisma/migrations/20201009213512-create-posts/steps.json deleted file mode 100644 index f2edc88..0000000 --- a/api/prisma/migrations/20201009213512-create-posts/steps.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "version": "0.3.14-fixed", - "steps": [ - { - "tag": "CreateSource", - "source": "DS" - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Source", - "source": "DS" - }, - "argument": "provider", - "value": "\"sqlite\"" - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Source", - "source": "DS" - }, - "argument": "url", - "value": "\"***\"" - }, - { - "tag": "CreateModel", - "model": "Post" - }, - { - "tag": "CreateField", - "model": "Post", - "field": "id", - "type": "Int", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Post", - "field": "id" - }, - "directive": "id" - } - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Post", - "field": "id" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Post", - "field": "id" - }, - "directive": "default" - }, - "argument": "", - "value": "autoincrement()" - }, - { - "tag": "CreateField", - "model": "Post", - "field": "title", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateField", - "model": "Post", - "field": "body", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateField", - "model": "Post", - "field": "createdAt", - "type": "DateTime", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Post", - "field": "createdAt" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Post", - "field": "createdAt" - }, - "directive": "default" - }, - "argument": "", - "value": "now()" - } - ] -} \ No newline at end of file diff --git a/api/prisma/migrations/20201011043647-create-parts/README.md b/api/prisma/migrations/20201011043647-create-parts/README.md deleted file mode 100644 index 1def1c5..0000000 --- a/api/prisma/migrations/20201011043647-create-parts/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# Migration `20201011043647-create-parts` - -This migration has been generated by Kurt Hutten at 10/11/2020, 3:36:47 PM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -## Database Steps - -```sql -CREATE TABLE "Part" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "title" TEXT NOT NULL, - "description" TEXT NOT NULL, - "mainImage" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -) -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration 20201009213512-create-posts..20201011043647-create-parts ---- datamodel.dml -+++ datamodel.dml -@@ -1,9 +1,9 @@ - datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" -- url = "***" -+ url = "***" - } - generator client { - provider = "prisma-client-js" -@@ -15,4 +15,14 @@ - title String - body String - createdAt DateTime @default(now()) - } -+ -+model Part { -+ id Int @id @default(autoincrement()) -+ title String -+ description String // markdown string -+ mainImage String // link to cloudinary -+ createdAt DateTime @default(now()) -+ // userId -+ //likes, comments, reactions -+} -``` - - diff --git a/api/prisma/migrations/20201011043647-create-parts/schema.prisma b/api/prisma/migrations/20201011043647-create-parts/schema.prisma deleted file mode 100644 index 6d2b834..0000000 --- a/api/prisma/migrations/20201011043647-create-parts/schema.prisma +++ /dev/null @@ -1,28 +0,0 @@ -datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" - url = "***" -} - -generator client { - provider = "prisma-client-js" - binaryTargets = "native" -} - -model Post { - id Int @id @default(autoincrement()) - title String - body String - createdAt DateTime @default(now()) -} - -model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -} diff --git a/api/prisma/migrations/20201011043647-create-parts/steps.json b/api/prisma/migrations/20201011043647-create-parts/steps.json deleted file mode 100644 index 3328ce6..0000000 --- a/api/prisma/migrations/20201011043647-create-parts/steps.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "version": "0.3.14-fixed", - "steps": [ - { - "tag": "CreateModel", - "model": "Part" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "id", - "type": "Int", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "id" - }, - "directive": "id" - } - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "id" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "id" - }, - "directive": "default" - }, - "argument": "", - "value": "autoincrement()" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "title", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "description", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "mainImage", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "createdAt", - "type": "DateTime", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "createdAt" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "createdAt" - }, - "directive": "default" - }, - "argument": "", - "value": "now()" - } - ] -} \ No newline at end of file diff --git a/api/prisma/migrations/20201011052155-add-code-to-part/README.md b/api/prisma/migrations/20201011052155-add-code-to-part/README.md deleted file mode 100644 index ffbd7bc..0000000 --- a/api/prisma/migrations/20201011052155-add-code-to-part/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Migration `20201011052155-add-code-to-part` - -This migration has been generated by Kurt Hutten at 10/11/2020, 4:21:55 PM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -## Database Steps - -```sql -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_Part" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "title" TEXT NOT NULL, - "description" TEXT NOT NULL, - "code" TEXT NOT NULL DEFAULT '// Welcome to Cascade Studio! Here are some useful functions: -// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection() -// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon() -// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(), -// FilletEdges(), ChamferEdges(), -// Slider(), Button(), Checkbox() -let holeRadius = Slider("Radius", 30 , 20 , 40); -let sphere = Sphere(50); -let cylinderZ = Cylinder(holeRadius, 200, true);/nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true)); -let cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));/nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ])); - -Translate([-25, 0, 40], Text3D("Hi!"));/n// Don''t forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!', - "mainImage" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); -INSERT INTO "new_Part" ("id", "title", "description", "mainImage", "createdAt") SELECT "id", "title", "description", "mainImage", "createdAt" FROM "Part"; -DROP TABLE "Part"; -ALTER TABLE "new_Part" RENAME TO "Part"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration 20201011043647-create-parts..20201011052155-add-code-to-part ---- datamodel.dml -+++ datamodel.dml -@@ -1,9 +1,9 @@ - datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" -- url = "***" -+ url = "***" - } - generator client { - provider = "prisma-client-js" -@@ -20,8 +20,9 @@ - model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string -+ code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);/nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));/nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));/n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -``` - - diff --git a/api/prisma/migrations/20201011052155-add-code-to-part/schema.prisma b/api/prisma/migrations/20201011052155-add-code-to-part/schema.prisma deleted file mode 100644 index 41ca83b..0000000 --- a/api/prisma/migrations/20201011052155-add-code-to-part/schema.prisma +++ /dev/null @@ -1,29 +0,0 @@ -datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" - url = "***" -} - -generator client { - provider = "prisma-client-js" - binaryTargets = "native" -} - -model Post { - id Int @id @default(autoincrement()) - title String - body String - createdAt DateTime @default(now()) -} - -model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string - code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);/nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));/nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));/n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -} diff --git a/api/prisma/migrations/20201011052155-add-code-to-part/steps.json b/api/prisma/migrations/20201011052155-add-code-to-part/steps.json deleted file mode 100644 index 0c8bd6f..0000000 --- a/api/prisma/migrations/20201011052155-add-code-to-part/steps.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "version": "0.3.14-fixed", - "steps": [ - { - "tag": "CreateField", - "model": "Part", - "field": "code", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "code" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "code" - }, - "directive": "default" - }, - "argument": "", - "value": "\"// Welcome to Cascade Studio! Here are some useful functions:\\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\\n// FilletEdges(), ChamferEdges(),\\n// Slider(), Button(), Checkbox()\\nlet holeRadius = Slider(\\\"Radius\\\", 30 , 20 , 40);\\nlet sphere = Sphere(50);\\nlet cylinderZ = Cylinder(holeRadius, 200, true);/nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));/nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\\n\\nTranslate([-25, 0, 40], Text3D(\\\"Hi!\\\"));/n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!\"" - } - ] -} \ No newline at end of file diff --git a/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/README.md b/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/README.md deleted file mode 100644 index 1e30c97..0000000 --- a/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Migration `20201011082558-add-code-not-needed-upon-create` - -This migration has been generated by Kurt Hutten at 10/11/2020, 7:25:58 PM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -## Database Steps - -```sql -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_Part" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "title" TEXT NOT NULL, - "description" TEXT NOT NULL, - "code" TEXT NOT NULL DEFAULT '// Welcome to Cascade Studio! Here are some useful functions: -// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection() -// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon() -// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(), -// FilletEdges(), ChamferEdges(), -// Slider(), Button(), Checkbox() -let holeRadius = Slider("Radius", 30 , 20 , 40); -let sphere = Sphere(50); -let cylinderZ = Cylinder(holeRadius, 200, true); -let cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true)); -let cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true)); -Translate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ])); - -Translate([-25, 0, 40], Text3D("Hi!")); -// Don''t forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!', - "mainImage" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -); -INSERT INTO "new_Part" ("id", "title", "description", "mainImage", "createdAt", "code") SELECT "id", "title", "description", "mainImage", "createdAt", "code" FROM "Part"; -DROP TABLE "Part"; -ALTER TABLE "new_Part" RENAME TO "Part"; -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration 20201011052155-add-code-to-part..20201011082558-add-code-not-needed-upon-create ---- datamodel.dml -+++ datamodel.dml -@@ -1,9 +1,9 @@ - datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" -- url = "***" -+ url = "***" - } - generator client { - provider = "prisma-client-js" -@@ -20,9 +20,9 @@ - model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string -- code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);/nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));/nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));/n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") -+ code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -``` - - diff --git a/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/schema.prisma b/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/schema.prisma deleted file mode 100644 index f22b4b7..0000000 --- a/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/schema.prisma +++ /dev/null @@ -1,29 +0,0 @@ -datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" - url = "***" -} - -generator client { - provider = "prisma-client-js" - binaryTargets = "native" -} - -model Post { - id Int @id @default(autoincrement()) - title String - body String - createdAt DateTime @default(now()) -} - -model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string - code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -} diff --git a/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/steps.json b/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/steps.json deleted file mode 100644 index 8c127a5..0000000 --- a/api/prisma/migrations/20201011082558-add-code-not-needed-upon-create/steps.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "0.3.14-fixed", - "steps": [ - { - "tag": "UpdateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "code" - }, - "directive": "default" - }, - "argument": "", - "newValue": "\"// Welcome to Cascade Studio! Here are some useful functions:\\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\\n// FilletEdges(), ChamferEdges(),\\n// Slider(), Button(), Checkbox()\\nlet holeRadius = Slider(\\\"Radius\\\", 30 , 20 , 40);\\nlet sphere = Sphere(50);\\nlet cylinderZ = Cylinder(holeRadius, 200, true);\\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\\n\\nTranslate([-25, 0, 40], Text3D(\\\"Hi!\\\"));\\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!\"" - } - ] -} \ No newline at end of file diff --git a/api/prisma/migrations/20201011095227-create-contact/README.md b/api/prisma/migrations/20201011095227-create-contact/README.md deleted file mode 100644 index 5748d5e..0000000 --- a/api/prisma/migrations/20201011095227-create-contact/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Migration `20201011095227-create-contact` - -This migration has been generated by Kurt Hutten at 10/11/2020, 8:52:27 PM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -## Database Steps - -```sql -CREATE TABLE "Contact" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "name" TEXT NOT NULL, - "email" TEXT NOT NULL, - "message" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP -) -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration 20201011082558-add-code-not-needed-upon-create..20201011095227-create-contact ---- datamodel.dml -+++ datamodel.dml -@@ -1,9 +1,9 @@ - datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" -- url = "***" -+ url = "***" - } - generator client { - provider = "prisma-client-js" -@@ -26,4 +26,12 @@ - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions - } -+ -+model Contact { -+ id Int @id @default(autoincrement()) -+ name String -+ email String -+ message String -+ createdAt DateTime @default(now()) -+} -``` - - diff --git a/api/prisma/migrations/20201011095227-create-contact/schema.prisma b/api/prisma/migrations/20201011095227-create-contact/schema.prisma deleted file mode 100644 index 03189f2..0000000 --- a/api/prisma/migrations/20201011095227-create-contact/schema.prisma +++ /dev/null @@ -1,37 +0,0 @@ -datasource DS { - // optionally set multiple providers - // example: provider = ["sqlite", "postgresql"] - provider = "sqlite" - url = "***" -} - -generator client { - provider = "prisma-client-js" - binaryTargets = "native" -} - -model Post { - id Int @id @default(autoincrement()) - title String - body String - createdAt DateTime @default(now()) -} - -model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string - code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -} - -model Contact { - id Int @id @default(autoincrement()) - name String - email String - message String - createdAt DateTime @default(now()) -} diff --git a/api/prisma/migrations/20201011095227-create-contact/steps.json b/api/prisma/migrations/20201011095227-create-contact/steps.json deleted file mode 100644 index 0ca4b72..0000000 --- a/api/prisma/migrations/20201011095227-create-contact/steps.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "version": "0.3.14-fixed", - "steps": [ - { - "tag": "CreateModel", - "model": "Contact" - }, - { - "tag": "CreateField", - "model": "Contact", - "field": "id", - "type": "Int", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Contact", - "field": "id" - }, - "directive": "id" - } - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Contact", - "field": "id" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Contact", - "field": "id" - }, - "directive": "default" - }, - "argument": "", - "value": "autoincrement()" - }, - { - "tag": "CreateField", - "model": "Contact", - "field": "name", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateField", - "model": "Contact", - "field": "email", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateField", - "model": "Contact", - "field": "message", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateField", - "model": "Contact", - "field": "createdAt", - "type": "DateTime", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Contact", - "field": "createdAt" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Contact", - "field": "createdAt" - }, - "directive": "default" - }, - "argument": "", - "value": "now()" - } - ] -} \ No newline at end of file diff --git a/api/prisma/migrations/20201018233330-add-simple-user-model/README.md b/api/prisma/migrations/20201018233330-add-simple-user-model/README.md deleted file mode 100644 index c8ec755..0000000 --- a/api/prisma/migrations/20201018233330-add-simple-user-model/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Migration `20201018233330-add-simple-user-model` - -This migration has been generated by Kurt Hutten at 10/19/2020, 10:33:30 AM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -## Database Steps - -```sql -CREATE TABLE "User" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "userName" TEXT NOT NULL, - "email" TEXT NOT NULL, - "issuer" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "image" TEXT, - "bio" TEXT -) - -CREATE UNIQUE INDEX "User.userName_unique" ON "User"("userName") - -CREATE UNIQUE INDEX "User.email_unique" ON "User"("email") - -CREATE UNIQUE INDEX "User.issuer_unique" ON "User"("issuer") -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration 20201011095227-create-contact..20201018233330-add-simple-user-model ---- datamodel.dml -+++ datamodel.dml -@@ -1,9 +1,7 @@ - datasource DS { -- // optionally set multiple providers -- // example: provider = ["sqlite", "postgresql"] -- provider = "sqlite" -- url = "***" -+ provider = ["sqlite", "postgresql"] -+ url = "***" - } - generator client { - provider = "prisma-client-js" -@@ -34,4 +32,17 @@ - email String - message String - createdAt DateTime @default(now()) - } -+ -+model User { -+ id Int @id @default(autoincrement()) -+ userName String @unique -+ email String @unique -+ issuer String @unique -+ -+ createdAt DateTime @default(now()) -+ updatedAt DateTime @updatedAt -+ -+ image String? // url maybe id or file storage service? cloudinary? -+ bio String? //mark down -+} -``` - - diff --git a/api/prisma/migrations/20201018233330-add-simple-user-model/schema.prisma b/api/prisma/migrations/20201018233330-add-simple-user-model/schema.prisma deleted file mode 100644 index 15e3468..0000000 --- a/api/prisma/migrations/20201018233330-add-simple-user-model/schema.prisma +++ /dev/null @@ -1,48 +0,0 @@ -datasource DS { - provider = ["sqlite", "postgresql"] - url = "***" -} - -generator client { - provider = "prisma-client-js" - binaryTargets = "native" -} - -model Post { - id Int @id @default(autoincrement()) - title String - body String - createdAt DateTime @default(now()) -} - -model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string - code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -} - -model Contact { - id Int @id @default(autoincrement()) - name String - email String - message String - createdAt DateTime @default(now()) -} - -model User { - id Int @id @default(autoincrement()) - userName String @unique - email String @unique - issuer String @unique - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - image String? // url maybe id or file storage service? cloudinary? - bio String? //mark down -} diff --git a/api/prisma/migrations/20201018233330-add-simple-user-model/steps.json b/api/prisma/migrations/20201018233330-add-simple-user-model/steps.json deleted file mode 100644 index 8ea741d..0000000 --- a/api/prisma/migrations/20201018233330-add-simple-user-model/steps.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "version": "0.3.14-fixed", - "steps": [ - { - "tag": "UpdateArgument", - "location": { - "tag": "Source", - "source": "DS" - }, - "argument": "provider", - "newValue": "[\"sqlite\", \"postgresql\"]" - }, - { - "tag": "CreateModel", - "model": "User" - }, - { - "tag": "CreateField", - "model": "User", - "field": "id", - "type": "Int", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "id" - }, - "directive": "id" - } - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "id" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "User", - "field": "id" - }, - "directive": "default" - }, - "argument": "", - "value": "autoincrement()" - }, - { - "tag": "CreateField", - "model": "User", - "field": "userName", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "userName" - }, - "directive": "unique" - } - }, - { - "tag": "CreateField", - "model": "User", - "field": "email", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "email" - }, - "directive": "unique" - } - }, - { - "tag": "CreateField", - "model": "User", - "field": "issuer", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "issuer" - }, - "directive": "unique" - } - }, - { - "tag": "CreateField", - "model": "User", - "field": "createdAt", - "type": "DateTime", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "createdAt" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "User", - "field": "createdAt" - }, - "directive": "default" - }, - "argument": "", - "value": "now()" - }, - { - "tag": "CreateField", - "model": "User", - "field": "updatedAt", - "type": "DateTime", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "updatedAt" - }, - "directive": "updatedAt" - } - }, - { - "tag": "CreateField", - "model": "User", - "field": "image", - "type": "String", - "arity": "Optional" - }, - { - "tag": "CreateField", - "model": "User", - "field": "bio", - "type": "String", - "arity": "Optional" - } - ] -} \ No newline at end of file diff --git a/api/prisma/migrations/20201019072122-add-simplify-user-model/README.md b/api/prisma/migrations/20201019072122-add-simplify-user-model/README.md deleted file mode 100644 index 29d4e11..0000000 --- a/api/prisma/migrations/20201019072122-add-simplify-user-model/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Migration `20201019072122-add-simplify-user-model` - -This migration has been generated by Kurt Hutten at 10/19/2020, 6:21:22 PM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -## Database Steps - -```sql -DROP INDEX "User.issuer_unique" - -DROP INDEX "User.userName_unique" - -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_User" ( - "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - "email" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "image" TEXT, - "bio" TEXT -); -INSERT INTO "new_User" ("id", "email", "createdAt", "updatedAt", "image", "bio") SELECT "id", "email", "createdAt", "updatedAt", "image", "bio" FROM "User"; -DROP TABLE "User"; -ALTER TABLE "new_User" RENAME TO "User"; -CREATE UNIQUE INDEX "User.email_unique" ON "User"("email"); -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration 20201018233330-add-simple-user-model..20201019072122-add-simplify-user-model ---- datamodel.dml -+++ datamodel.dml -@@ -1,7 +1,7 @@ - datasource DS { - provider = ["sqlite", "postgresql"] -- url = "***" -+ url = "***" - } - generator client { - provider = "prisma-client-js" -@@ -34,12 +34,12 @@ - createdAt DateTime @default(now()) - } - model User { -- id Int @id @default(autoincrement()) -- userName String @unique -- email String @unique -- issuer String @unique -+ id Int @id @default(autoincrement()) -+ email String @unique -+ // userName String @unique -+ // issuer String @unique - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt -``` - - diff --git a/api/prisma/migrations/20201019072122-add-simplify-user-model/schema.prisma b/api/prisma/migrations/20201019072122-add-simplify-user-model/schema.prisma deleted file mode 100644 index 24140d8..0000000 --- a/api/prisma/migrations/20201019072122-add-simplify-user-model/schema.prisma +++ /dev/null @@ -1,48 +0,0 @@ -datasource DS { - provider = ["sqlite", "postgresql"] - url = "***" -} - -generator client { - provider = "prisma-client-js" - binaryTargets = "native" -} - -model Post { - id Int @id @default(autoincrement()) - title String - body String - createdAt DateTime @default(now()) -} - -model Part { - id Int @id @default(autoincrement()) - title String - description String // markdown string - code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") - mainImage String // link to cloudinary - createdAt DateTime @default(now()) - // userId - //likes, comments, reactions -} - -model Contact { - id Int @id @default(autoincrement()) - name String - email String - message String - createdAt DateTime @default(now()) -} - -model User { - id Int @id @default(autoincrement()) - email String @unique - // userName String @unique - // issuer String @unique - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - image String? // url maybe id or file storage service? cloudinary? - bio String? //mark down -} diff --git a/api/prisma/migrations/20201019072122-add-simplify-user-model/steps.json b/api/prisma/migrations/20201019072122-add-simplify-user-model/steps.json deleted file mode 100644 index 0285263..0000000 --- a/api/prisma/migrations/20201019072122-add-simplify-user-model/steps.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "version": "0.3.14-fixed", - "steps": [ - { - "tag": "DeleteField", - "model": "User", - "field": "userName" - }, - { - "tag": "DeleteField", - "model": "User", - "field": "issuer" - } - ] -} \ No newline at end of file diff --git a/api/prisma/migrations/20201029214206-rejig-schema/README.md b/api/prisma/migrations/20201029214206-rejig-schema/README.md deleted file mode 100644 index 3014ffa..0000000 --- a/api/prisma/migrations/20201029214206-rejig-schema/README.md +++ /dev/null @@ -1,188 +0,0 @@ -# Migration `20201029214206-rejig-schema` - -This migration has been generated by Kurt Hutten at 10/30/2020, 8:42:06 AM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -# explanation - -The previous schema was really just thrown together to progress with parts of the client. -No relations had been included so this change in reality can be consider the initial schema. - -## Database Steps - -```sql -CREATE TABLE "PartReaction" ( - "emote" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "partId" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - - FOREIGN KEY ("userId") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY ("partId") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE -) - -CREATE TABLE "Comment" ( - "id" TEXT NOT NULL, - "text" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - - FOREIGN KEY ("id") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY ("id") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE, -PRIMARY KEY ("id") -) - -PRAGMA foreign_keys=OFF; -CREATE TABLE "new_Part" ( - "id" TEXT NOT NULL, - "title" TEXT NOT NULL, - "description" TEXT, - "code" TEXT, - "mainImage" TEXT, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "authorUserName" TEXT NOT NULL DEFAULT 'irevdev', - - FOREIGN KEY ("authorUserName") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, -PRIMARY KEY ("title","authorUserName") -); -INSERT INTO "new_Part" ("id", "title", "description", "mainImage", "createdAt", "code") SELECT "id", "title", "description", "mainImage", "createdAt", "code" FROM "Part"; -DROP TABLE "Part"; -ALTER TABLE "new_Part" RENAME TO "Part"; -CREATE UNIQUE INDEX "Part.id_unique" ON "Part"("id"); -CREATE UNIQUE INDEX "Part.title_authorUserName_unique" ON "Part"("title", "authorUserName"); -CREATE TABLE "new_User" ( - "userName" TEXT NOT NULL DEFAULT 'irevdev', - "email" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "image" TEXT, - "bio" TEXT, -PRIMARY KEY ("userName") -); -INSERT INTO "new_User" ("email", "createdAt", "updatedAt", "image", "bio") SELECT "email", "createdAt", "updatedAt", "image", "bio" FROM "User"; -DROP TABLE "User"; -ALTER TABLE "new_User" RENAME TO "User"; -CREATE UNIQUE INDEX "User.email_unique" ON "User"("email"); -PRAGMA foreign_key_check; -PRAGMA foreign_keys=ON - -CREATE UNIQUE INDEX "PartReaction.emote_userId_partId_unique" ON "PartReaction"("emote", "userId", "partId") - -PRAGMA foreign_keys=off; -DROP TABLE "Post"; -PRAGMA foreign_keys=on - -PRAGMA foreign_keys=off; -DROP TABLE "Contact"; -PRAGMA foreign_keys=on -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration 20201019072122-add-simplify-user-model..20201029214206-rejig-schema ---- datamodel.dml -+++ datamodel.dml -@@ -1,48 +1,76 @@ - datasource DS { - provider = ["sqlite", "postgresql"] -- url = "***" -+ url = "***" - } - generator client { - provider = "prisma-client-js" - binaryTargets = "native" - } --model Post { -- id Int @id @default(autoincrement()) -- title String -- body String -+// sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode -+// enum Role { -+// USER -+// ADMIN -+// } -+ -+// enum PartType { -+// CASCADESTUDIO -+// JSCAD -+// } -+ -+model User { -+ userName String @id @default("irevdev") -+ email String @unique -+ // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev -+ // maybe let netlify handle roles for now. -+ // role String @default("user") -+ - createdAt DateTime @default(now()) -+ updatedAt DateTime @updatedAt -+ -+ image String? // url maybe id or file storage service? cloudinary? -+ bio String? //mark down -+ Part Part[] -+ Reaction PartReaction[] -+ Comment Comment[] - } - model Part { -- id Int @id @default(autoincrement()) -- title String -- description String // markdown string -- code String @default("// Welcome to Cascade Studio! Here are some useful functions:\n// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()\n// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()\n// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),\n// FilletEdges(), ChamferEdges(),\n// Slider(), Button(), Checkbox()\nlet holeRadius = Slider(\"Radius\", 30 , 20 , 40);\nlet sphere = Sphere(50);\nlet cylinderZ = Cylinder(holeRadius, 200, true);\nlet cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));\nlet cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));\nTranslate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));\n\nTranslate([-25, 0, 40], Text3D(\"Hi!\"));\n// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!") -- mainImage String // link to cloudinary -- createdAt DateTime @default(now()) -- // userId -- //likes, comments, reactions -+ id String @unique @default(uuid()) -+ title String -+ description String? // markdown string -+ code String? -+ mainImage String? // link to cloudinary -+ createdAt DateTime @default(now()) -+ updatedAt DateTime @default(now()) @updatedAt -+ author User @relation(fields: [authorUserName], references: [userName]) -+ authorUserName String @default("irevdev") -+ -+ Comment Comment[] -+ Reaction PartReaction[] -+ @@id([title, authorUserName]) -+ @@unique([title, authorUserName]) - } --model Contact { -- id Int @id @default(autoincrement()) -- name String -- email String -- message String -+model PartReaction { -+ emote String // an emoji -+ userId String -+ user User @relation(fields: [userId], references: [userName]) -+ partId String -+ part Part @relation(fields: [partId], references: [id]) -+ - createdAt DateTime @default(now()) -+ updatedAt DateTime @updatedAt -+ @@unique([emote, userId, partId]) - } --model User { -- id Int @id @default(autoincrement()) -- email String @unique -- // userName String @unique -- // issuer String @unique -+model Comment { -+ id String @id @default(uuid()) -+ text String // the comment, should I allow mark down? -+ user User @relation(fields: [id], references: [userName]) -+ part Part @relation(fields: [id], references: [id]) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt -- -- image String? // url maybe id or file storage service? cloudinary? -- bio String? //mark down - } -``` - - diff --git a/api/prisma/migrations/20201029214206-rejig-schema/schema.prisma b/api/prisma/migrations/20201029214206-rejig-schema/schema.prisma deleted file mode 100644 index cfd2660..0000000 --- a/api/prisma/migrations/20201029214206-rejig-schema/schema.prisma +++ /dev/null @@ -1,76 +0,0 @@ -datasource DS { - provider = ["sqlite", "postgresql"] - url = "***" -} - -generator client { - provider = "prisma-client-js" - binaryTargets = "native" -} - -// sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode -// enum Role { -// USER -// ADMIN -// } - -// enum PartType { -// CASCADESTUDIO -// JSCAD -// } - -model User { - userName String @id @default(uuid()) - email String @unique - // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev - // maybe let netlify handle roles for now. - // role String @default("user") - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - image String? // url maybe id or file storage service? cloudinary? - bio String? //mark down - Part Part[] - Reaction PartReaction[] - Comment Comment[] -} - -model Part { - id String @unique @default(uuid()) - title String - description String? // markdown string - code String? - mainImage String? // link to cloudinary - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - author User @relation(fields: [authorUserName], references: [userName]) - authorUserName String - - Comment Comment[] - Reaction PartReaction[] - @@id([title, authorUserName]) - @@unique([title, authorUserName]) -} - -model PartReaction { - emote String // an emoji - userId String - user User @relation(fields: [userId], references: [userName]) - partId String - part Part @relation(fields: [partId], references: [id]) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - @@unique([emote, userId, partId]) -} - -model Comment { - id String @id @default(uuid()) - text String // the comment, should I allow mark down? - user User @relation(fields: [id], references: [userName]) - part Part @relation(fields: [id], references: [id]) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt -} diff --git a/api/prisma/migrations/20201030061957-rejig-schema/README.md b/api/prisma/migrations/20201030061957-rejig-schema/README.md deleted file mode 100644 index 45e5d74..0000000 --- a/api/prisma/migrations/20201030061957-rejig-schema/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# Migration `20201030061957-rejig-schema` - -This migration has been generated by Kurt Hutten at 10/30/2020, 5:19:57 PM. -You can check out the [state of the schema](./schema.prisma) after the migration. - -## Database Steps - -```sql -CREATE TABLE "User" ( - "userName" TEXT NOT NULL, - "email" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "image" TEXT, - "bio" TEXT, -PRIMARY KEY ("userName") -) - -CREATE TABLE "Part" ( - "id" TEXT NOT NULL, - "title" TEXT NOT NULL, - "description" TEXT, - "code" TEXT, - "mainImage" TEXT, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - "authorUserName" TEXT NOT NULL, - - FOREIGN KEY ("authorUserName") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, -PRIMARY KEY ("title","authorUserName") -) - -CREATE TABLE "PartReaction" ( - "emote" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "partId" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - - FOREIGN KEY ("userId") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY ("partId") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE -) - -CREATE TABLE "Comment" ( - "id" TEXT NOT NULL, - "text" TEXT NOT NULL, - "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" DATETIME NOT NULL, - - FOREIGN KEY ("id") REFERENCES "User"("userName") ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY ("id") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE, -PRIMARY KEY ("id") -) - -CREATE UNIQUE INDEX "User.email_unique" ON "User"("email") - -CREATE UNIQUE INDEX "Part.id_unique" ON "Part"("id") - -CREATE UNIQUE INDEX "Part.title_authorUserName_unique" ON "Part"("title", "authorUserName") - -CREATE UNIQUE INDEX "PartReaction.emote_userId_partId_unique" ON "PartReaction"("emote", "userId", "partId") -``` - -## Changes - -```diff -diff --git schema.prisma schema.prisma -migration 20201029214206-rejig-schema..20201030061957-rejig-schema ---- datamodel.dml -+++ datamodel.dml -@@ -1,7 +1,7 @@ - datasource DS { - provider = ["sqlite", "postgresql"] -- url = "***" -+ url = "***" - } - generator client { - provider = "prisma-client-js" -@@ -19,9 +19,9 @@ - // JSCAD - // } - model User { -- userName String @id @default(uuid()) -+ userName String @id - email String @unique - // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev - // maybe let netlify handle roles for now. - // role String @default("user") -``` - - diff --git a/api/prisma/migrations/20201030061957-rejig-schema/steps.json b/api/prisma/migrations/20201030061957-rejig-schema/steps.json deleted file mode 100644 index 17d5f9e..0000000 --- a/api/prisma/migrations/20201030061957-rejig-schema/steps.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "version": "0.3.14-fixed", - "steps": [ - { - "tag": "DeleteDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "updatedAt" - }, - "directive": "default" - } - }, - { - "tag": "DeleteDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "authorUserName" - }, - "directive": "default" - } - }, - { - "tag": "DeleteDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "userName" - }, - "directive": "default" - } - } - ] -} \ No newline at end of file diff --git a/api/prisma/migrations/20201101183848-db-init/README.md b/api/prisma/migrations/20201101183848-db-init/README.md new file mode 100644 index 0000000..29cd885 --- /dev/null +++ b/api/prisma/migrations/20201101183848-db-init/README.md @@ -0,0 +1,158 @@ +# Migration `20201101183848-db-init` + +This migration has been generated by Kurt Hutten at 11/2/2020, 5:38:48 AM. +You can check out the [state of the schema](./schema.prisma) after the migration. + +## Database Steps + +```sql +CREATE TABLE "User" ( + "id" TEXT NOT NULL, + "userName" TEXT NOT NULL, + "email" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + "image" TEXT, + "bio" TEXT, +PRIMARY KEY ("id") +) + +CREATE TABLE "Part" ( + "id" TEXT NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "code" TEXT, + "mainImage" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + "userId" TEXT NOT NULL, + + FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE, +PRIMARY KEY ("id") +) + +CREATE TABLE "PartReaction" ( + "id" TEXT NOT NULL, + "emote" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "partId" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + + FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY ("partId") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE, +PRIMARY KEY ("id") +) + +CREATE TABLE "Comment" ( + "id" TEXT NOT NULL, + "text" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "partId" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + + FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY ("partId") REFERENCES "Part"("id") ON DELETE CASCADE ON UPDATE CASCADE, +PRIMARY KEY ("id") +) + +CREATE UNIQUE INDEX "User.userName_unique" ON "User"("userName") + +CREATE UNIQUE INDEX "User.email_unique" ON "User"("email") + +CREATE UNIQUE INDEX "Part.title_userId_unique" ON "Part"("title", "userId") + +CREATE UNIQUE INDEX "PartReaction.emote_userId_partId_unique" ON "PartReaction"("emote", "userId", "partId") +``` + +## Changes + +```diff +diff --git schema.prisma schema.prisma +migration ..20201101183848-db-init +--- datamodel.dml ++++ datamodel.dml +@@ -1,0 +1,79 @@ ++datasource DS { ++ provider = ["sqlite", "postgresql"] ++ url = "***" ++} ++ ++generator client { ++ provider = "prisma-client-js" ++ binaryTargets = "native" ++} ++ ++// sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode ++// enum Role { ++// USER ++// ADMIN ++// } ++ ++// enum PartType { ++// CASCADESTUDIO ++// JSCAD ++// } ++ ++model User { ++ id String @id @default(uuid()) ++ userName String @unique // reffered to as userId in @relations ++ email String @unique ++ // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev ++ // maybe let netlify handle roles for now. ++ // role String @default("user") ++ ++ createdAt DateTime @default(now()) ++ updatedAt DateTime @updatedAt ++ ++ image String? // url maybe id or file storage service? cloudinary? ++ bio String? //mark down ++ Part Part[] ++ Reaction PartReaction[] ++ Comment Comment[] ++} ++ ++model Part { ++ id String @id @default(uuid()) ++ title String ++ description String? // markdown string ++ code String? ++ mainImage String? // link to cloudinary ++ createdAt DateTime @default(now()) ++ updatedAt DateTime @updatedAt ++ user User @relation(fields: [userId], references: [id]) ++ userId String ++ ++ Comment Comment[] ++ Reaction PartReaction[] ++ @@unique([title, userId]) ++} ++ ++model PartReaction { ++ id String @id @default(uuid()) ++ emote String // an emoji ++ user User @relation(fields: [userId], references: [id]) ++ userId String ++ part Part @relation(fields: [partId], references: [id]) ++ partId String ++ ++ createdAt DateTime @default(now()) ++ updatedAt DateTime @updatedAt ++ @@unique([emote, userId, partId]) ++} ++ ++model Comment { ++ id String @id @default(uuid()) ++ text String // the comment, should I allow mark down? ++ user User @relation(fields: [userId], references: [id]) ++ userId String ++ part Part @relation(fields: [partId], references: [id]) ++ partId String ++ ++ createdAt DateTime @default(now()) ++ updatedAt DateTime @updatedAt ++} +``` + + diff --git a/api/prisma/migrations/20201030061957-rejig-schema/schema.prisma b/api/prisma/migrations/20201101183848-db-init/schema.prisma similarity index 60% rename from api/prisma/migrations/20201030061957-rejig-schema/schema.prisma rename to api/prisma/migrations/20201101183848-db-init/schema.prisma index 5515849..f5d13ba 100644 --- a/api/prisma/migrations/20201030061957-rejig-schema/schema.prisma +++ b/api/prisma/migrations/20201101183848-db-init/schema.prisma @@ -20,7 +20,8 @@ generator client { // } model User { - userName String @id + id String @id @default(uuid()) + userName String @unique // reffered to as userId in @relations email String @unique // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev // maybe let netlify handle roles for now. @@ -37,28 +38,28 @@ model User { } model Part { - id String @unique @default(uuid()) - title String - description String? // markdown string - code String? - mainImage String? // link to cloudinary - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - author User @relation(fields: [authorUserName], references: [userName]) - authorUserName String + id String @id @default(uuid()) + title String + description String? // markdown string + code String? + mainImage String? // link to cloudinary + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + user User @relation(fields: [userId], references: [id]) + userId String Comment Comment[] Reaction PartReaction[] - @@id([title, authorUserName]) - @@unique([title, authorUserName]) + @@unique([title, userId]) } model PartReaction { + id String @id @default(uuid()) emote String // an emoji + user User @relation(fields: [userId], references: [id]) userId String - user User @relation(fields: [userId], references: [userName]) - partId String part Part @relation(fields: [partId], references: [id]) + partId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -66,10 +67,12 @@ model PartReaction { } model Comment { - id String @id @default(uuid()) - text String // the comment, should I allow mark down? - user User @relation(fields: [id], references: [userName]) - part Part @relation(fields: [id], references: [id]) + id String @id @default(uuid()) + text String // the comment, should I allow mark down? + user User @relation(fields: [userId], references: [id]) + userId String + part Part @relation(fields: [partId], references: [id]) + partId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/api/prisma/migrations/20201029214206-rejig-schema/steps.json b/api/prisma/migrations/20201101183848-db-init/steps.json similarity index 77% rename from api/prisma/migrations/20201029214206-rejig-schema/steps.json rename to api/prisma/migrations/20201101183848-db-init/steps.json index a0b86eb..ce0e48a 100644 --- a/api/prisma/migrations/20201029214206-rejig-schema/steps.json +++ b/api/prisma/migrations/20201101183848-db-init/steps.json @@ -1,6 +1,404 @@ { "version": "0.3.14-fixed", "steps": [ + { + "tag": "CreateSource", + "source": "DS" + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Source", + "source": "DS" + }, + "argument": "provider", + "value": "[\"sqlite\", \"postgresql\"]" + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Source", + "source": "DS" + }, + "argument": "url", + "value": "\"***\"" + }, + { + "tag": "CreateModel", + "model": "User" + }, + { + "tag": "CreateField", + "model": "User", + "field": "id", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "id" + }, + "directive": "id" + } + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "id" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "User", + "field": "id" + }, + "directive": "default" + }, + "argument": "", + "value": "uuid()" + }, + { + "tag": "CreateField", + "model": "User", + "field": "userName", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "userName" + }, + "directive": "unique" + } + }, + { + "tag": "CreateField", + "model": "User", + "field": "email", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "email" + }, + "directive": "unique" + } + }, + { + "tag": "CreateField", + "model": "User", + "field": "createdAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "createdAt" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "User", + "field": "createdAt" + }, + "directive": "default" + }, + "argument": "", + "value": "now()" + }, + { + "tag": "CreateField", + "model": "User", + "field": "updatedAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "User", + "field": "updatedAt" + }, + "directive": "updatedAt" + } + }, + { + "tag": "CreateField", + "model": "User", + "field": "image", + "type": "String", + "arity": "Optional" + }, + { + "tag": "CreateField", + "model": "User", + "field": "bio", + "type": "String", + "arity": "Optional" + }, + { + "tag": "CreateField", + "model": "User", + "field": "Part", + "type": "Part", + "arity": "List" + }, + { + "tag": "CreateField", + "model": "User", + "field": "Reaction", + "type": "PartReaction", + "arity": "List" + }, + { + "tag": "CreateField", + "model": "User", + "field": "Comment", + "type": "Comment", + "arity": "List" + }, + { + "tag": "CreateModel", + "model": "Part" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "id", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "id" + }, + "directive": "id" + } + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "id" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "id" + }, + "directive": "default" + }, + "argument": "", + "value": "uuid()" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "title", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "description", + "type": "String", + "arity": "Optional" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "code", + "type": "String", + "arity": "Optional" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "mainImage", + "type": "String", + "arity": "Optional" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "createdAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "createdAt" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "createdAt" + }, + "directive": "default" + }, + "argument": "", + "value": "now()" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "updatedAt", + "type": "DateTime", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "updatedAt" + }, + "directive": "updatedAt" + } + }, + { + "tag": "CreateField", + "model": "Part", + "field": "user", + "type": "User", + "arity": "Required" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "Part", + "field": "user" + }, + "directive": "relation" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "user" + }, + "directive": "relation" + }, + "argument": "fields", + "value": "[userId]" + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "Part", + "field": "user" + }, + "directive": "relation" + }, + "argument": "references", + "value": "[id]" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "userId", + "type": "String", + "arity": "Required" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "Comment", + "type": "Comment", + "arity": "List" + }, + { + "tag": "CreateField", + "model": "Part", + "field": "Reaction", + "type": "PartReaction", + "arity": "List" + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Model", + "model": "Part", + "arguments": [ + { + "name": "", + "value": "[title, userId]" + } + ] + }, + "directive": "unique" + } + }, { "tag": "CreateModel", "model": "PartReaction" @@ -8,14 +406,50 @@ { "tag": "CreateField", "model": "PartReaction", - "field": "emote", + "field": "id", "type": "String", "arity": "Required" }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "id" + }, + "directive": "id" + } + }, + { + "tag": "CreateDirective", + "location": { + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "id" + }, + "directive": "default" + } + }, + { + "tag": "CreateArgument", + "location": { + "tag": "Directive", + "path": { + "tag": "Field", + "model": "PartReaction", + "field": "id" + }, + "directive": "default" + }, + "argument": "", + "value": "uuid()" + }, { "tag": "CreateField", "model": "PartReaction", - "field": "userId", + "field": "emote", "type": "String", "arity": "Required" }, @@ -63,12 +497,12 @@ "directive": "relation" }, "argument": "references", - "value": "[userName]" + "value": "[id]" }, { "tag": "CreateField", "model": "PartReaction", - "field": "partId", + "field": "userId", "type": "String", "arity": "Required" }, @@ -118,6 +552,13 @@ "argument": "references", "value": "[id]" }, + { + "tag": "CreateField", + "model": "PartReaction", + "field": "partId", + "type": "String", + "arity": "Required" + }, { "tag": "CreateField", "model": "PartReaction", @@ -268,7 +709,7 @@ "directive": "relation" }, "argument": "fields", - "value": "[id]" + "value": "[userId]" }, { "tag": "CreateArgument", @@ -282,7 +723,14 @@ "directive": "relation" }, "argument": "references", - "value": "[userName]" + "value": "[id]" + }, + { + "tag": "CreateField", + "model": "Comment", + "field": "userId", + "type": "String", + "arity": "Required" }, { "tag": "CreateField", @@ -314,7 +762,7 @@ "directive": "relation" }, "argument": "fields", - "value": "[id]" + "value": "[partId]" }, { "tag": "CreateArgument", @@ -330,6 +778,13 @@ "argument": "references", "value": "[id]" }, + { + "tag": "CreateField", + "model": "Comment", + "field": "partId", + "type": "String", + "arity": "Required" + }, { "tag": "CreateField", "model": "Comment", @@ -379,328 +834,6 @@ }, "directive": "updatedAt" } - }, - { - "tag": "DeleteModel", - "model": "Post" - }, - { - "tag": "DeleteModel", - "model": "Contact" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "updatedAt", - "type": "DateTime", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "updatedAt" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "updatedAt" - }, - "directive": "default" - }, - "argument": "", - "value": "now()" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "updatedAt" - }, - "directive": "updatedAt" - } - }, - { - "tag": "CreateField", - "model": "Part", - "field": "author", - "type": "User", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "author" - }, - "directive": "relation" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "author" - }, - "directive": "relation" - }, - "argument": "fields", - "value": "[authorUserName]" - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "author" - }, - "directive": "relation" - }, - "argument": "references", - "value": "[userName]" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "authorUserName", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "authorUserName" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "authorUserName" - }, - "directive": "default" - }, - "argument": "", - "value": "\"irevdev\"" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "Comment", - "type": "Comment", - "arity": "List" - }, - { - "tag": "CreateField", - "model": "Part", - "field": "Reaction", - "type": "PartReaction", - "arity": "List" - }, - { - "tag": "UpdateField", - "model": "Part", - "field": "id", - "type": "String" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "id" - }, - "directive": "unique" - } - }, - { - "tag": "UpdateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "Part", - "field": "id" - }, - "directive": "default" - }, - "argument": "", - "newValue": "uuid()" - }, - { - "tag": "DeleteDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "id" - }, - "directive": "id" - } - }, - { - "tag": "UpdateField", - "model": "Part", - "field": "description", - "arity": "Optional" - }, - { - "tag": "UpdateField", - "model": "Part", - "field": "mainImage", - "arity": "Optional" - }, - { - "tag": "UpdateField", - "model": "Part", - "field": "code", - "arity": "Optional" - }, - { - "tag": "DeleteDirective", - "location": { - "path": { - "tag": "Field", - "model": "Part", - "field": "code" - }, - "directive": "default" - } - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Model", - "model": "Part" - }, - "directive": "id" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Model", - "model": "Part" - }, - "directive": "id" - }, - "argument": "", - "value": "[title, authorUserName]" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Model", - "model": "Part", - "arguments": [ - { - "name": "", - "value": "[title, authorUserName]" - } - ] - }, - "directive": "unique" - } - }, - { - "tag": "CreateField", - "model": "User", - "field": "userName", - "type": "String", - "arity": "Required" - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "userName" - }, - "directive": "id" - } - }, - { - "tag": "CreateDirective", - "location": { - "path": { - "tag": "Field", - "model": "User", - "field": "userName" - }, - "directive": "default" - } - }, - { - "tag": "CreateArgument", - "location": { - "tag": "Directive", - "path": { - "tag": "Field", - "model": "User", - "field": "userName" - }, - "directive": "default" - }, - "argument": "", - "value": "\"irevdev\"" - }, - { - "tag": "CreateField", - "model": "User", - "field": "Part", - "type": "Part", - "arity": "List" - }, - { - "tag": "CreateField", - "model": "User", - "field": "Reaction", - "type": "PartReaction", - "arity": "List" - }, - { - "tag": "CreateField", - "model": "User", - "field": "Comment", - "type": "Comment", - "arity": "List" - }, - { - "tag": "DeleteField", - "model": "User", - "field": "id" } ] } \ No newline at end of file diff --git a/api/prisma/migrations/migrate.lock b/api/prisma/migrations/migrate.lock index 66735c0..3d49851 100644 --- a/api/prisma/migrations/migrate.lock +++ b/api/prisma/migrations/migrate.lock @@ -1,11 +1,3 @@ # Prisma Migrate lockfile v1 -20201009213512-create-posts -20201011043647-create-parts -20201011052155-add-code-to-part -20201011082558-add-code-not-needed-upon-create -20201011095227-create-contact -20201018233330-add-simple-user-model -20201019072122-add-simplify-user-model -20201029214206-rejig-schema -20201030061957-rejig-schema \ No newline at end of file +20201101183848-db-init \ No newline at end of file diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index a786c36..a8ac9dc 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -20,7 +20,8 @@ generator client { // } model User { - userName String @id + id String @id @default(uuid()) + userName String @unique // reffered to as userId in @relations email String @unique // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev // maybe let netlify handle roles for now. @@ -37,28 +38,28 @@ model User { } model Part { - id String @unique @default(uuid()) - title String - description String? // markdown string - code String? - mainImage String? // link to cloudinary - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - author User @relation(fields: [authorUserName], references: [userName]) - authorUserName String + id String @id @default(uuid()) + title String + description String? // markdown string + code String? + mainImage String? // link to cloudinary + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + user User @relation(fields: [userId], references: [id]) + userId String Comment Comment[] Reaction PartReaction[] - @@id([title, authorUserName]) - @@unique([title, authorUserName]) + @@unique([title, userId]) } model PartReaction { + id String @id @default(uuid()) emote String // an emoji + user User @relation(fields: [userId], references: [id]) userId String - user User @relation(fields: [userId], references: [userName]) - partId String part Part @relation(fields: [partId], references: [id]) + partId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -66,10 +67,12 @@ model PartReaction { } model Comment { - id String @id @default(uuid()) - text String // the comment, should I allow mark down? - user User @relation(fields: [id], references: [userName]) - part Part @relation(fields: [id], references: [id]) + id String @id @default(uuid()) + text String // the comment, should I allow mark down? + user User @relation(fields: [userId], references: [id]) + userId String + part Part @relation(fields: [partId], references: [id]) + partId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/api/src/functions/identity-signup.js b/api/src/functions/identity-signup.js index 6b52938..f816d78 100644 --- a/api/src/functions/identity-signup.js +++ b/api/src/functions/identity-signup.js @@ -1,4 +1,4 @@ -import { createUserInsecure } from 'src/services/users/users.js' +// import { createUserInsecure } from 'src/services/users/users.js' export const handler = async (req, _context) => { const body = JSON.parse(req.body) @@ -66,7 +66,7 @@ export const handler = async (req, _context) => { bio: 'default bio' // full_name: user.user_metadata.full_name } - await createUserInsecure({input}) + // await createUserInsecure({input}) return { statusCode: 200, diff --git a/api/src/graphql/comments.sdl.js b/api/src/graphql/comments.sdl.js new file mode 100644 index 0000000..b36296b --- /dev/null +++ b/api/src/graphql/comments.sdl.js @@ -0,0 +1,35 @@ +export const schema = gql` + type Comment { + id: String! + text: String! + user: User! + userId: String! + part: Part! + partId: String! + createdAt: DateTime! + updatedAt: DateTime! + } + + type Query { + comments: [Comment!]! + comment(id: String!): Comment + } + + input CreateCommentInput { + text: String! + userId: String! + partId: String! + } + + input UpdateCommentInput { + text: String + userId: String + partId: String + } + + type Mutation { + createComment(input: CreateCommentInput!): Comment! + updateComment(id: String!, input: UpdateCommentInput!): Comment! + deleteComment(id: String!): Comment! + } +` diff --git a/api/src/graphql/partReactions.sdl.js b/api/src/graphql/partReactions.sdl.js new file mode 100644 index 0000000..7aba11f --- /dev/null +++ b/api/src/graphql/partReactions.sdl.js @@ -0,0 +1,38 @@ +export const schema = gql` + type PartReaction { + id: String! + emote: String! + user: User! + userId: String! + part: Part! + partId: String! + createdAt: DateTime! + updatedAt: DateTime! + } + + type Query { + partReactions: [PartReaction!]! + partReaction(id: String!): PartReaction + } + + input CreatePartReactionInput { + emote: String! + userId: String! + partId: String! + } + + input UpdatePartReactionInput { + emote: String + userId: String + partId: String + } + + type Mutation { + createPartReaction(input: CreatePartReactionInput!): PartReaction! + updatePartReaction( + id: String! + input: UpdatePartReactionInput! + ): PartReaction! + deletePartReaction(id: String!): PartReaction! + } +` diff --git a/api/src/graphql/parts.sdl.js b/api/src/graphql/parts.sdl.js new file mode 100644 index 0000000..c8054a4 --- /dev/null +++ b/api/src/graphql/parts.sdl.js @@ -0,0 +1,42 @@ +export const schema = gql` + type Part { + id: String! + title: String! + description: String + code: String + mainImage: String + createdAt: DateTime! + updatedAt: DateTime! + user: User! + userId: String! + Comment: [Comment]! + Reaction: [PartReaction]! + } + + type Query { + parts: [Part!]! + part(id: String!): Part + } + + input CreatePartInput { + title: String! + description: String + code: String + mainImage: String + userId: String! + } + + input UpdatePartInput { + title: String + description: String + code: String + mainImage: String + userId: String + } + + type Mutation { + createPart(input: CreatePartInput!): Part! + updatePart(id: String!, input: UpdatePartInput!): Part! + deletePart(id: String!): Part! + } +` diff --git a/api/src/graphql/users.sdl.js b/api/src/graphql/users.sdl.js new file mode 100644 index 0000000..4e25e97 --- /dev/null +++ b/api/src/graphql/users.sdl.js @@ -0,0 +1,39 @@ +export const schema = gql` + type User { + id: String! + userName: String! + email: String! + createdAt: DateTime! + updatedAt: DateTime! + image: String + bio: String + Part: [Part]! + Reaction: [PartReaction]! + Comment: [Comment]! + } + + type Query { + users: [User!]! + user(id: String!): User + } + + input CreateUserInput { + userName: String! + email: String! + image: String + bio: String + } + + input UpdateUserInput { + userName: String + email: String + image: String + bio: String + } + + type Mutation { + createUser(input: CreateUserInput!): User! + updateUser(id: String!, input: UpdateUserInput!): User! + deleteUser(id: String!): User! + } +` diff --git a/api/src/services/comments/comments.js b/api/src/services/comments/comments.js new file mode 100644 index 0000000..5c46fdf --- /dev/null +++ b/api/src/services/comments/comments.js @@ -0,0 +1,38 @@ +import { db } from 'src/lib/db' +import { foreignKeyReplacement } from 'src/services/helpers' + +export const comments = () => { + return db.comment.findMany() +} + +export const comment = ({ id }) => { + return db.comment.findOne({ + where: { id }, + }) +} + +export const createComment = ({ input }) => { + return db.comment.create({ + data: foreignKeyReplacement(input), + }) +} + +export const updateComment = ({ id, input }) => { + return db.comment.update({ + data: foreignKeyReplacement(input), + where: { id }, + }) +} + +export const deleteComment = ({ id }) => { + return db.comment.delete({ + where: { id }, + }) +} + +export const Comment = { + user: (_obj, { root }) => + db.comment.findOne({ where: { id: root.id } }).user(), + part: (_obj, { root }) => + db.comment.findOne({ where: { id: root.id } }).part(), +} diff --git a/api/src/services/comments/comments.test.js b/api/src/services/comments/comments.test.js new file mode 100644 index 0000000..108fd0f --- /dev/null +++ b/api/src/services/comments/comments.test.js @@ -0,0 +1,9 @@ +/* +import { comments } from './comments' +*/ + +describe('comments', () => { + it('returns true', () => { + expect(true).toBe(true) + }) +}) diff --git a/api/src/services/helpers.js b/api/src/services/helpers.js new file mode 100644 index 0000000..ed474f3 --- /dev/null +++ b/api/src/services/helpers.js @@ -0,0 +1,13 @@ +export const foreignKeyReplacement = (input) => { + let output = input + const foreignKeys = Object.keys(input).filter((k) => k.match(/Id$/)) + foreignKeys.forEach((key) => { + const modelName = key.replace(/Id$/, '') + const value = input[key] + delete output[key] + output = Object.assign(output, { + [modelName]: { connect: { id: value } }, + }) + }) + return output +} diff --git a/api/src/services/partReactions/partReactions.js b/api/src/services/partReactions/partReactions.js new file mode 100644 index 0000000..e7b526d --- /dev/null +++ b/api/src/services/partReactions/partReactions.js @@ -0,0 +1,38 @@ +import { db } from 'src/lib/db' +import { foreignKeyReplacement } from 'src/services/helpers' + +export const partReactions = () => { + return db.partReaction.findMany() +} + +export const partReaction = ({ id }) => { + return db.partReaction.findOne({ + where: { id }, + }) +} + +export const createPartReaction = ({ input }) => { + return db.partReaction.create({ + data: foreignKeyReplacement(input), + }) +} + +export const updatePartReaction = ({ id, input }) => { + return db.partReaction.update({ + data: foreignKeyReplacement(input), + where: { id }, + }) +} + +export const deletePartReaction = ({ id }) => { + return db.partReaction.delete({ + where: { id }, + }) +} + +export const PartReaction = { + user: (_obj, { root }) => + db.partReaction.findOne({ where: { id: root.id } }).user(), + part: (_obj, { root }) => + db.partReaction.findOne({ where: { id: root.id } }).part(), +} diff --git a/api/src/services/partReactions/partReactions.test.js b/api/src/services/partReactions/partReactions.test.js new file mode 100644 index 0000000..47d4f20 --- /dev/null +++ b/api/src/services/partReactions/partReactions.test.js @@ -0,0 +1,9 @@ +/* +import { partReactions } from './partReactions' +*/ + +describe('partReactions', () => { + it('returns true', () => { + expect(true).toBe(true) + }) +}) diff --git a/api/src/services/parts/parts.js b/api/src/services/parts/parts.js new file mode 100644 index 0000000..2c3cee1 --- /dev/null +++ b/api/src/services/parts/parts.js @@ -0,0 +1,40 @@ +import { db } from 'src/lib/db' +import { foreignKeyReplacement } from 'src/services/helpers' +import { user } from 'src/services/users/users' + +export const parts = () => { + return db.part.findMany() +} + +export const part = ({ id }) => { + return db.part.findOne({ + where: { id }, + }) +} + +export const createPart = async ({ input }) => { + return db.part.create({ + data: foreignKeyReplacement(input), + }) +} + +export const updatePart = ({ id, input }) => { + return db.part.update({ + data: foreignKeyReplacement(input), + where: { id }, + }) +} + +export const deletePart = ({ id }) => { + return db.part.delete({ + where: { id }, + }) +} + +export const Part = { + user: (_obj, { root }) => db.part.findOne({ where: { id: root.id } }).user(), + Comment: (_obj, { root }) => + db.part.findOne({ where: { id: root.id } }).Comment(), + Reaction: (_obj, { root }) => + db.part.findOne({ where: { id: root.id } }).Reaction(), +} diff --git a/api/src/services/parts/parts.test.js b/api/src/services/parts/parts.test.js new file mode 100644 index 0000000..e8b80ce --- /dev/null +++ b/api/src/services/parts/parts.test.js @@ -0,0 +1,9 @@ +/* +import { parts } from './parts' +*/ + +describe('parts', () => { + it('returns true', () => { + expect(true).toBe(true) + }) +}) diff --git a/api/src/services/users/users.js b/api/src/services/users/users.js new file mode 100644 index 0000000..9a10d66 --- /dev/null +++ b/api/src/services/users/users.js @@ -0,0 +1,38 @@ +import { db } from 'src/lib/db' + +export const users = () => { + return db.user.findMany() +} + +export const user = ({ id }) => { + return db.user.findOne({ + where: { id }, + }) +} + +export const createUser = ({ input }) => { + return db.user.create({ + data: input, + }) +} + +export const updateUser = ({ id, input }) => { + return db.user.update({ + data: input, + where: { id }, + }) +} + +export const deleteUser = ({ id }) => { + return db.user.delete({ + where: { id }, + }) +} + +export const User = { + Part: (_obj, { root }) => db.user.findOne({ where: { id: root.id } }).Part(), + Reaction: (_obj, { root }) => + db.user.findOne({ where: { id: root.id } }).Reaction(), + Comment: (_obj, { root }) => + db.user.findOne({ where: { id: root.id } }).Comment(), +} diff --git a/api/src/services/users/users.test.js b/api/src/services/users/users.test.js new file mode 100644 index 0000000..bac7cb4 --- /dev/null +++ b/api/src/services/users/users.test.js @@ -0,0 +1,9 @@ +/* +import { users } from './users' +*/ + +describe('users', () => { + it('returns true', () => { + expect(true).toBe(true) + }) +}) diff --git a/web/src/Routes.js b/web/src/Routes.js index c9ebd82..257a6ee 100644 --- a/web/src/Routes.js +++ b/web/src/Routes.js @@ -12,8 +12,24 @@ import { Router, Route, Private } from '@redwoodjs/router' const Routes = () => { return ( - - + + + + + + + + + + + + + + + + + + {/* */} ) diff --git a/web/src/components/Comment/Comment.js b/web/src/components/Comment/Comment.js new file mode 100644 index 0000000..4d928d2 --- /dev/null +++ b/web/src/components/Comment/Comment.js @@ -0,0 +1,103 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes, navigate } from '@redwoodjs/router' + +const DELETE_COMMENT_MUTATION = gql` + mutation DeleteCommentMutation($id: String!) { + deleteComment(id: $id) { + id + } + } +` + +const jsonDisplay = (obj) => { + return ( +
+      {JSON.stringify(obj, null, 2)}
+    
+ ) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const Comment = ({ comment }) => { + const { addMessage } = useFlash() + const [deleteComment] = useMutation(DELETE_COMMENT_MUTATION, { + onCompleted: () => { + navigate(routes.comments()) + addMessage('Comment deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete comment ' + id + '?')) { + deleteComment({ variables: { id } }) + } + } + + return ( + <> +
+
+

+ Comment {comment.id} Detail +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Id{comment.id}
Text{comment.text}
User id{comment.userId}
Part id{comment.partId}
Created at{timeTag(comment.createdAt)}
Updated at{timeTag(comment.updatedAt)}
+
+ + + ) +} + +export default Comment diff --git a/web/src/components/CommentCell/CommentCell.js b/web/src/components/CommentCell/CommentCell.js new file mode 100644 index 0000000..1c93fe8 --- /dev/null +++ b/web/src/components/CommentCell/CommentCell.js @@ -0,0 +1,22 @@ +import Comment from 'src/components/Comment' + +export const QUERY = gql` + query FIND_COMMENT_BY_ID($id: String!) { + comment: comment(id: $id) { + id + text + userId + partId + createdAt + updatedAt + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () =>
Comment not found
+ +export const Success = ({ comment }) => { + return +} diff --git a/web/src/components/CommentForm/CommentForm.js b/web/src/components/CommentForm/CommentForm.js new file mode 100644 index 0000000..e145dc5 --- /dev/null +++ b/web/src/components/CommentForm/CommentForm.js @@ -0,0 +1,83 @@ +import { + Form, + FormError, + FieldError, + Label, + TextField, + Submit, +} from '@redwoodjs/forms' + +const CommentForm = (props) => { + const onSubmit = (data) => { + props.onSave(data, props?.comment?.id) + } + + return ( +
+
+ + + + + + + + + + + + + + +
+ + Save + +
+ +
+ ) +} + +export default CommentForm diff --git a/web/src/components/Comments/Comments.js b/web/src/components/Comments/Comments.js new file mode 100644 index 0000000..f105938 --- /dev/null +++ b/web/src/components/Comments/Comments.js @@ -0,0 +1,109 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes } from '@redwoodjs/router' + +const DELETE_COMMENT_MUTATION = gql` + mutation DeleteCommentMutation($id: String!) { + deleteComment(id: $id) { + id + } + } +` + +const MAX_STRING_LENGTH = 150 + +const truncate = (text) => { + let output = text + if (text && text.length > MAX_STRING_LENGTH) { + output = output.substring(0, MAX_STRING_LENGTH) + '...' + } + return output +} + +const jsonTruncate = (obj) => { + return truncate(JSON.stringify(obj, null, 2)) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const CommentsList = ({ comments }) => { + const { addMessage } = useFlash() + const [deleteComment] = useMutation(DELETE_COMMENT_MUTATION, { + onCompleted: () => { + addMessage('Comment deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete comment ' + id + '?')) { + deleteComment({ variables: { id }, refetchQueries: ['COMMENTS'] }) + } + } + + return ( +
+ + + + + + + + + + + + + + {comments.map((comment) => ( + + + + + + + + + + ))} + +
IdTextUser idPart idCreated atUpdated at 
{truncate(comment.id)}{truncate(comment.text)}{truncate(comment.userId)}{truncate(comment.partId)}{timeTag(comment.createdAt)}{timeTag(comment.updatedAt)} + +
+
+ ) +} + +export default CommentsList diff --git a/web/src/components/CommentsCell/CommentsCell.js b/web/src/components/CommentsCell/CommentsCell.js new file mode 100644 index 0000000..eefd988 --- /dev/null +++ b/web/src/components/CommentsCell/CommentsCell.js @@ -0,0 +1,33 @@ +import { Link, routes } from '@redwoodjs/router' + +import Comments from 'src/components/Comments' + +export const QUERY = gql` + query COMMENTS { + comments { + id + text + userId + partId + createdAt + updatedAt + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () => { + return ( +
+ {'No comments yet. '} + + {'Create one?'} + +
+ ) +} + +export const Success = ({ comments }) => { + return +} diff --git a/web/src/components/EditCommentCell/EditCommentCell.js b/web/src/components/EditCommentCell/EditCommentCell.js new file mode 100644 index 0000000..3edac98 --- /dev/null +++ b/web/src/components/EditCommentCell/EditCommentCell.js @@ -0,0 +1,60 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import CommentForm from 'src/components/CommentForm' + +export const QUERY = gql` + query FIND_COMMENT_BY_ID($id: String!) { + comment: comment(id: $id) { + id + text + userId + partId + createdAt + updatedAt + } + } +` +const UPDATE_COMMENT_MUTATION = gql` + mutation UpdateCommentMutation($id: String!, $input: UpdateCommentInput!) { + updateComment(id: $id, input: $input) { + id + } + } +` + +export const Loading = () =>
Loading...
+ +export const Success = ({ comment }) => { + const { addMessage } = useFlash() + const [updateComment, { loading, error }] = useMutation( + UPDATE_COMMENT_MUTATION, + { + onCompleted: () => { + navigate(routes.comments()) + addMessage('Comment updated.', { classes: 'rw-flash-success' }) + }, + } + ) + + const onSave = (input, id) => { + updateComment({ variables: { id, input } }) + } + + return ( +
+
+

+ Edit Comment {comment.id} +

+
+
+ +
+
+ ) +} diff --git a/web/src/components/EditPartCell/EditPartCell.js b/web/src/components/EditPartCell/EditPartCell.js new file mode 100644 index 0000000..8b551ac --- /dev/null +++ b/web/src/components/EditPartCell/EditPartCell.js @@ -0,0 +1,52 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import PartForm from 'src/components/PartForm' + +export const QUERY = gql` + query FIND_PART_BY_ID($id: String!) { + part: part(id: $id) { + id + title + description + code + mainImage + createdAt + updatedAt + userId + } + } +` +const UPDATE_PART_MUTATION = gql` + mutation UpdatePartMutation($id: String!, $input: UpdatePartInput!) { + updatePart(id: $id, input: $input) { + id + } + } +` + +export const Loading = () =>
Loading...
+ +export const Success = ({ part }) => { + const { addMessage } = useFlash() + const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION, { + onCompleted: () => { + navigate(routes.parts()) + addMessage('Part updated.', { classes: 'rw-flash-success' }) + }, + }) + + const onSave = (input, id) => { + updatePart({ variables: { id, input } }) + } + + return ( +
+
+

Edit Part {part.id}

+
+
+ +
+
+ ) +} diff --git a/web/src/components/EditPartReactionCell/EditPartReactionCell.js b/web/src/components/EditPartReactionCell/EditPartReactionCell.js new file mode 100644 index 0000000..2c23c50 --- /dev/null +++ b/web/src/components/EditPartReactionCell/EditPartReactionCell.js @@ -0,0 +1,63 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import PartReactionForm from 'src/components/PartReactionForm' + +export const QUERY = gql` + query FIND_PART_REACTION_BY_ID($id: String!) { + partReaction: partReaction(id: $id) { + id + emote + userId + partId + createdAt + updatedAt + } + } +` +const UPDATE_PART_REACTION_MUTATION = gql` + mutation UpdatePartReactionMutation( + $id: String! + $input: UpdatePartReactionInput! + ) { + updatePartReaction(id: $id, input: $input) { + id + } + } +` + +export const Loading = () =>
Loading...
+ +export const Success = ({ partReaction }) => { + const { addMessage } = useFlash() + const [updatePartReaction, { loading, error }] = useMutation( + UPDATE_PART_REACTION_MUTATION, + { + onCompleted: () => { + navigate(routes.partReactions()) + addMessage('PartReaction updated.', { classes: 'rw-flash-success' }) + }, + } + ) + + const onSave = (input, id) => { + updatePartReaction({ variables: { id, input } }) + } + + return ( +
+
+

+ Edit PartReaction {partReaction.id} +

+
+
+ +
+
+ ) +} diff --git a/web/src/components/EditUserCell/EditUserCell.js b/web/src/components/EditUserCell/EditUserCell.js new file mode 100644 index 0000000..7d3682b --- /dev/null +++ b/web/src/components/EditUserCell/EditUserCell.js @@ -0,0 +1,51 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import UserForm from 'src/components/UserForm' + +export const QUERY = gql` + query FIND_USER_BY_ID($id: String!) { + user: user(id: $id) { + id + userName + email + createdAt + updatedAt + image + bio + } + } +` +const UPDATE_USER_MUTATION = gql` + mutation UpdateUserMutation($id: String!, $input: UpdateUserInput!) { + updateUser(id: $id, input: $input) { + id + } + } +` + +export const Loading = () =>
Loading...
+ +export const Success = ({ user }) => { + const { addMessage } = useFlash() + const [updateUser, { loading, error }] = useMutation(UPDATE_USER_MUTATION, { + onCompleted: () => { + navigate(routes.users()) + addMessage('User updated.', { classes: 'rw-flash-success' }) + }, + }) + + const onSave = (input, id) => { + updateUser({ variables: { id, input } }) + } + + return ( +
+
+

Edit User {user.id}

+
+
+ +
+
+ ) +} diff --git a/web/src/components/IdePartCell/IdePartCell.js b/web/src/components/IdePartCell/IdePartCell.js index 3b95c0b..122ed88 100644 --- a/web/src/components/IdePartCell/IdePartCell.js +++ b/web/src/components/IdePartCell/IdePartCell.js @@ -1,6 +1,6 @@ import { useMutation, useFlash } from '@redwoodjs/web' import { navigate, routes } from '@redwoodjs/router' -import Part from 'src/components/Part' +// import Part from 'src/components/Part' export const QUERY = gql` query FIND_PART_BY_ID($id: Int!) { @@ -42,5 +42,6 @@ export const Success = ({ part }) => { console.log(id, input, 'wowow') updatePart({ variables: { id, input } }) } - return + return
TODO part
+ // return } diff --git a/web/src/components/NewComment/NewComment.js b/web/src/components/NewComment/NewComment.js new file mode 100644 index 0000000..750bba4 --- /dev/null +++ b/web/src/components/NewComment/NewComment.js @@ -0,0 +1,41 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import CommentForm from 'src/components/CommentForm' + +const CREATE_COMMENT_MUTATION = gql` + mutation CreateCommentMutation($input: CreateCommentInput!) { + createComment(input: $input) { + id + } + } +` + +const NewComment = () => { + const { addMessage } = useFlash() + const [createComment, { loading, error }] = useMutation( + CREATE_COMMENT_MUTATION, + { + onCompleted: () => { + navigate(routes.comments()) + addMessage('Comment created.', { classes: 'rw-flash-success' }) + }, + } + ) + + const onSave = (input) => { + createComment({ variables: { input } }) + } + + return ( +
+
+

New Comment

+
+
+ +
+
+ ) +} + +export default NewComment diff --git a/web/src/components/NewPart/NewPart.js b/web/src/components/NewPart/NewPart.js new file mode 100644 index 0000000..3b7e5ed --- /dev/null +++ b/web/src/components/NewPart/NewPart.js @@ -0,0 +1,38 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import PartForm from 'src/components/PartForm' + +const CREATE_PART_MUTATION = gql` + mutation CreatePartMutation($input: CreatePartInput!) { + createPart(input: $input) { + id + } + } +` + +const NewPart = () => { + const { addMessage } = useFlash() + const [createPart, { loading, error }] = useMutation(CREATE_PART_MUTATION, { + onCompleted: () => { + navigate(routes.parts()) + addMessage('Part created.', { classes: 'rw-flash-success' }) + }, + }) + + const onSave = (input) => { + createPart({ variables: { input } }) + } + + return ( +
+
+

New Part

+
+
+ +
+
+ ) +} + +export default NewPart diff --git a/web/src/components/NewPartReaction/NewPartReaction.js b/web/src/components/NewPartReaction/NewPartReaction.js new file mode 100644 index 0000000..8cbcba3 --- /dev/null +++ b/web/src/components/NewPartReaction/NewPartReaction.js @@ -0,0 +1,41 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import PartReactionForm from 'src/components/PartReactionForm' + +const CREATE_PART_REACTION_MUTATION = gql` + mutation CreatePartReactionMutation($input: CreatePartReactionInput!) { + createPartReaction(input: $input) { + id + } + } +` + +const NewPartReaction = () => { + const { addMessage } = useFlash() + const [createPartReaction, { loading, error }] = useMutation( + CREATE_PART_REACTION_MUTATION, + { + onCompleted: () => { + navigate(routes.partReactions()) + addMessage('PartReaction created.', { classes: 'rw-flash-success' }) + }, + } + ) + + const onSave = (input) => { + createPartReaction({ variables: { input } }) + } + + return ( +
+
+

New PartReaction

+
+
+ +
+
+ ) +} + +export default NewPartReaction diff --git a/web/src/components/NewUser/NewUser.js b/web/src/components/NewUser/NewUser.js new file mode 100644 index 0000000..6f89a18 --- /dev/null +++ b/web/src/components/NewUser/NewUser.js @@ -0,0 +1,38 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' +import UserForm from 'src/components/UserForm' + +const CREATE_USER_MUTATION = gql` + mutation CreateUserMutation($input: CreateUserInput!) { + createUser(input: $input) { + id + } + } +` + +const NewUser = () => { + const { addMessage } = useFlash() + const [createUser, { loading, error }] = useMutation(CREATE_USER_MUTATION, { + onCompleted: () => { + navigate(routes.users()) + addMessage('User created.', { classes: 'rw-flash-success' }) + }, + }) + + const onSave = (input) => { + createUser({ variables: { input } }) + } + + return ( +
+
+

New User

+
+
+ +
+
+ ) +} + +export default NewUser diff --git a/web/src/components/Part/Part.js b/web/src/components/Part/Part.js new file mode 100644 index 0000000..4fe2e15 --- /dev/null +++ b/web/src/components/Part/Part.js @@ -0,0 +1,111 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes, navigate } from '@redwoodjs/router' + +const DELETE_PART_MUTATION = gql` + mutation DeletePartMutation($id: String!) { + deletePart(id: $id) { + id + } + } +` + +const jsonDisplay = (obj) => { + return ( +
+      {JSON.stringify(obj, null, 2)}
+    
+ ) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const Part = ({ part }) => { + const { addMessage } = useFlash() + const [deletePart] = useMutation(DELETE_PART_MUTATION, { + onCompleted: () => { + navigate(routes.parts()) + addMessage('Part deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete part ' + id + '?')) { + deletePart({ variables: { id } }) + } + } + + return ( + <> +
+
+

+ Part {part.id} Detail +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Id{part.id}
Title{part.title}
Description{part.description}
Code{part.code}
Main image{part.mainImage}
Created at{timeTag(part.createdAt)}
Updated at{timeTag(part.updatedAt)}
User id{part.userId}
+
+ + + ) +} + +export default Part diff --git a/web/src/components/PartCell/PartCell.js b/web/src/components/PartCell/PartCell.js new file mode 100644 index 0000000..3c69b24 --- /dev/null +++ b/web/src/components/PartCell/PartCell.js @@ -0,0 +1,24 @@ +import Part from 'src/components/Part' + +export const QUERY = gql` + query FIND_PART_BY_ID($id: String!) { + part: part(id: $id) { + id + title + description + code + mainImage + createdAt + updatedAt + userId + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () =>
Part not found
+ +export const Success = ({ part }) => { + return +} diff --git a/web/src/components/PartForm/ImageUploader.js b/web/src/components/PartForm/ImageUploader.js deleted file mode 100644 index 0314a13..0000000 --- a/web/src/components/PartForm/ImageUploader.js +++ /dev/null @@ -1,120 +0,0 @@ -import React, { useCallback, useState } from "react"; -import { useDropzone } from "react-dropzone"; -import Button from "@material-ui/core/Button"; -import axios from 'axios' -import ReactCrop from 'react-image-crop' -import { Dialog } from '@material-ui/core' -import { Image as CloudinaryImage } from 'cloudinary-react' -import 'react-image-crop/dist/ReactCrop.css' -import Svg from 'src/components/Svg/Svg.js' - -const CLOUDINARY_UPLOAD_PRESET = "CadHub_project_images"; -const CLOUDINARY_UPLOAD_URL = "https://api.cloudinary.com/v1_1/irevdev/upload"; - -export default function ImageUploader({ onImageUpload, imageUrl }) { - const [isModalOpen, setIsModalOpen] = useState(false) - const [file, setFile] = useState() - const [cloudinaryId, setCloudinaryId] = useState(imageUrl) - const [imageObj, setImageObj] = useState() - const [crop, setCrop] = useState({ - aspect: 16 / 9, - unit: '%', - width: 100, - }); - async function handleImageUpload() { - const croppedFile = await getCroppedImg(imageObj, crop, 'avatar') - console.log(croppedFile) - const imageData = new FormData(); - imageData.append('upload_preset', CLOUDINARY_UPLOAD_PRESET); - imageData.append('file', croppedFile); - let upload = axios.post(CLOUDINARY_UPLOAD_URL, imageData) - try { - const { data } = await upload - if (data && data.public_id !== "") { - onImageUpload({cloudinaryPublicId: data.public_id}) - setCloudinaryId(data.public_id) - setIsModalOpen(false) - } - } catch (e) { - console.error('ERROR', e) - } - } - // Drag and Drop - const onDrop = useCallback(acceptedFiles => { - setIsModalOpen(true) - const fileReader = new FileReader() - fileReader.onload = () => { - setFile(fileReader.result) - } - fileReader.readAsDataURL(acceptedFiles[0]) - }, []); - - const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop }); - return ( -
-
- {cloudinaryId && } - - {cloudinaryId &&
- -
} - {!cloudinaryId && } - {!cloudinaryId &&
- Drop files here ... - or - upload - -
} -
- setIsModalOpen(false)} - > -
- setImageObj(image)} onChange={newCrop => setCrop(newCrop)} /> - -
-
-
- ); -} - -function getCroppedImg(image, crop, fileName) { - const canvas = document.createElement('canvas'); - const scaleX = image.naturalWidth / image.width; - const scaleY = image.naturalHeight / image.height; - canvas.width = crop.width; - canvas.height = crop.height; - const ctx = canvas.getContext('2d'); - ctx.drawImage( - image, - crop.x * scaleX, - crop.y * scaleY, - crop.width * scaleX, - crop.height * scaleY, - 0, - 0, - crop.width, - crop.height - ); - - // As Base64 string - // const base64Image = canvas.toDataURL('image/jpeg'); - - // As a blob - return new Promise((resolve, reject) => { - canvas.toBlob(blob => { - blob.name = fileName; - resolve(blob); - }, 'image/jpeg', 1); - }); -} - diff --git a/web/src/components/PartForm/PartForm.js b/web/src/components/PartForm/PartForm.js new file mode 100644 index 0000000..3fc1009 --- /dev/null +++ b/web/src/components/PartForm/PartForm.js @@ -0,0 +1,115 @@ +import { + Form, + FormError, + FieldError, + Label, + TextField, + Submit, +} from '@redwoodjs/forms' + +const PartForm = (props) => { + const onSubmit = (data) => { + props.onSave(data, props?.part?.id) + } + + return ( +
+
+ + + + + + + + + + + + + + + + + + + + + + +
+ + Save + +
+ +
+ ) +} + +export default PartForm diff --git a/web/src/components/PartReaction/PartReaction.js b/web/src/components/PartReaction/PartReaction.js new file mode 100644 index 0000000..82f0645 --- /dev/null +++ b/web/src/components/PartReaction/PartReaction.js @@ -0,0 +1,103 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes, navigate } from '@redwoodjs/router' + +const DELETE_PART_REACTION_MUTATION = gql` + mutation DeletePartReactionMutation($id: String!) { + deletePartReaction(id: $id) { + id + } + } +` + +const jsonDisplay = (obj) => { + return ( +
+      {JSON.stringify(obj, null, 2)}
+    
+ ) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const PartReaction = ({ partReaction }) => { + const { addMessage } = useFlash() + const [deletePartReaction] = useMutation(DELETE_PART_REACTION_MUTATION, { + onCompleted: () => { + navigate(routes.partReactions()) + addMessage('PartReaction deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete partReaction ' + id + '?')) { + deletePartReaction({ variables: { id } }) + } + } + + return ( + <> +
+
+

+ PartReaction {partReaction.id} Detail +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Id{partReaction.id}
Emote{partReaction.emote}
User id{partReaction.userId}
Part id{partReaction.partId}
Created at{timeTag(partReaction.createdAt)}
Updated at{timeTag(partReaction.updatedAt)}
+
+ + + ) +} + +export default PartReaction diff --git a/web/src/components/PartReactionCell/PartReactionCell.js b/web/src/components/PartReactionCell/PartReactionCell.js new file mode 100644 index 0000000..102916c --- /dev/null +++ b/web/src/components/PartReactionCell/PartReactionCell.js @@ -0,0 +1,22 @@ +import PartReaction from 'src/components/PartReaction' + +export const QUERY = gql` + query FIND_PART_REACTION_BY_ID($id: String!) { + partReaction: partReaction(id: $id) { + id + emote + userId + partId + createdAt + updatedAt + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () =>
PartReaction not found
+ +export const Success = ({ partReaction }) => { + return +} diff --git a/web/src/components/PartReactionForm/PartReactionForm.js b/web/src/components/PartReactionForm/PartReactionForm.js new file mode 100644 index 0000000..5bcac9e --- /dev/null +++ b/web/src/components/PartReactionForm/PartReactionForm.js @@ -0,0 +1,83 @@ +import { + Form, + FormError, + FieldError, + Label, + TextField, + Submit, +} from '@redwoodjs/forms' + +const PartReactionForm = (props) => { + const onSubmit = (data) => { + props.onSave(data, props?.partReaction?.id) + } + + return ( +
+
+ + + + + + + + + + + + + + +
+ + Save + +
+ +
+ ) +} + +export default PartReactionForm diff --git a/web/src/components/PartReactions/PartReactions.js b/web/src/components/PartReactions/PartReactions.js new file mode 100644 index 0000000..2653abc --- /dev/null +++ b/web/src/components/PartReactions/PartReactions.js @@ -0,0 +1,112 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes } from '@redwoodjs/router' + +const DELETE_PART_REACTION_MUTATION = gql` + mutation DeletePartReactionMutation($id: String!) { + deletePartReaction(id: $id) { + id + } + } +` + +const MAX_STRING_LENGTH = 150 + +const truncate = (text) => { + let output = text + if (text && text.length > MAX_STRING_LENGTH) { + output = output.substring(0, MAX_STRING_LENGTH) + '...' + } + return output +} + +const jsonTruncate = (obj) => { + return truncate(JSON.stringify(obj, null, 2)) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const PartReactionsList = ({ partReactions }) => { + const { addMessage } = useFlash() + const [deletePartReaction] = useMutation(DELETE_PART_REACTION_MUTATION, { + onCompleted: () => { + addMessage('PartReaction deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete partReaction ' + id + '?')) { + deletePartReaction({ + variables: { id }, + refetchQueries: ['PART_REACTIONS'], + }) + } + } + + return ( +
+ + + + + + + + + + + + + + {partReactions.map((partReaction) => ( + + + + + + + + + + ))} + +
IdEmoteUser idPart idCreated atUpdated at 
{truncate(partReaction.id)}{truncate(partReaction.emote)}{truncate(partReaction.userId)}{truncate(partReaction.partId)}{timeTag(partReaction.createdAt)}{timeTag(partReaction.updatedAt)} + +
+
+ ) +} + +export default PartReactionsList diff --git a/web/src/components/PartReactionsCell/PartReactionsCell.js b/web/src/components/PartReactionsCell/PartReactionsCell.js new file mode 100644 index 0000000..5a8b8bf --- /dev/null +++ b/web/src/components/PartReactionsCell/PartReactionsCell.js @@ -0,0 +1,33 @@ +import { Link, routes } from '@redwoodjs/router' + +import PartReactions from 'src/components/PartReactions' + +export const QUERY = gql` + query PART_REACTIONS { + partReactions { + id + emote + userId + partId + createdAt + updatedAt + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () => { + return ( +
+ {'No partReactions yet. '} + + {'Create one?'} + +
+ ) +} + +export const Success = ({ partReactions }) => { + return +} diff --git a/web/src/components/Parts/Parts.js b/web/src/components/Parts/Parts.js new file mode 100644 index 0000000..9e25f6f --- /dev/null +++ b/web/src/components/Parts/Parts.js @@ -0,0 +1,113 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes } from '@redwoodjs/router' + +const DELETE_PART_MUTATION = gql` + mutation DeletePartMutation($id: String!) { + deletePart(id: $id) { + id + } + } +` + +const MAX_STRING_LENGTH = 150 + +const truncate = (text) => { + let output = text + if (text && text.length > MAX_STRING_LENGTH) { + output = output.substring(0, MAX_STRING_LENGTH) + '...' + } + return output +} + +const jsonTruncate = (obj) => { + return truncate(JSON.stringify(obj, null, 2)) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const PartsList = ({ parts }) => { + const { addMessage } = useFlash() + const [deletePart] = useMutation(DELETE_PART_MUTATION, { + onCompleted: () => { + addMessage('Part deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete part ' + id + '?')) { + deletePart({ variables: { id }, refetchQueries: ['PARTS'] }) + } + } + + return ( +
+ + + + + + + + + + + + + + + + {parts.map((part) => ( + + + + + + + + + + + + ))} + +
IdTitleDescriptionCodeMain imageCreated atUpdated atUser id 
{truncate(part.id)}{truncate(part.title)}{truncate(part.description)}{truncate(part.code)}{truncate(part.mainImage)}{timeTag(part.createdAt)}{timeTag(part.updatedAt)}{truncate(part.userId)} + +
+
+ ) +} + +export default PartsList diff --git a/web/src/components/PartsCell/PartsCell.js b/web/src/components/PartsCell/PartsCell.js new file mode 100644 index 0000000..3e087bd --- /dev/null +++ b/web/src/components/PartsCell/PartsCell.js @@ -0,0 +1,35 @@ +import { Link, routes } from '@redwoodjs/router' + +import Parts from 'src/components/Parts' + +export const QUERY = gql` + query PARTS { + parts { + id + title + description + code + mainImage + createdAt + updatedAt + userId + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () => { + return ( +
+ {'No parts yet. '} + + {'Create one?'} + +
+ ) +} + +export const Success = ({ parts }) => { + return +} diff --git a/web/src/components/User/User.js b/web/src/components/User/User.js new file mode 100644 index 0000000..20ba427 --- /dev/null +++ b/web/src/components/User/User.js @@ -0,0 +1,107 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes, navigate } from '@redwoodjs/router' + +const DELETE_USER_MUTATION = gql` + mutation DeleteUserMutation($id: String!) { + deleteUser(id: $id) { + id + } + } +` + +const jsonDisplay = (obj) => { + return ( +
+      {JSON.stringify(obj, null, 2)}
+    
+ ) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const User = ({ user }) => { + const { addMessage } = useFlash() + const [deleteUser] = useMutation(DELETE_USER_MUTATION, { + onCompleted: () => { + navigate(routes.users()) + addMessage('User deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete user ' + id + '?')) { + deleteUser({ variables: { id } }) + } + } + + return ( + <> +
+
+

+ User {user.id} Detail +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Id{user.id}
User name{user.userName}
Email{user.email}
Created at{timeTag(user.createdAt)}
Updated at{timeTag(user.updatedAt)}
Image{user.image}
Bio{user.bio}
+
+ + + ) +} + +export default User diff --git a/web/src/components/UserCell/UserCell.js b/web/src/components/UserCell/UserCell.js new file mode 100644 index 0000000..7c34e11 --- /dev/null +++ b/web/src/components/UserCell/UserCell.js @@ -0,0 +1,23 @@ +import User from 'src/components/User' + +export const QUERY = gql` + query FIND_USER_BY_ID($id: String!) { + user: user(id: $id) { + id + userName + email + createdAt + updatedAt + image + bio + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () =>
User not found
+ +export const Success = ({ user }) => { + return +} diff --git a/web/src/components/UserForm/UserForm.js b/web/src/components/UserForm/UserForm.js new file mode 100644 index 0000000..c34107d --- /dev/null +++ b/web/src/components/UserForm/UserForm.js @@ -0,0 +1,99 @@ +import { + Form, + FormError, + FieldError, + Label, + TextField, + Submit, +} from '@redwoodjs/forms' + +const UserForm = (props) => { + const onSubmit = (data) => { + props.onSave(data, props?.user?.id) + } + + return ( +
+
+ + + + + + + + + + + + + + + + + + +
+ + Save + +
+ +
+ ) +} + +export default UserForm diff --git a/web/src/components/Users/Users.js b/web/src/components/Users/Users.js new file mode 100644 index 0000000..6b240a4 --- /dev/null +++ b/web/src/components/Users/Users.js @@ -0,0 +1,111 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { Link, routes } from '@redwoodjs/router' + +const DELETE_USER_MUTATION = gql` + mutation DeleteUserMutation($id: String!) { + deleteUser(id: $id) { + id + } + } +` + +const MAX_STRING_LENGTH = 150 + +const truncate = (text) => { + let output = text + if (text && text.length > MAX_STRING_LENGTH) { + output = output.substring(0, MAX_STRING_LENGTH) + '...' + } + return output +} + +const jsonTruncate = (obj) => { + return truncate(JSON.stringify(obj, null, 2)) +} + +const timeTag = (datetime) => { + return ( + + ) +} + +const checkboxInputTag = (checked) => { + return +} + +const UsersList = ({ users }) => { + const { addMessage } = useFlash() + const [deleteUser] = useMutation(DELETE_USER_MUTATION, { + onCompleted: () => { + addMessage('User deleted.', { classes: 'rw-flash-success' }) + }, + }) + + const onDeleteClick = (id) => { + if (confirm('Are you sure you want to delete user ' + id + '?')) { + deleteUser({ variables: { id }, refetchQueries: ['USERS'] }) + } + } + + return ( +
+ + + + + + + + + + + + + + + {users.map((user) => ( + + + + + + + + + + + ))} + +
IdUser nameEmailCreated atUpdated atImageBio 
{truncate(user.id)}{truncate(user.userName)}{truncate(user.email)}{timeTag(user.createdAt)}{timeTag(user.updatedAt)}{truncate(user.image)}{truncate(user.bio)} + +
+
+ ) +} + +export default UsersList diff --git a/web/src/components/UsersCell/UsersCell.js b/web/src/components/UsersCell/UsersCell.js new file mode 100644 index 0000000..64b62f2 --- /dev/null +++ b/web/src/components/UsersCell/UsersCell.js @@ -0,0 +1,34 @@ +import { Link, routes } from '@redwoodjs/router' + +import Users from 'src/components/Users' + +export const QUERY = gql` + query USERS { + users { + id + userName + email + createdAt + updatedAt + image + bio + } + } +` + +export const Loading = () =>
Loading...
+ +export const Empty = () => { + return ( +
+ {'No users yet. '} + + {'Create one?'} + +
+ ) +} + +export const Success = ({ users }) => { + return +} diff --git a/web/src/layouts/CommentsLayout/CommentsLayout.js b/web/src/layouts/CommentsLayout/CommentsLayout.js new file mode 100644 index 0000000..4ed9e72 --- /dev/null +++ b/web/src/layouts/CommentsLayout/CommentsLayout.js @@ -0,0 +1,23 @@ +import { Link, routes } from '@redwoodjs/router' +import { Flash } from '@redwoodjs/web' + +const CommentsLayout = (props) => { + return ( +
+ +
+

+ + Comments + +

+ +
+
New Comment + +
+
{props.children}
+
+ ) +} + +export default CommentsLayout diff --git a/web/src/layouts/MainLayout/MainLayout.js b/web/src/layouts/MainLayout/MainLayout.js index 9dcb960..7e00667 100644 --- a/web/src/layouts/MainLayout/MainLayout.js +++ b/web/src/layouts/MainLayout/MainLayout.js @@ -18,7 +18,7 @@ const MainLayout = ({ children }) => { - + @@ -35,9 +35,9 @@ const MainLayout = ({ children }) => {
  • - + {/* */} - + {/* */}
  • { isAuthenticated ? diff --git a/web/src/layouts/PartReactionsLayout/PartReactionsLayout.js b/web/src/layouts/PartReactionsLayout/PartReactionsLayout.js new file mode 100644 index 0000000..076c5b2 --- /dev/null +++ b/web/src/layouts/PartReactionsLayout/PartReactionsLayout.js @@ -0,0 +1,26 @@ +import { Link, routes } from '@redwoodjs/router' +import { Flash } from '@redwoodjs/web' + +const PartReactionsLayout = (props) => { + return ( +
    + +
    +

    + + PartReactions + +

    + +
    +
    New PartReaction + +
    +
    {props.children}
    +
    + ) +} + +export default PartReactionsLayout diff --git a/web/src/layouts/PartsLayout/PartsLayout.js b/web/src/layouts/PartsLayout/PartsLayout.js new file mode 100644 index 0000000..f0ecd0c --- /dev/null +++ b/web/src/layouts/PartsLayout/PartsLayout.js @@ -0,0 +1,23 @@ +import { Link, routes } from '@redwoodjs/router' +import { Flash } from '@redwoodjs/web' + +const PartsLayout = (props) => { + return ( +
    + +
    +

    + + Parts + +

    + +
    +
    New Part + +
    +
    {props.children}
    +
    + ) +} + +export default PartsLayout diff --git a/web/src/layouts/UsersLayout/UsersLayout.js b/web/src/layouts/UsersLayout/UsersLayout.js new file mode 100644 index 0000000..f4f055f --- /dev/null +++ b/web/src/layouts/UsersLayout/UsersLayout.js @@ -0,0 +1,23 @@ +import { Link, routes } from '@redwoodjs/router' +import { Flash } from '@redwoodjs/web' + +const UsersLayout = (props) => { + return ( +
    + +
    +

    + + Users + +

    + +
    +
    New User + +
    +
    {props.children}
    +
    + ) +} + +export default UsersLayout diff --git a/web/src/pages/CommentPage/CommentPage.js b/web/src/pages/CommentPage/CommentPage.js new file mode 100644 index 0000000..b4365f8 --- /dev/null +++ b/web/src/pages/CommentPage/CommentPage.js @@ -0,0 +1,12 @@ +import CommentsLayout from 'src/layouts/CommentsLayout' +import CommentCell from 'src/components/CommentCell' + +const CommentPage = ({ id }) => { + return ( + + + + ) +} + +export default CommentPage diff --git a/web/src/pages/CommentsPage/CommentsPage.js b/web/src/pages/CommentsPage/CommentsPage.js new file mode 100644 index 0000000..37336da --- /dev/null +++ b/web/src/pages/CommentsPage/CommentsPage.js @@ -0,0 +1,12 @@ +import CommentsLayout from 'src/layouts/CommentsLayout' +import CommentsCell from 'src/components/CommentsCell' + +const CommentsPage = () => { + return ( + + + + ) +} + +export default CommentsPage diff --git a/web/src/pages/EditCommentPage/EditCommentPage.js b/web/src/pages/EditCommentPage/EditCommentPage.js new file mode 100644 index 0000000..159f6af --- /dev/null +++ b/web/src/pages/EditCommentPage/EditCommentPage.js @@ -0,0 +1,12 @@ +import CommentsLayout from 'src/layouts/CommentsLayout' +import EditCommentCell from 'src/components/EditCommentCell' + +const EditCommentPage = ({ id }) => { + return ( + + + + ) +} + +export default EditCommentPage diff --git a/web/src/pages/EditPartPage/EditPartPage.js b/web/src/pages/EditPartPage/EditPartPage.js new file mode 100644 index 0000000..3634709 --- /dev/null +++ b/web/src/pages/EditPartPage/EditPartPage.js @@ -0,0 +1,12 @@ +import PartsLayout from 'src/layouts/PartsLayout' +import EditPartCell from 'src/components/EditPartCell' + +const EditPartPage = ({ id }) => { + return ( + + + + ) +} + +export default EditPartPage diff --git a/web/src/pages/EditPartReactionPage/EditPartReactionPage.js b/web/src/pages/EditPartReactionPage/EditPartReactionPage.js new file mode 100644 index 0000000..1ed29bd --- /dev/null +++ b/web/src/pages/EditPartReactionPage/EditPartReactionPage.js @@ -0,0 +1,12 @@ +import PartReactionsLayout from 'src/layouts/PartReactionsLayout' +import EditPartReactionCell from 'src/components/EditPartReactionCell' + +const EditPartReactionPage = ({ id }) => { + return ( + + + + ) +} + +export default EditPartReactionPage diff --git a/web/src/pages/EditUserPage/EditUserPage.js b/web/src/pages/EditUserPage/EditUserPage.js new file mode 100644 index 0000000..4cc6d38 --- /dev/null +++ b/web/src/pages/EditUserPage/EditUserPage.js @@ -0,0 +1,12 @@ +import UsersLayout from 'src/layouts/UsersLayout' +import EditUserCell from 'src/components/EditUserCell' + +const EditUserPage = ({ id }) => { + return ( + + + + ) +} + +export default EditUserPage diff --git a/web/src/pages/HomePage/HomePage.js b/web/src/pages/HomePage/HomePage.js index 94f1f89..8e247ce 100644 --- a/web/src/pages/HomePage/HomePage.js +++ b/web/src/pages/HomePage/HomePage.js @@ -1,5 +1,5 @@ import MainLayout from 'src/layouts/MainLayout' -import BlogPostsCell from 'src/components/BlogPostsCell' +// import BlogPostsCell from 'src/components/BlogPostsCell' import { initialize } from 'src/cascade/js/MainPage/CascadeMain' import { useEffect, useState } from 'react' @@ -27,7 +27,7 @@ Translate([-100, 0, 100], Text3D("cadhub.xyz")); // Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace! `; -const HomePage = () => { +const HomePage1 = () => { const [code, setCode] = useState(starterCode) useEffect(() => { const sickCallback = (code) => setCode(code) @@ -73,4 +73,12 @@ const HomePage = () => { ) } +const HomePage = () => { + return ( + + hi + + ) +} + export default HomePage diff --git a/web/src/pages/NewCommentPage/NewCommentPage.js b/web/src/pages/NewCommentPage/NewCommentPage.js new file mode 100644 index 0000000..d459c05 --- /dev/null +++ b/web/src/pages/NewCommentPage/NewCommentPage.js @@ -0,0 +1,12 @@ +import CommentsLayout from 'src/layouts/CommentsLayout' +import NewComment from 'src/components/NewComment' + +const NewCommentPage = () => { + return ( + + + + ) +} + +export default NewCommentPage diff --git a/web/src/pages/NewPartPage/NewPartPage.js b/web/src/pages/NewPartPage/NewPartPage.js new file mode 100644 index 0000000..4f39148 --- /dev/null +++ b/web/src/pages/NewPartPage/NewPartPage.js @@ -0,0 +1,12 @@ +import PartsLayout from 'src/layouts/PartsLayout' +import NewPart from 'src/components/NewPart' + +const NewPartPage = () => { + return ( + + + + ) +} + +export default NewPartPage diff --git a/web/src/pages/NewPartReactionPage/NewPartReactionPage.js b/web/src/pages/NewPartReactionPage/NewPartReactionPage.js new file mode 100644 index 0000000..931b1d2 --- /dev/null +++ b/web/src/pages/NewPartReactionPage/NewPartReactionPage.js @@ -0,0 +1,12 @@ +import PartReactionsLayout from 'src/layouts/PartReactionsLayout' +import NewPartReaction from 'src/components/NewPartReaction' + +const NewPartReactionPage = () => { + return ( + + + + ) +} + +export default NewPartReactionPage diff --git a/web/src/pages/NewUserPage/NewUserPage.js b/web/src/pages/NewUserPage/NewUserPage.js new file mode 100644 index 0000000..a3818b5 --- /dev/null +++ b/web/src/pages/NewUserPage/NewUserPage.js @@ -0,0 +1,12 @@ +import UsersLayout from 'src/layouts/UsersLayout' +import NewUser from 'src/components/NewUser' + +const NewUserPage = () => { + return ( + + + + ) +} + +export default NewUserPage diff --git a/web/src/pages/PartPage/PartPage.js b/web/src/pages/PartPage/PartPage.js new file mode 100644 index 0000000..e39c2fb --- /dev/null +++ b/web/src/pages/PartPage/PartPage.js @@ -0,0 +1,12 @@ +import PartsLayout from 'src/layouts/PartsLayout' +import PartCell from 'src/components/PartCell' + +const PartPage = ({ id }) => { + return ( + + + + ) +} + +export default PartPage diff --git a/web/src/pages/PartReactionPage/PartReactionPage.js b/web/src/pages/PartReactionPage/PartReactionPage.js new file mode 100644 index 0000000..9a014ef --- /dev/null +++ b/web/src/pages/PartReactionPage/PartReactionPage.js @@ -0,0 +1,12 @@ +import PartReactionsLayout from 'src/layouts/PartReactionsLayout' +import PartReactionCell from 'src/components/PartReactionCell' + +const PartReactionPage = ({ id }) => { + return ( + + + + ) +} + +export default PartReactionPage diff --git a/web/src/pages/PartReactionsPage/PartReactionsPage.js b/web/src/pages/PartReactionsPage/PartReactionsPage.js new file mode 100644 index 0000000..f6d927c --- /dev/null +++ b/web/src/pages/PartReactionsPage/PartReactionsPage.js @@ -0,0 +1,12 @@ +import PartReactionsLayout from 'src/layouts/PartReactionsLayout' +import PartReactionsCell from 'src/components/PartReactionsCell' + +const PartReactionsPage = () => { + return ( + + + + ) +} + +export default PartReactionsPage diff --git a/web/src/pages/PartsPage/PartsPage.js b/web/src/pages/PartsPage/PartsPage.js new file mode 100644 index 0000000..3d97fa8 --- /dev/null +++ b/web/src/pages/PartsPage/PartsPage.js @@ -0,0 +1,12 @@ +import PartsLayout from 'src/layouts/PartsLayout' +import PartsCell from 'src/components/PartsCell' + +const PartsPage = () => { + return ( + + + + ) +} + +export default PartsPage diff --git a/web/src/pages/UserPage/UserPage.js b/web/src/pages/UserPage/UserPage.js new file mode 100644 index 0000000..250b619 --- /dev/null +++ b/web/src/pages/UserPage/UserPage.js @@ -0,0 +1,12 @@ +import UsersLayout from 'src/layouts/UsersLayout' +import UserCell from 'src/components/UserCell' + +const UserPage = ({ id }) => { + return ( + + + + ) +} + +export default UserPage diff --git a/web/src/pages/UsersPage/UsersPage.js b/web/src/pages/UsersPage/UsersPage.js new file mode 100644 index 0000000..8f380ce --- /dev/null +++ b/web/src/pages/UsersPage/UsersPage.js @@ -0,0 +1,12 @@ +import UsersLayout from 'src/layouts/UsersLayout' +import UsersCell from 'src/components/UsersCell' + +const UsersPage = () => { + return ( + + + + ) +} + +export default UsersPage From faffc0f46d54bd6d398cd4b0a1e9c3a45a5bfae5 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Mon, 2 Nov 2020 07:09:22 +1100 Subject: [PATCH 04/24] Use a common layout for all pages --- .../layouts/CommentsLayout/CommentsLayout.js | 23 ---------------- .../PartReactionsLayout.js | 26 ------------------- web/src/layouts/PartsLayout/PartsLayout.js | 23 ---------------- web/src/layouts/UsersLayout/UsersLayout.js | 23 ---------------- web/src/pages/CommentPage/CommentPage.js | 6 ++--- web/src/pages/CommentsPage/CommentsPage.js | 6 ++--- .../pages/EditCommentPage/EditCommentPage.js | 6 ++--- web/src/pages/EditPartPage/EditPartPage.js | 6 ++--- .../EditPartReactionPage.js | 6 ++--- web/src/pages/EditUserPage/EditUserPage.js | 6 ++--- .../pages/NewCommentPage/NewCommentPage.js | 6 ++--- web/src/pages/NewPartPage/NewPartPage.js | 6 ++--- .../NewPartReactionPage.js | 6 ++--- web/src/pages/NewUserPage/NewUserPage.js | 6 ++--- web/src/pages/PartPage/PartPage.js | 6 ++--- .../PartReactionPage/PartReactionPage.js | 6 ++--- .../PartReactionsPage/PartReactionsPage.js | 6 ++--- web/src/pages/PartsPage/PartsPage.js | 6 ++--- web/src/pages/UserPage/UserPage.js | 6 ++--- web/src/pages/UsersPage/UsersPage.js | 6 ++--- 20 files changed, 48 insertions(+), 143 deletions(-) delete mode 100644 web/src/layouts/CommentsLayout/CommentsLayout.js delete mode 100644 web/src/layouts/PartReactionsLayout/PartReactionsLayout.js delete mode 100644 web/src/layouts/PartsLayout/PartsLayout.js delete mode 100644 web/src/layouts/UsersLayout/UsersLayout.js diff --git a/web/src/layouts/CommentsLayout/CommentsLayout.js b/web/src/layouts/CommentsLayout/CommentsLayout.js deleted file mode 100644 index 4ed9e72..0000000 --- a/web/src/layouts/CommentsLayout/CommentsLayout.js +++ /dev/null @@ -1,23 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' -import { Flash } from '@redwoodjs/web' - -const CommentsLayout = (props) => { - return ( -
    - -
    -

    - - Comments - -

    - -
    +
    New Comment - -
    -
    {props.children}
    -
    - ) -} - -export default CommentsLayout diff --git a/web/src/layouts/PartReactionsLayout/PartReactionsLayout.js b/web/src/layouts/PartReactionsLayout/PartReactionsLayout.js deleted file mode 100644 index 076c5b2..0000000 --- a/web/src/layouts/PartReactionsLayout/PartReactionsLayout.js +++ /dev/null @@ -1,26 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' -import { Flash } from '@redwoodjs/web' - -const PartReactionsLayout = (props) => { - return ( -
    - -
    -

    - - PartReactions - -

    - -
    +
    New PartReaction - -
    -
    {props.children}
    -
    - ) -} - -export default PartReactionsLayout diff --git a/web/src/layouts/PartsLayout/PartsLayout.js b/web/src/layouts/PartsLayout/PartsLayout.js deleted file mode 100644 index f0ecd0c..0000000 --- a/web/src/layouts/PartsLayout/PartsLayout.js +++ /dev/null @@ -1,23 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' -import { Flash } from '@redwoodjs/web' - -const PartsLayout = (props) => { - return ( -
    - -
    -

    - - Parts - -

    - -
    +
    New Part - -
    -
    {props.children}
    -
    - ) -} - -export default PartsLayout diff --git a/web/src/layouts/UsersLayout/UsersLayout.js b/web/src/layouts/UsersLayout/UsersLayout.js deleted file mode 100644 index f4f055f..0000000 --- a/web/src/layouts/UsersLayout/UsersLayout.js +++ /dev/null @@ -1,23 +0,0 @@ -import { Link, routes } from '@redwoodjs/router' -import { Flash } from '@redwoodjs/web' - -const UsersLayout = (props) => { - return ( -
    - -
    -

    - - Users - -

    - -
    +
    New User - -
    -
    {props.children}
    -
    - ) -} - -export default UsersLayout diff --git a/web/src/pages/CommentPage/CommentPage.js b/web/src/pages/CommentPage/CommentPage.js index b4365f8..ea476db 100644 --- a/web/src/pages/CommentPage/CommentPage.js +++ b/web/src/pages/CommentPage/CommentPage.js @@ -1,11 +1,11 @@ -import CommentsLayout from 'src/layouts/CommentsLayout' +import MainLayout from 'src/layouts/MainLayout' import CommentCell from 'src/components/CommentCell' const CommentPage = ({ id }) => { return ( - + - + ) } diff --git a/web/src/pages/CommentsPage/CommentsPage.js b/web/src/pages/CommentsPage/CommentsPage.js index 37336da..eae6bf3 100644 --- a/web/src/pages/CommentsPage/CommentsPage.js +++ b/web/src/pages/CommentsPage/CommentsPage.js @@ -1,11 +1,11 @@ -import CommentsLayout from 'src/layouts/CommentsLayout' +import MainLayout from 'src/layouts/MainLayout' import CommentsCell from 'src/components/CommentsCell' const CommentsPage = () => { return ( - + - + ) } diff --git a/web/src/pages/EditCommentPage/EditCommentPage.js b/web/src/pages/EditCommentPage/EditCommentPage.js index 159f6af..966739f 100644 --- a/web/src/pages/EditCommentPage/EditCommentPage.js +++ b/web/src/pages/EditCommentPage/EditCommentPage.js @@ -1,11 +1,11 @@ -import CommentsLayout from 'src/layouts/CommentsLayout' +import MainLayout from 'src/layouts/MainLayout' import EditCommentCell from 'src/components/EditCommentCell' const EditCommentPage = ({ id }) => { return ( - + - + ) } diff --git a/web/src/pages/EditPartPage/EditPartPage.js b/web/src/pages/EditPartPage/EditPartPage.js index 3634709..4d6eb43 100644 --- a/web/src/pages/EditPartPage/EditPartPage.js +++ b/web/src/pages/EditPartPage/EditPartPage.js @@ -1,11 +1,11 @@ -import PartsLayout from 'src/layouts/PartsLayout' +import MainLayout from 'src/layouts/MainLayout' import EditPartCell from 'src/components/EditPartCell' const EditPartPage = ({ id }) => { return ( - + - + ) } diff --git a/web/src/pages/EditPartReactionPage/EditPartReactionPage.js b/web/src/pages/EditPartReactionPage/EditPartReactionPage.js index 1ed29bd..f57b936 100644 --- a/web/src/pages/EditPartReactionPage/EditPartReactionPage.js +++ b/web/src/pages/EditPartReactionPage/EditPartReactionPage.js @@ -1,11 +1,11 @@ -import PartReactionsLayout from 'src/layouts/PartReactionsLayout' +import MainLayout from 'src/layouts/MainLayout' import EditPartReactionCell from 'src/components/EditPartReactionCell' const EditPartReactionPage = ({ id }) => { return ( - + - + ) } diff --git a/web/src/pages/EditUserPage/EditUserPage.js b/web/src/pages/EditUserPage/EditUserPage.js index 4cc6d38..5c8fa8d 100644 --- a/web/src/pages/EditUserPage/EditUserPage.js +++ b/web/src/pages/EditUserPage/EditUserPage.js @@ -1,11 +1,11 @@ -import UsersLayout from 'src/layouts/UsersLayout' +import MainLayout from 'src/layouts/MainLayout' import EditUserCell from 'src/components/EditUserCell' const EditUserPage = ({ id }) => { return ( - + - + ) } diff --git a/web/src/pages/NewCommentPage/NewCommentPage.js b/web/src/pages/NewCommentPage/NewCommentPage.js index d459c05..6526345 100644 --- a/web/src/pages/NewCommentPage/NewCommentPage.js +++ b/web/src/pages/NewCommentPage/NewCommentPage.js @@ -1,11 +1,11 @@ -import CommentsLayout from 'src/layouts/CommentsLayout' +import MainLayout from 'src/layouts/MainLayout' import NewComment from 'src/components/NewComment' const NewCommentPage = () => { return ( - + - + ) } diff --git a/web/src/pages/NewPartPage/NewPartPage.js b/web/src/pages/NewPartPage/NewPartPage.js index 4f39148..c3e7d11 100644 --- a/web/src/pages/NewPartPage/NewPartPage.js +++ b/web/src/pages/NewPartPage/NewPartPage.js @@ -1,11 +1,11 @@ -import PartsLayout from 'src/layouts/PartsLayout' +import MainLayout from 'src/layouts/MainLayout' import NewPart from 'src/components/NewPart' const NewPartPage = () => { return ( - + - + ) } diff --git a/web/src/pages/NewPartReactionPage/NewPartReactionPage.js b/web/src/pages/NewPartReactionPage/NewPartReactionPage.js index 931b1d2..206b815 100644 --- a/web/src/pages/NewPartReactionPage/NewPartReactionPage.js +++ b/web/src/pages/NewPartReactionPage/NewPartReactionPage.js @@ -1,11 +1,11 @@ -import PartReactionsLayout from 'src/layouts/PartReactionsLayout' +import MainLayout from 'src/layouts/MainLayout' import NewPartReaction from 'src/components/NewPartReaction' const NewPartReactionPage = () => { return ( - + - + ) } diff --git a/web/src/pages/NewUserPage/NewUserPage.js b/web/src/pages/NewUserPage/NewUserPage.js index a3818b5..0368b02 100644 --- a/web/src/pages/NewUserPage/NewUserPage.js +++ b/web/src/pages/NewUserPage/NewUserPage.js @@ -1,11 +1,11 @@ -import UsersLayout from 'src/layouts/UsersLayout' +import MainLayout from 'src/layouts/MainLayout' import NewUser from 'src/components/NewUser' const NewUserPage = () => { return ( - + - + ) } diff --git a/web/src/pages/PartPage/PartPage.js b/web/src/pages/PartPage/PartPage.js index e39c2fb..5835dbf 100644 --- a/web/src/pages/PartPage/PartPage.js +++ b/web/src/pages/PartPage/PartPage.js @@ -1,11 +1,11 @@ -import PartsLayout from 'src/layouts/PartsLayout' +import MainLayout from 'src/layouts/MainLayout' import PartCell from 'src/components/PartCell' const PartPage = ({ id }) => { return ( - + - + ) } diff --git a/web/src/pages/PartReactionPage/PartReactionPage.js b/web/src/pages/PartReactionPage/PartReactionPage.js index 9a014ef..849f002 100644 --- a/web/src/pages/PartReactionPage/PartReactionPage.js +++ b/web/src/pages/PartReactionPage/PartReactionPage.js @@ -1,11 +1,11 @@ -import PartReactionsLayout from 'src/layouts/PartReactionsLayout' +import MainLayout from 'src/layouts/MainLayout' import PartReactionCell from 'src/components/PartReactionCell' const PartReactionPage = ({ id }) => { return ( - + - + ) } diff --git a/web/src/pages/PartReactionsPage/PartReactionsPage.js b/web/src/pages/PartReactionsPage/PartReactionsPage.js index f6d927c..1dab5ae 100644 --- a/web/src/pages/PartReactionsPage/PartReactionsPage.js +++ b/web/src/pages/PartReactionsPage/PartReactionsPage.js @@ -1,11 +1,11 @@ -import PartReactionsLayout from 'src/layouts/PartReactionsLayout' +import MainLayout from 'src/layouts/MainLayout' import PartReactionsCell from 'src/components/PartReactionsCell' const PartReactionsPage = () => { return ( - + - + ) } diff --git a/web/src/pages/PartsPage/PartsPage.js b/web/src/pages/PartsPage/PartsPage.js index 3d97fa8..b96b998 100644 --- a/web/src/pages/PartsPage/PartsPage.js +++ b/web/src/pages/PartsPage/PartsPage.js @@ -1,11 +1,11 @@ -import PartsLayout from 'src/layouts/PartsLayout' +import MainLayout from 'src/layouts/MainLayout' import PartsCell from 'src/components/PartsCell' const PartsPage = () => { return ( - + - + ) } diff --git a/web/src/pages/UserPage/UserPage.js b/web/src/pages/UserPage/UserPage.js index 250b619..cf81dc9 100644 --- a/web/src/pages/UserPage/UserPage.js +++ b/web/src/pages/UserPage/UserPage.js @@ -1,11 +1,11 @@ -import UsersLayout from 'src/layouts/UsersLayout' +import MainLayout from 'src/layouts/MainLayout' import UserCell from 'src/components/UserCell' const UserPage = ({ id }) => { return ( - + - + ) } diff --git a/web/src/pages/UsersPage/UsersPage.js b/web/src/pages/UsersPage/UsersPage.js index 8f380ce..7331b05 100644 --- a/web/src/pages/UsersPage/UsersPage.js +++ b/web/src/pages/UsersPage/UsersPage.js @@ -1,11 +1,11 @@ -import UsersLayout from 'src/layouts/UsersLayout' +import MainLayout from 'src/layouts/MainLayout' import UsersCell from 'src/components/UsersCell' const UsersPage = () => { return ( - + - + ) } From a28f126f9ce694a5f7f7e6d97fc55529ab94d01e Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Tue, 3 Nov 2020 20:09:31 +1100 Subject: [PATCH 05/24] Update image uploader to service as avatar as well as uploader --- .vscode/settings.json | 3 + .../components/ImageUploader/ImageUploader.js | 121 ++++++++++++++++++ .../ImageUploader/ImageUploader.stories.js | 42 ++++++ .../ImageUploader/ImageUploader.test.js | 11 ++ web/tailwind.config.js | 3 + 5 files changed, 180 insertions(+) create mode 100644 web/src/components/ImageUploader/ImageUploader.js create mode 100644 web/src/components/ImageUploader/ImageUploader.stories.js create mode 100644 web/src/components/ImageUploader/ImageUploader.test.js diff --git a/.vscode/settings.json b/.vscode/settings.json index a95220c..65a4f69 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,5 +15,8 @@ "./web/src/pages", "./web/src/index.js", "./web/src/Routes.js", + ], + "cSpell.words": [ + "Uploader" ] } diff --git a/web/src/components/ImageUploader/ImageUploader.js b/web/src/components/ImageUploader/ImageUploader.js new file mode 100644 index 0000000..39e78a4 --- /dev/null +++ b/web/src/components/ImageUploader/ImageUploader.js @@ -0,0 +1,121 @@ +import React, { useCallback, useState } from "react"; +import { useDropzone } from "react-dropzone"; +import Button from "@material-ui/core/Button"; +import axios from 'axios' +import ReactCrop from 'react-image-crop' +import { Dialog } from '@material-ui/core' +import { Image as CloudinaryImage } from 'cloudinary-react' +import 'react-image-crop/dist/ReactCrop.css' +import Svg from 'src/components/Svg/Svg.js' + +const CLOUDINARY_UPLOAD_PRESET = "CadHub_project_images"; +const CLOUDINARY_UPLOAD_URL = "https://api.cloudinary.com/v1_1/irevdev/upload"; + +export default function ImageUploader({ onImageUpload, imageUrl, aspectRatio, className, isEditable }) { + const [isModalOpen, setIsModalOpen] = useState(false) + const [file, setFile] = useState() + const [cloudinaryId, setCloudinaryId] = useState(imageUrl) + const [imageObj, setImageObj] = useState() + const [crop, setCrop] = useState({ + aspect: aspectRatio, + unit: '%', + width: 100, + }); + async function handleImageUpload() { + const croppedFile = await getCroppedImg(imageObj, crop, 'avatar') + console.log(croppedFile) + const imageData = new FormData(); + imageData.append('upload_preset', CLOUDINARY_UPLOAD_PRESET); + imageData.append('file', croppedFile); + let upload = axios.post(CLOUDINARY_UPLOAD_URL, imageData) + try { + const { data } = await upload + if (data && data.public_id !== "") { + onImageUpload({cloudinaryPublicId: data.public_id}) + setCloudinaryId(data.public_id) + setIsModalOpen(false) + } + } catch (e) { + console.error('ERROR', e) + } + } + // Drag and Drop + const onDrop = useCallback(acceptedFiles => { + setIsModalOpen(true) + const fileReader = new FileReader() + fileReader.onload = () => { + setFile(fileReader.result) + } + fileReader.readAsDataURL(acceptedFiles[0]) + }, []); + + const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop }); + return ( +
    +
    + {cloudinaryId && isEditable && } + {isEditable && } + {(cloudinaryId || !isEditable) &&
    + +
    } + {!cloudinaryId && } + {!cloudinaryId && isEditable &&
    +
    + Drop files here ... + or + upload + +
    +
    } +
    + setIsModalOpen(false)} + > +
    + setImageObj(image)} onChange={newCrop => setCrop(newCrop)} /> + +
    +
    +
    + ); +} + +function getCroppedImg(image, crop, fileName) { + const canvas = document.createElement('canvas'); + const scaleX = image.naturalWidth / image.width; + const scaleY = image.naturalHeight / image.height; + canvas.width = crop.width; + canvas.height = crop.height; + const ctx = canvas.getContext('2d'); + ctx.drawImage( + image, + crop.x * scaleX, + crop.y * scaleY, + crop.width * scaleX, + crop.height * scaleY, + 0, + 0, + crop.width, + crop.height + ); + + // As Base64 string + // const base64Image = canvas.toDataURL('image/jpeg'); + + // As a blob + return new Promise((resolve, reject) => { + canvas.toBlob(blob => { + blob.name = fileName; + resolve(blob); + }, 'image/jpeg', 1); + }); +} diff --git a/web/src/components/ImageUploader/ImageUploader.stories.js b/web/src/components/ImageUploader/ImageUploader.stories.js new file mode 100644 index 0000000..f5b9f65 --- /dev/null +++ b/web/src/components/ImageUploader/ImageUploader.stories.js @@ -0,0 +1,42 @@ +import ImageUploader from './ImageUploader' + +export const generated = () => { + return ( + <> +

    AspectRatio:1, no initial image, editable

    + < + ImageUploader + onImageUpload={({cloudinaryPublicId}) => console.log(cloudinaryPublicId)} + aspectRatio={1} + isEditable={true} + className={"bg-red-400 rounded-half rounded-br-xl"} + /> +

    AspectRatio 16:9, no initial image, editable

    + < + ImageUploader + onImageUpload={({cloudinaryPublicId}) => console.log(cloudinaryPublicId)} + aspectRatio={16/9} + isEditable={true} + className={"bg-red-400 rounded-xl"} + imageUrl="CadHub/inakek2urbreynblzhgt" + /> +

    AspectRatio:1, no initial image, NOT editable

    + < + ImageUploader + onImageUpload={({cloudinaryPublicId}) => console.log(cloudinaryPublicId)} + aspectRatio={1} + className={"rounded-half rounded-br-xl"} + /> +

    AspectRatio ,16:9 no initial image, NOT editable

    + < + ImageUploader + onImageUpload={({cloudinaryPublicId}) => console.log(cloudinaryPublicId)} + aspectRatio={16/9} + className={"rounded-xl"} + imageUrl="CadHub/inakek2urbreynblzhgt" + /> + + ) +} + +export default { title: 'Components/ImageUploader' } diff --git a/web/src/components/ImageUploader/ImageUploader.test.js b/web/src/components/ImageUploader/ImageUploader.test.js new file mode 100644 index 0000000..1a05ab3 --- /dev/null +++ b/web/src/components/ImageUploader/ImageUploader.test.js @@ -0,0 +1,11 @@ +import { render } from '@redwoodjs/testing' + +import ImageUploader from './ImageUploader' + +describe('ImageUploader', () => { + it('renders successfully', () => { + expect(() => { + render() + }).not.toThrow() + }) +}) diff --git a/web/tailwind.config.js b/web/tailwind.config.js index c15b6f2..c49984b 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -22,6 +22,9 @@ module.exports = { }, skew: { '-20': "-20deg" + }, + borderRadius: { + half: '50%', } } }, From 217cb31ed2b1f9aae21df8eca7fa09e8dc17e8ef Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Wed, 4 Nov 2020 07:21:47 +1100 Subject: [PATCH 06/24] Add display user page --- api/src/graphql/users.sdl.js | 1 + api/src/services/users/users.js | 6 ++ web/src/Routes.js | 10 ++- web/src/components/Button/Button.js | 17 ++++++ web/src/components/Button/Button.stories.js | 10 +++ web/src/components/Button/Button.test.js | 11 ++++ .../components/ImageUploader/ImageUploader.js | 6 +- web/src/components/Svg/Svg.js | 2 +- web/src/components/User2Cell/User2Cell.js | 61 +++++++++++++++++++ web/src/layouts/MainLayout/MainLayout.js | 8 +-- web/src/pages/UserPage2/UserPage2.js | 12 ++++ 11 files changed, 132 insertions(+), 12 deletions(-) create mode 100644 web/src/components/Button/Button.js create mode 100644 web/src/components/Button/Button.stories.js create mode 100644 web/src/components/Button/Button.test.js create mode 100644 web/src/components/User2Cell/User2Cell.js create mode 100644 web/src/pages/UserPage2/UserPage2.js diff --git a/api/src/graphql/users.sdl.js b/api/src/graphql/users.sdl.js index 4e25e97..44fe21a 100644 --- a/api/src/graphql/users.sdl.js +++ b/api/src/graphql/users.sdl.js @@ -15,6 +15,7 @@ export const schema = gql` type Query { users: [User!]! user(id: String!): User + userName(userName: String!): User } input CreateUserInput { diff --git a/api/src/services/users/users.js b/api/src/services/users/users.js index 9a10d66..5e4522b 100644 --- a/api/src/services/users/users.js +++ b/api/src/services/users/users.js @@ -10,6 +10,12 @@ export const user = ({ id }) => { }) } +export const userName = ({ userName }) => { + return db.user.findOne({ + where: { userName }, + }) +} + export const createUser = ({ input }) => { return db.user.create({ data: input, diff --git a/web/src/Routes.js b/web/src/Routes.js index 257a6ee..798f9e5 100644 --- a/web/src/Routes.js +++ b/web/src/Routes.js @@ -12,6 +12,13 @@ import { Router, Route, Private } from '@redwoodjs/router' const Routes = () => { return ( + + {/* */} + + + + + {/* GENERATED ROUTES BELOW, probably going to clean these up and delete most of them, but the CRUD functionality is useful for now */} @@ -28,9 +35,6 @@ const Routes = () => { - - {/* */} - ) } diff --git a/web/src/components/Button/Button.js b/web/src/components/Button/Button.js new file mode 100644 index 0000000..38277a1 --- /dev/null +++ b/web/src/components/Button/Button.js @@ -0,0 +1,17 @@ +import Svg from 'src/components/Svg' + +const Button = ({onClick, children}) => { + return ( +
    + +
    + ) +} + +export default Button diff --git a/web/src/components/Button/Button.stories.js b/web/src/components/Button/Button.stories.js new file mode 100644 index 0000000..7d95d2d --- /dev/null +++ b/web/src/components/Button/Button.stories.js @@ -0,0 +1,10 @@ +import Button from './Button' + +export const generated = () => { + return <> + button with icon + + +} + +export default { title: 'Components/Button' } diff --git a/web/src/components/Button/Button.test.js b/web/src/components/Button/Button.test.js new file mode 100644 index 0000000..b0f1d6e --- /dev/null +++ b/web/src/components/Button/Button.test.js @@ -0,0 +1,11 @@ +import { render } from '@redwoodjs/testing' + +import Button from './Button' + +describe('Button', () => { + it('renders successfully', () => { + expect(() => { + render(} {isEditable && } - {(cloudinaryId || !isEditable) &&
    + {(cloudinaryId || !isEditable) &&
    { } - return
    + return
    {svgs[name]}
    } diff --git a/web/src/components/User2Cell/User2Cell.js b/web/src/components/User2Cell/User2Cell.js new file mode 100644 index 0000000..791cbb7 --- /dev/null +++ b/web/src/components/User2Cell/User2Cell.js @@ -0,0 +1,61 @@ +import User from 'src/components/User' +import {Fragment} from 'react' +import ImageUploader from 'src/components/ImageUploader' +import Button from 'src/components/Button' +import Editor from "rich-markdown-editor"; + +export const QUERY = gql` + query FIND_USER_BY_ID($userName: String!) { + user: userName(userName: $userName) { + id + userName + email + createdAt + updatedAt + image + bio + } + } +` + +export const Loading = () =>
    Loading...
    + +export const Empty = () =>
    User not found
    + +export const Success = ({ user }) => { + const {userName, email} = user + const keyValueDisplay = Object.entries({userName, name: email}) // TODO add name field to user + return ( + <> +
    +
    +
    + +
    +
    +
    + {keyValueDisplay.map(([property, value]) => ( + {property}: + {value} + ))} +
    + +
    +
    +
    +

    Bio:

    +
    + +
    +
    +
    + + ) +} diff --git a/web/src/layouts/MainLayout/MainLayout.js b/web/src/layouts/MainLayout/MainLayout.js index 7e00667..5baf22d 100644 --- a/web/src/layouts/MainLayout/MainLayout.js +++ b/web/src/layouts/MainLayout/MainLayout.js @@ -16,11 +16,9 @@ const MainLayout = ({ children }) => {
    • - - - - - +
      + +
    • diff --git a/web/src/pages/UserPage2/UserPage2.js b/web/src/pages/UserPage2/UserPage2.js new file mode 100644 index 0000000..efc80bb --- /dev/null +++ b/web/src/pages/UserPage2/UserPage2.js @@ -0,0 +1,12 @@ +import MainLayout from 'src/layouts/MainLayout' +import User2Cell from 'src/components/User2Cell' + +const UserPage = ({ userName }) => { + return ( + + + + ) +} + +export default UserPage From 249dbaba1ad911da49c41cd1804adc48d4c3d4cb Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Thu, 5 Nov 2020 06:47:55 +1100 Subject: [PATCH 07/24] Style userProfile display and editable --- web/src/Routes.js | 3 +- web/src/components/Button/Button.js | 4 +- .../components/EditUser2Cell/EditUser2Cell.js | 25 ++++++++++ .../EditUser2Cell/EditUser2Cell.mock.js | 6 +++ .../EditUser2Cell/EditUser2Cell.stories.js | 20 ++++++++ .../EditUser2Cell/EditUser2Cell.test.js | 26 +++++++++++ .../components/ImageUploader/ImageUploader.js | 4 +- .../ProfileTextInput/ProfileTextInput.js | 29 ++++++++++++ .../ProfileTextInput.stories.js | 7 +++ .../ProfileTextInput/ProfileTextInput.test.js | 11 +++++ web/src/components/User2Cell/User2Cell.js | 44 ++---------------- web/src/components/UserProfile/UserProfile.js | 46 +++++++++++++++++++ .../UserProfile/UserProfile.stories.js | 7 +++ .../UserProfile/UserProfile.test.js | 11 +++++ web/src/index.css | 2 +- web/src/pages/EditUser2Page/EditUser2Page.js | 12 +++++ .../UserPage2.js => User2Page/User2Page.js} | 0 17 files changed, 210 insertions(+), 47 deletions(-) create mode 100644 web/src/components/EditUser2Cell/EditUser2Cell.js create mode 100644 web/src/components/EditUser2Cell/EditUser2Cell.mock.js create mode 100644 web/src/components/EditUser2Cell/EditUser2Cell.stories.js create mode 100644 web/src/components/EditUser2Cell/EditUser2Cell.test.js create mode 100644 web/src/components/ProfileTextInput/ProfileTextInput.js create mode 100644 web/src/components/ProfileTextInput/ProfileTextInput.stories.js create mode 100644 web/src/components/ProfileTextInput/ProfileTextInput.test.js create mode 100644 web/src/components/UserProfile/UserProfile.js create mode 100644 web/src/components/UserProfile/UserProfile.stories.js create mode 100644 web/src/components/UserProfile/UserProfile.test.js create mode 100644 web/src/pages/EditUser2Page/EditUser2Page.js rename web/src/pages/{UserPage2/UserPage2.js => User2Page/User2Page.js} (100%) diff --git a/web/src/Routes.js b/web/src/Routes.js index 798f9e5..b7a253c 100644 --- a/web/src/Routes.js +++ b/web/src/Routes.js @@ -16,7 +16,8 @@ const Routes = () => { {/* */} - + + {/* GENERATED ROUTES BELOW, probably going to clean these up and delete most of them, but the CRUD functionality is useful for now */} diff --git a/web/src/components/Button/Button.js b/web/src/components/Button/Button.js index 38277a1..c327ec1 100644 --- a/web/src/components/Button/Button.js +++ b/web/src/components/Button/Button.js @@ -1,6 +1,6 @@ import Svg from 'src/components/Svg' -const Button = ({onClick, children}) => { +const Button = ({onClick, iconName, children}) => { return (
      ) diff --git a/web/src/components/EditUser2Cell/EditUser2Cell.js b/web/src/components/EditUser2Cell/EditUser2Cell.js new file mode 100644 index 0000000..07656aa --- /dev/null +++ b/web/src/components/EditUser2Cell/EditUser2Cell.js @@ -0,0 +1,25 @@ +import UserProfile from 'src/components/UserProfile' + +export const QUERY = gql` + query FIND_USER_BY_ID($userName: String!) { + user: userName(userName: $userName) { + id + userName + email + createdAt + updatedAt + image + bio + } + } +` + +export const Loading = () =>
      Loading...
      + +export const Empty = () =>
      Empty
      + +export const Failure = ({ error }) =>
      Error: {error.message}
      + +export const Success = ({ user }) => { + return +} diff --git a/web/src/components/EditUser2Cell/EditUser2Cell.mock.js b/web/src/components/EditUser2Cell/EditUser2Cell.mock.js new file mode 100644 index 0000000..99b257c --- /dev/null +++ b/web/src/components/EditUser2Cell/EditUser2Cell.mock.js @@ -0,0 +1,6 @@ +// Define your own mock data here: +export const standard = (/* vars, { ctx, req } */) => ({ + editUser2: { + id: 42, + }, +}) diff --git a/web/src/components/EditUser2Cell/EditUser2Cell.stories.js b/web/src/components/EditUser2Cell/EditUser2Cell.stories.js new file mode 100644 index 0000000..d416704 --- /dev/null +++ b/web/src/components/EditUser2Cell/EditUser2Cell.stories.js @@ -0,0 +1,20 @@ +import { Loading, Empty, Failure, Success } from './EditUser2Cell' +import { standard } from './EditUser2Cell.mock' + +export const loading = () => { + return Loading ? : null +} + +export const empty = () => { + return Empty ? : null +} + +export const failure = () => { + return Failure ? : null +} + +export const success = () => { + return Success ? : null +} + +export default { title: 'Cells/EditUser2Cell' } diff --git a/web/src/components/EditUser2Cell/EditUser2Cell.test.js b/web/src/components/EditUser2Cell/EditUser2Cell.test.js new file mode 100644 index 0000000..eb9b86f --- /dev/null +++ b/web/src/components/EditUser2Cell/EditUser2Cell.test.js @@ -0,0 +1,26 @@ +import { render, screen } from '@redwoodjs/testing' +import { Loading, Empty, Failure, Success } from './EditUser2Cell' +import { standard } from './EditUser2Cell.mock' + +describe('EditUser2Cell', () => { + test('Loading renders successfully', () => { + render() + // Use screen.debug() to see output + expect(screen.getByText('Loading...')).toBeInTheDocument() + }) + + test('Empty renders successfully', async () => { + render() + expect(screen.getByText('Empty')).toBeInTheDocument() + }) + + test('Failure renders successfully', async () => { + render() + expect(screen.getByText(/Oh no/i)).toBeInTheDocument() + }) + + test('Success renders successfully', async () => { + render() + expect(screen.getByText(/42/i)).toBeInTheDocument() + }) +}) diff --git a/web/src/components/ImageUploader/ImageUploader.js b/web/src/components/ImageUploader/ImageUploader.js index 1d2a614..819b236 100644 --- a/web/src/components/ImageUploader/ImageUploader.js +++ b/web/src/components/ImageUploader/ImageUploader.js @@ -68,9 +68,9 @@ export default function ImageUploader({ onImageUpload, imageUrl, aspectRatio, cl
    } {!cloudinaryId && } {!cloudinaryId && isEditable &&
    -
    +
    Drop files here ... - or + or upload
    diff --git a/web/src/components/ProfileTextInput/ProfileTextInput.js b/web/src/components/ProfileTextInput/ProfileTextInput.js new file mode 100644 index 0000000..d0b07d5 --- /dev/null +++ b/web/src/components/ProfileTextInput/ProfileTextInput.js @@ -0,0 +1,29 @@ +import {Fragment, useState} from 'react' + +const ProfileTextInput = ({fields, isEditable, onChange= () => {}}) => { + const keyValueDisplay = Object.entries(fields) + return ( +
    +
    + {keyValueDisplay.map(([property, value]) => ( + {property}: + { + isEditable ? +
    +
    + onChange({...fields, [property]: target.value})} + value={value} + type="text" + /> +
    : + {value} + } + ))} +
    +
    + ) +} + +export default ProfileTextInput diff --git a/web/src/components/ProfileTextInput/ProfileTextInput.stories.js b/web/src/components/ProfileTextInput/ProfileTextInput.stories.js new file mode 100644 index 0000000..daef953 --- /dev/null +++ b/web/src/components/ProfileTextInput/ProfileTextInput.stories.js @@ -0,0 +1,7 @@ +import ProfileTextInput from './ProfileTextInput' + +export const generated = () => { + return +} + +export default { title: 'Components/ProfileTextInput' } diff --git a/web/src/components/ProfileTextInput/ProfileTextInput.test.js b/web/src/components/ProfileTextInput/ProfileTextInput.test.js new file mode 100644 index 0000000..e5f6e14 --- /dev/null +++ b/web/src/components/ProfileTextInput/ProfileTextInput.test.js @@ -0,0 +1,11 @@ +import { render } from '@redwoodjs/testing' + +import ProfileTextInput from './ProfileTextInput' + +describe('ProfileTextInput', () => { + it('renders successfully', () => { + expect(() => { + render() + }).not.toThrow() + }) +}) diff --git a/web/src/components/User2Cell/User2Cell.js b/web/src/components/User2Cell/User2Cell.js index 791cbb7..faea1cd 100644 --- a/web/src/components/User2Cell/User2Cell.js +++ b/web/src/components/User2Cell/User2Cell.js @@ -1,8 +1,4 @@ -import User from 'src/components/User' -import {Fragment} from 'react' -import ImageUploader from 'src/components/ImageUploader' -import Button from 'src/components/Button' -import Editor from "rich-markdown-editor"; +import UserProfile from 'src/components/UserProfile' export const QUERY = gql` query FIND_USER_BY_ID($userName: String!) { @@ -22,40 +18,6 @@ export const Loading = () =>
    Loading...
    export const Empty = () =>
    User not found
    -export const Success = ({ user }) => { - const {userName, email} = user - const keyValueDisplay = Object.entries({userName, name: email}) // TODO add name field to user - return ( - <> -
    -
    -
    - -
    -
    -
    - {keyValueDisplay.map(([property, value]) => ( - {property}: - {value} - ))} -
    - -
    -
    -
    -

    Bio:

    -
    - -
    -
    -
    - - ) +export const Success = ({user}) => { + return } diff --git a/web/src/components/UserProfile/UserProfile.js b/web/src/components/UserProfile/UserProfile.js new file mode 100644 index 0000000..62bf827 --- /dev/null +++ b/web/src/components/UserProfile/UserProfile.js @@ -0,0 +1,46 @@ +import {Fragment} from 'react' +import ImageUploader from 'src/components/ImageUploader' +import Button from 'src/components/Button' +import Editor from "rich-markdown-editor"; +import ProfileTextInput from 'src/components/ProfileTextInput' + + +const UserProfile = ({user, isEditable}) => { + console.log(isEditable) + const {userName, email} = user + const editableTextFields = {userName, name: email} // TODO add name field to user + return ( + <> +
    +
    +
    + +
    +
    + + {isEditable ? + : // TODO replace pencil with a save icon + + } +
    +
    +
    +

    Bio:

    +
    + +
    +
    +
    + + ) +} + +export default UserProfile diff --git a/web/src/components/UserProfile/UserProfile.stories.js b/web/src/components/UserProfile/UserProfile.stories.js new file mode 100644 index 0000000..f53091f --- /dev/null +++ b/web/src/components/UserProfile/UserProfile.stories.js @@ -0,0 +1,7 @@ +import UserProfile from './UserProfile' + +export const generated = () => { + return +} + +export default { title: 'Components/UserProfile' } diff --git a/web/src/components/UserProfile/UserProfile.test.js b/web/src/components/UserProfile/UserProfile.test.js new file mode 100644 index 0000000..d4ffd8d --- /dev/null +++ b/web/src/components/UserProfile/UserProfile.test.js @@ -0,0 +1,11 @@ +import { render } from '@redwoodjs/testing' + +import UserProfile from './UserProfile' + +describe('UserProfile', () => { + it('renders successfully', () => { + expect(() => { + render() + }).not.toThrow() + }) +}) diff --git a/web/src/index.css b/web/src/index.css index 5b01aec..46d152f 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -36,7 +36,7 @@ body { /* TODO can I use a tailwind class here? */ - background-color: #E5E5E5; + background-color: #f7fafc; } button, input, label, textarea { diff --git a/web/src/pages/EditUser2Page/EditUser2Page.js b/web/src/pages/EditUser2Page/EditUser2Page.js new file mode 100644 index 0000000..767effa --- /dev/null +++ b/web/src/pages/EditUser2Page/EditUser2Page.js @@ -0,0 +1,12 @@ +import MainLayout from 'src/layouts/MainLayout' +import EditUser2Cell from 'src/components/EditUser2Cell' + +const UserPage = ({ userName }) => { + return ( + + + + ) +} + +export default UserPage diff --git a/web/src/pages/UserPage2/UserPage2.js b/web/src/pages/User2Page/User2Page.js similarity index 100% rename from web/src/pages/UserPage2/UserPage2.js rename to web/src/pages/User2Page/User2Page.js From 2b6af01767df5c3a520aca8b1f53598e1944e010 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Thu, 5 Nov 2020 21:06:40 +1100 Subject: [PATCH 08/24] Hook up edit user flow --- api/src/graphql/users.sdl.js | 1 + api/src/services/users/users.js | 7 ++++ .../components/EditUser2Cell/EditUser2Cell.js | 31 +++++++++++++++- .../components/ImageUploader/ImageUploader.js | 3 +- web/src/components/UserProfile/UserProfile.js | 36 ++++++++++++++----- 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/api/src/graphql/users.sdl.js b/api/src/graphql/users.sdl.js index 44fe21a..a72a9a3 100644 --- a/api/src/graphql/users.sdl.js +++ b/api/src/graphql/users.sdl.js @@ -35,6 +35,7 @@ export const schema = gql` type Mutation { createUser(input: CreateUserInput!): User! updateUser(id: String!, input: UpdateUserInput!): User! + updateUserByUserName(userName: String!, input: UpdateUserInput!): User! deleteUser(id: String!): User! } ` diff --git a/api/src/services/users/users.js b/api/src/services/users/users.js index 5e4522b..cde157a 100644 --- a/api/src/services/users/users.js +++ b/api/src/services/users/users.js @@ -29,6 +29,13 @@ export const updateUser = ({ id, input }) => { }) } +export const updateUserByUserName = ({ userName, input }) => { + return db.user.update({ + data: input, + where: { userName }, + }) +} + export const deleteUser = ({ id }) => { return db.user.delete({ where: { id }, diff --git a/web/src/components/EditUser2Cell/EditUser2Cell.js b/web/src/components/EditUser2Cell/EditUser2Cell.js index 07656aa..caba9fa 100644 --- a/web/src/components/EditUser2Cell/EditUser2Cell.js +++ b/web/src/components/EditUser2Cell/EditUser2Cell.js @@ -1,3 +1,5 @@ +import { useMutation, useFlash } from '@redwoodjs/web' +import { navigate, routes } from '@redwoodjs/router' import UserProfile from 'src/components/UserProfile' export const QUERY = gql` @@ -14,6 +16,15 @@ export const QUERY = gql` } ` +const UPDATE_USER_MUTATION = gql` + mutation UpdateUserMutation($userName: String!, $input: UpdateUserInput!) { + updateUserByUserName(userName: $userName, input: $input) { + id + userName + } + } +` + export const Loading = () =>
    Loading...
    export const Empty = () =>
    Empty
    @@ -21,5 +32,23 @@ export const Empty = () =>
    Empty
    export const Failure = ({ error }) =>
    Error: {error.message}
    export const Success = ({ user }) => { - return + const { addMessage } = useFlash() + const [updateUser, { loading, error }] = useMutation(UPDATE_USER_MUTATION, { + onCompleted: ({updateUserByUserName}) => { + navigate(routes.user2({userName: updateUserByUserName.userName})) + addMessage('User updated.', { classes: 'rw-flash-success' }) + }, + }) + + const onSave = (userName, input) => { + updateUser({ variables: { userName, input } }) + } + + return } diff --git a/web/src/components/ImageUploader/ImageUploader.js b/web/src/components/ImageUploader/ImageUploader.js index 819b236..22a1196 100644 --- a/web/src/components/ImageUploader/ImageUploader.js +++ b/web/src/components/ImageUploader/ImageUploader.js @@ -23,7 +23,6 @@ export default function ImageUploader({ onImageUpload, imageUrl, aspectRatio, cl }); async function handleImageUpload() { const croppedFile = await getCroppedImg(imageObj, crop, 'avatar') - console.log(croppedFile) const imageData = new FormData(); imageData.append('upload_preset', CLOUDINARY_UPLOAD_PRESET); imageData.append('file', croppedFile); @@ -54,7 +53,7 @@ export default function ImageUploader({ onImageUpload, imageUrl, aspectRatio, cl
    {cloudinaryId && isEditable && } {isEditable && } {(cloudinaryId || !isEditable) &&
    diff --git a/web/src/components/UserProfile/UserProfile.js b/web/src/components/UserProfile/UserProfile.js index 62bf827..6239111 100644 --- a/web/src/components/UserProfile/UserProfile.js +++ b/web/src/components/UserProfile/UserProfile.js @@ -1,14 +1,21 @@ -import {Fragment} from 'react' +import {useState, useEffect} from 'react' +import { navigate, routes } from '@redwoodjs/router' +import Editor from "rich-markdown-editor"; + import ImageUploader from 'src/components/ImageUploader' import Button from 'src/components/Button' -import Editor from "rich-markdown-editor"; import ProfileTextInput from 'src/components/ProfileTextInput' -const UserProfile = ({user, isEditable}) => { - console.log(isEditable) - const {userName, email} = user - const editableTextFields = {userName, name: email} // TODO add name field to user +const UserProfile = ({user, isEditable, loading, onSave, error}) => { + const [input, setInput] = useState({ + userName: user.userName, + email: user.email, + bio: user.bio, + image: user.image, + }) + const {userName, email} = input + const editableTextFields = {userName, email} // TODO add name field to user return ( <>
    @@ -16,16 +23,23 @@ const UserProfile = ({user, isEditable}) => {
    setInput({ + ...input, + image, + })} aspectRatio={1} isEditable={isEditable} imageUrl={user.image === 'abc' ? '': user.image} />
    - + setInput({ + ...input, + ...textFields, + })} isEditable={isEditable}/> {isEditable ? - : // TODO replace pencil with a save icon - + : // TODO replace pencil with a save icon + }
    @@ -35,6 +49,10 @@ const UserProfile = ({user, isEditable}) => { setInput({ + ...input, + bio: bioFn(), + })} />
    From 07296d0a23d786ac44bdd68a2e10a3355f824540 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Fri, 6 Nov 2020 06:43:16 +1100 Subject: [PATCH 09/24] Replace email with name on user profile --- .../20201105184423-add-name-to-user/README.md | 43 ++++++++++ .../schema.prisma | 80 +++++++++++++++++++ .../steps.json | 12 +++ api/prisma/migrations/migrate.lock | 3 +- api/prisma/schema.prisma | 7 +- api/src/graphql/users.sdl.js | 3 + web/package.json | 1 + .../components/EditUser2Cell/EditUser2Cell.js | 2 +- .../ProfileTextInput/ProfileTextInput.js | 17 ++-- web/src/components/User2Cell/User2Cell.js | 2 +- web/src/components/UserProfile/UserProfile.js | 6 +- yarn.lock | 5 ++ 12 files changed, 163 insertions(+), 18 deletions(-) create mode 100644 api/prisma/migrations/20201105184423-add-name-to-user/README.md create mode 100644 api/prisma/migrations/20201105184423-add-name-to-user/schema.prisma create mode 100644 api/prisma/migrations/20201105184423-add-name-to-user/steps.json diff --git a/api/prisma/migrations/20201105184423-add-name-to-user/README.md b/api/prisma/migrations/20201105184423-add-name-to-user/README.md new file mode 100644 index 0000000..e89ab99 --- /dev/null +++ b/api/prisma/migrations/20201105184423-add-name-to-user/README.md @@ -0,0 +1,43 @@ +# Migration `20201105184423-add-name-to-user` + +This migration has been generated by Kurt Hutten at 11/6/2020, 5:44:24 AM. +You can check out the [state of the schema](./schema.prisma) after the migration. + +## Database Steps + +```sql +ALTER TABLE "User" ADD COLUMN "name" TEXT +``` + +## Changes + +```diff +diff --git schema.prisma schema.prisma +migration 20201101183848-db-init..20201105184423-add-name-to-user +--- datamodel.dml ++++ datamodel.dml +@@ -1,7 +1,7 @@ + datasource DS { + provider = ["sqlite", "postgresql"] +- url = "***" ++ url = "***" + } + generator client { + provider = "prisma-client-js" +@@ -19,11 +19,12 @@ + // JSCAD + // } + model User { +- id String @id @default(uuid()) +- userName String @unique // reffered to as userId in @relations +- email String @unique ++ id String @id @default(uuid()) ++ userName String @unique // reffered to as userId in @relations ++ email String @unique ++ name String? + // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev + // maybe let netlify handle roles for now. + // role String @default("user") +``` + + diff --git a/api/prisma/migrations/20201105184423-add-name-to-user/schema.prisma b/api/prisma/migrations/20201105184423-add-name-to-user/schema.prisma new file mode 100644 index 0000000..e0f3879 --- /dev/null +++ b/api/prisma/migrations/20201105184423-add-name-to-user/schema.prisma @@ -0,0 +1,80 @@ +datasource DS { + provider = ["sqlite", "postgresql"] + url = "***" +} + +generator client { + provider = "prisma-client-js" + binaryTargets = "native" +} + +// sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode +// enum Role { +// USER +// ADMIN +// } + +// enum PartType { +// CASCADESTUDIO +// JSCAD +// } + +model User { + id String @id @default(uuid()) + userName String @unique // reffered to as userId in @relations + email String @unique + name String? + // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev + // maybe let netlify handle roles for now. + // role String @default("user") + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + image String? // url maybe id or file storage service? cloudinary? + bio String? //mark down + Part Part[] + Reaction PartReaction[] + Comment Comment[] +} + +model Part { + id String @id @default(uuid()) + title String + description String? // markdown string + code String? + mainImage String? // link to cloudinary + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + user User @relation(fields: [userId], references: [id]) + userId String + + Comment Comment[] + Reaction PartReaction[] + @@unique([title, userId]) +} + +model PartReaction { + id String @id @default(uuid()) + emote String // an emoji + user User @relation(fields: [userId], references: [id]) + userId String + part Part @relation(fields: [partId], references: [id]) + partId String + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + @@unique([emote, userId, partId]) +} + +model Comment { + id String @id @default(uuid()) + text String // the comment, should I allow mark down? + user User @relation(fields: [userId], references: [id]) + userId String + part Part @relation(fields: [partId], references: [id]) + partId String + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} diff --git a/api/prisma/migrations/20201105184423-add-name-to-user/steps.json b/api/prisma/migrations/20201105184423-add-name-to-user/steps.json new file mode 100644 index 0000000..21ac63d --- /dev/null +++ b/api/prisma/migrations/20201105184423-add-name-to-user/steps.json @@ -0,0 +1,12 @@ +{ + "version": "0.3.14-fixed", + "steps": [ + { + "tag": "CreateField", + "model": "User", + "field": "name", + "type": "String", + "arity": "Optional" + } + ] +} \ No newline at end of file diff --git a/api/prisma/migrations/migrate.lock b/api/prisma/migrations/migrate.lock index 3d49851..0f07957 100644 --- a/api/prisma/migrations/migrate.lock +++ b/api/prisma/migrations/migrate.lock @@ -1,3 +1,4 @@ # Prisma Migrate lockfile v1 -20201101183848-db-init \ No newline at end of file +20201101183848-db-init +20201105184423-add-name-to-user \ No newline at end of file diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index a8ac9dc..c55ce7f 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -20,9 +20,10 @@ generator client { // } model User { - id String @id @default(uuid()) - userName String @unique // reffered to as userId in @relations - email String @unique + id String @id @default(uuid()) + userName String @unique // reffered to as userId in @relations + email String @unique + name String? // role should probably be a list [] and also use enums, neither are supported by sqllight, so we need to set up postgresql in dev // maybe let netlify handle roles for now. // role String @default("user") diff --git a/api/src/graphql/users.sdl.js b/api/src/graphql/users.sdl.js index a72a9a3..743011f 100644 --- a/api/src/graphql/users.sdl.js +++ b/api/src/graphql/users.sdl.js @@ -3,6 +3,7 @@ export const schema = gql` id: String! userName: String! email: String! + name: String createdAt: DateTime! updatedAt: DateTime! image: String @@ -21,6 +22,7 @@ export const schema = gql` input CreateUserInput { userName: String! email: String! + name: String image: String bio: String } @@ -28,6 +30,7 @@ export const schema = gql` input UpdateUserInput { userName: String email: String + name: String image: String bio: String } diff --git a/web/package.json b/web/package.json index a9942bc..e9ac1d7 100644 --- a/web/package.json +++ b/web/package.json @@ -20,6 +20,7 @@ "@redwoodjs/web": "^0.19.2", "cloudinary-react": "^1.6.7", "controlkit": "^0.1.9", + "get-active-classes": "^0.0.11", "golden-layout": "^1.5.9", "jquery": "^3.5.1", "monaco-editor": "^0.20.0", diff --git a/web/src/components/EditUser2Cell/EditUser2Cell.js b/web/src/components/EditUser2Cell/EditUser2Cell.js index caba9fa..147921e 100644 --- a/web/src/components/EditUser2Cell/EditUser2Cell.js +++ b/web/src/components/EditUser2Cell/EditUser2Cell.js @@ -7,7 +7,7 @@ export const QUERY = gql` user: userName(userName: $userName) { id userName - email + name createdAt updatedAt image diff --git a/web/src/components/ProfileTextInput/ProfileTextInput.js b/web/src/components/ProfileTextInput/ProfileTextInput.js index d0b07d5..b8de516 100644 --- a/web/src/components/ProfileTextInput/ProfileTextInput.js +++ b/web/src/components/ProfileTextInput/ProfileTextInput.js @@ -1,25 +1,24 @@ import {Fragment, useState} from 'react' +import { getActiveClasses } from "get-active-classes" const ProfileTextInput = ({fields, isEditable, onChange= () => {}}) => { - const keyValueDisplay = Object.entries(fields) return (
    - {keyValueDisplay.map(([property, value]) => ( + {Object.entries(fields).map(([property, value]) => ( {property}: - { - isEditable ? -
    + +
    onChange({...fields, [property]: target.value})} value={value} type="text" /> -
    : - {value} - } +
    + {value} + ))}
    diff --git a/web/src/components/User2Cell/User2Cell.js b/web/src/components/User2Cell/User2Cell.js index faea1cd..e10d13c 100644 --- a/web/src/components/User2Cell/User2Cell.js +++ b/web/src/components/User2Cell/User2Cell.js @@ -5,7 +5,7 @@ export const QUERY = gql` user: userName(userName: $userName) { id userName - email + name createdAt updatedAt image diff --git a/web/src/components/UserProfile/UserProfile.js b/web/src/components/UserProfile/UserProfile.js index 6239111..ea9c971 100644 --- a/web/src/components/UserProfile/UserProfile.js +++ b/web/src/components/UserProfile/UserProfile.js @@ -10,12 +10,12 @@ import ProfileTextInput from 'src/components/ProfileTextInput' const UserProfile = ({user, isEditable, loading, onSave, error}) => { const [input, setInput] = useState({ userName: user.userName, - email: user.email, + name: user.name, bio: user.bio, image: user.image, }) - const {userName, email} = input - const editableTextFields = {userName, email} // TODO add name field to user + const {userName, name} = input + const editableTextFields = {userName, name} return ( <>
    diff --git a/yarn.lock b/yarn.lock index 9a65f6e..ad5cccd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8313,6 +8313,11 @@ gensync@^1.0.0-beta.1: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== +get-active-classes@^0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/get-active-classes/-/get-active-classes-0.0.11.tgz#1ed78f7470141f9ea6e2c113728b990710316c1e" + integrity sha512-lLPN0fi3ospZ4pKQTVQ+/0K3HmxrSs09yuE9BrahjLUQvA0zYHHH4eBhwR1bhguy3+wNwzg85yWUz8oKQLCnYg== + get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" From c0cd79f48b7855f3079b22d9117944c962b00747 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Fri, 6 Nov 2020 17:27:49 +1100 Subject: [PATCH 10/24] Add mainlayout to not found page --- web/src/pages/NotFoundPage/NotFoundPage.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web/src/pages/NotFoundPage/NotFoundPage.js b/web/src/pages/NotFoundPage/NotFoundPage.js index 92ef916..968f82d 100644 --- a/web/src/pages/NotFoundPage/NotFoundPage.js +++ b/web/src/pages/NotFoundPage/NotFoundPage.js @@ -1,5 +1,7 @@ +import MainLayout from 'src/layouts/MainLayout' + export default () => ( -
    +