Re-init DB and scaffold all models
This commit is contained in:
@@ -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())
|
|
||||||
+}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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())
|
|
||||||
}
|
|
||||||
@@ -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()"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
+}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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()"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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!\""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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!\""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -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())
|
|
||||||
+}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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())
|
|
||||||
}
|
|
||||||
@@ -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()"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
+}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "0.3.14-fixed",
|
|
||||||
"steps": [
|
|
||||||
{
|
|
||||||
"tag": "DeleteField",
|
|
||||||
"model": "User",
|
|
||||||
"field": "userName"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag": "DeleteField",
|
|
||||||
"model": "User",
|
|
||||||
"field": "issuer"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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")
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
158
api/prisma/migrations/20201101183848-db-init/README.md
Normal file
158
api/prisma/migrations/20201101183848-db-init/README.md
Normal file
@@ -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
|
||||||
|
+}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -20,7 +20,8 @@ generator client {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
userName String @id
|
id String @id @default(uuid())
|
||||||
|
userName String @unique // reffered to as userId in @relations
|
||||||
email String @unique
|
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
|
// 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.
|
// maybe let netlify handle roles for now.
|
||||||
@@ -37,28 +38,28 @@ model User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Part {
|
model Part {
|
||||||
id String @unique @default(uuid())
|
id String @id @default(uuid())
|
||||||
title String
|
title String
|
||||||
description String? // markdown string
|
description String? // markdown string
|
||||||
code String?
|
code String?
|
||||||
mainImage String? // link to cloudinary
|
mainImage String? // link to cloudinary
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
author User @relation(fields: [authorUserName], references: [userName])
|
user User @relation(fields: [userId], references: [id])
|
||||||
authorUserName String
|
userId String
|
||||||
|
|
||||||
Comment Comment[]
|
Comment Comment[]
|
||||||
Reaction PartReaction[]
|
Reaction PartReaction[]
|
||||||
@@id([title, authorUserName])
|
@@unique([title, userId])
|
||||||
@@unique([title, authorUserName])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model PartReaction {
|
model PartReaction {
|
||||||
|
id String @id @default(uuid())
|
||||||
emote String // an emoji
|
emote String // an emoji
|
||||||
|
user User @relation(fields: [userId], references: [id])
|
||||||
userId String
|
userId String
|
||||||
user User @relation(fields: [userId], references: [userName])
|
|
||||||
partId String
|
|
||||||
part Part @relation(fields: [partId], references: [id])
|
part Part @relation(fields: [partId], references: [id])
|
||||||
|
partId String
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
@@ -66,10 +67,12 @@ model PartReaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Comment {
|
model Comment {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
text String // the comment, should I allow mark down?
|
text String // the comment, should I allow mark down?
|
||||||
user User @relation(fields: [id], references: [userName])
|
user User @relation(fields: [userId], references: [id])
|
||||||
part Part @relation(fields: [id], references: [id])
|
userId String
|
||||||
|
part Part @relation(fields: [partId], references: [id])
|
||||||
|
partId String
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
@@ -1,6 +1,404 @@
|
|||||||
{
|
{
|
||||||
"version": "0.3.14-fixed",
|
"version": "0.3.14-fixed",
|
||||||
"steps": [
|
"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",
|
"tag": "CreateModel",
|
||||||
"model": "PartReaction"
|
"model": "PartReaction"
|
||||||
@@ -8,14 +406,50 @@
|
|||||||
{
|
{
|
||||||
"tag": "CreateField",
|
"tag": "CreateField",
|
||||||
"model": "PartReaction",
|
"model": "PartReaction",
|
||||||
"field": "emote",
|
"field": "id",
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"arity": "Required"
|
"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",
|
"tag": "CreateField",
|
||||||
"model": "PartReaction",
|
"model": "PartReaction",
|
||||||
"field": "userId",
|
"field": "emote",
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"arity": "Required"
|
"arity": "Required"
|
||||||
},
|
},
|
||||||
@@ -63,12 +497,12 @@
|
|||||||
"directive": "relation"
|
"directive": "relation"
|
||||||
},
|
},
|
||||||
"argument": "references",
|
"argument": "references",
|
||||||
"value": "[userName]"
|
"value": "[id]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "CreateField",
|
"tag": "CreateField",
|
||||||
"model": "PartReaction",
|
"model": "PartReaction",
|
||||||
"field": "partId",
|
"field": "userId",
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"arity": "Required"
|
"arity": "Required"
|
||||||
},
|
},
|
||||||
@@ -118,6 +552,13 @@
|
|||||||
"argument": "references",
|
"argument": "references",
|
||||||
"value": "[id]"
|
"value": "[id]"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"tag": "CreateField",
|
||||||
|
"model": "PartReaction",
|
||||||
|
"field": "partId",
|
||||||
|
"type": "String",
|
||||||
|
"arity": "Required"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"tag": "CreateField",
|
"tag": "CreateField",
|
||||||
"model": "PartReaction",
|
"model": "PartReaction",
|
||||||
@@ -268,7 +709,7 @@
|
|||||||
"directive": "relation"
|
"directive": "relation"
|
||||||
},
|
},
|
||||||
"argument": "fields",
|
"argument": "fields",
|
||||||
"value": "[id]"
|
"value": "[userId]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "CreateArgument",
|
"tag": "CreateArgument",
|
||||||
@@ -282,7 +723,14 @@
|
|||||||
"directive": "relation"
|
"directive": "relation"
|
||||||
},
|
},
|
||||||
"argument": "references",
|
"argument": "references",
|
||||||
"value": "[userName]"
|
"value": "[id]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "CreateField",
|
||||||
|
"model": "Comment",
|
||||||
|
"field": "userId",
|
||||||
|
"type": "String",
|
||||||
|
"arity": "Required"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "CreateField",
|
"tag": "CreateField",
|
||||||
@@ -314,7 +762,7 @@
|
|||||||
"directive": "relation"
|
"directive": "relation"
|
||||||
},
|
},
|
||||||
"argument": "fields",
|
"argument": "fields",
|
||||||
"value": "[id]"
|
"value": "[partId]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "CreateArgument",
|
"tag": "CreateArgument",
|
||||||
@@ -330,6 +778,13 @@
|
|||||||
"argument": "references",
|
"argument": "references",
|
||||||
"value": "[id]"
|
"value": "[id]"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"tag": "CreateField",
|
||||||
|
"model": "Comment",
|
||||||
|
"field": "partId",
|
||||||
|
"type": "String",
|
||||||
|
"arity": "Required"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"tag": "CreateField",
|
"tag": "CreateField",
|
||||||
"model": "Comment",
|
"model": "Comment",
|
||||||
@@ -379,328 +834,6 @@
|
|||||||
},
|
},
|
||||||
"directive": "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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,3 @@
|
|||||||
# Prisma Migrate lockfile v1
|
# Prisma Migrate lockfile v1
|
||||||
|
|
||||||
20201009213512-create-posts
|
20201101183848-db-init
|
||||||
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
|
|
||||||
@@ -20,7 +20,8 @@ generator client {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
userName String @id
|
id String @id @default(uuid())
|
||||||
|
userName String @unique // reffered to as userId in @relations
|
||||||
email String @unique
|
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
|
// 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.
|
// maybe let netlify handle roles for now.
|
||||||
@@ -37,28 +38,28 @@ model User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Part {
|
model Part {
|
||||||
id String @unique @default(uuid())
|
id String @id @default(uuid())
|
||||||
title String
|
title String
|
||||||
description String? // markdown string
|
description String? // markdown string
|
||||||
code String?
|
code String?
|
||||||
mainImage String? // link to cloudinary
|
mainImage String? // link to cloudinary
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
author User @relation(fields: [authorUserName], references: [userName])
|
user User @relation(fields: [userId], references: [id])
|
||||||
authorUserName String
|
userId String
|
||||||
|
|
||||||
Comment Comment[]
|
Comment Comment[]
|
||||||
Reaction PartReaction[]
|
Reaction PartReaction[]
|
||||||
@@id([title, authorUserName])
|
@@unique([title, userId])
|
||||||
@@unique([title, authorUserName])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model PartReaction {
|
model PartReaction {
|
||||||
|
id String @id @default(uuid())
|
||||||
emote String // an emoji
|
emote String // an emoji
|
||||||
|
user User @relation(fields: [userId], references: [id])
|
||||||
userId String
|
userId String
|
||||||
user User @relation(fields: [userId], references: [userName])
|
|
||||||
partId String
|
|
||||||
part Part @relation(fields: [partId], references: [id])
|
part Part @relation(fields: [partId], references: [id])
|
||||||
|
partId String
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
@@ -66,10 +67,12 @@ model PartReaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Comment {
|
model Comment {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
text String // the comment, should I allow mark down?
|
text String // the comment, should I allow mark down?
|
||||||
user User @relation(fields: [id], references: [userName])
|
user User @relation(fields: [userId], references: [id])
|
||||||
part Part @relation(fields: [id], references: [id])
|
userId String
|
||||||
|
part Part @relation(fields: [partId], references: [id])
|
||||||
|
partId String
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|||||||
@@ -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) => {
|
export const handler = async (req, _context) => {
|
||||||
const body = JSON.parse(req.body)
|
const body = JSON.parse(req.body)
|
||||||
@@ -66,7 +66,7 @@ export const handler = async (req, _context) => {
|
|||||||
bio: 'default bio'
|
bio: 'default bio'
|
||||||
// full_name: user.user_metadata.full_name
|
// full_name: user.user_metadata.full_name
|
||||||
}
|
}
|
||||||
await createUserInsecure({input})
|
// await createUserInsecure({input})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
|
|||||||
35
api/src/graphql/comments.sdl.js
Normal file
35
api/src/graphql/comments.sdl.js
Normal file
@@ -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!
|
||||||
|
}
|
||||||
|
`
|
||||||
38
api/src/graphql/partReactions.sdl.js
Normal file
38
api/src/graphql/partReactions.sdl.js
Normal file
@@ -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!
|
||||||
|
}
|
||||||
|
`
|
||||||
42
api/src/graphql/parts.sdl.js
Normal file
42
api/src/graphql/parts.sdl.js
Normal file
@@ -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!
|
||||||
|
}
|
||||||
|
`
|
||||||
39
api/src/graphql/users.sdl.js
Normal file
39
api/src/graphql/users.sdl.js
Normal file
@@ -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!
|
||||||
|
}
|
||||||
|
`
|
||||||
38
api/src/services/comments/comments.js
Normal file
38
api/src/services/comments/comments.js
Normal file
@@ -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(),
|
||||||
|
}
|
||||||
9
api/src/services/comments/comments.test.js
Normal file
9
api/src/services/comments/comments.test.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
import { comments } from './comments'
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('comments', () => {
|
||||||
|
it('returns true', () => {
|
||||||
|
expect(true).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
13
api/src/services/helpers.js
Normal file
13
api/src/services/helpers.js
Normal file
@@ -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
|
||||||
|
}
|
||||||
38
api/src/services/partReactions/partReactions.js
Normal file
38
api/src/services/partReactions/partReactions.js
Normal file
@@ -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(),
|
||||||
|
}
|
||||||
9
api/src/services/partReactions/partReactions.test.js
Normal file
9
api/src/services/partReactions/partReactions.test.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
import { partReactions } from './partReactions'
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('partReactions', () => {
|
||||||
|
it('returns true', () => {
|
||||||
|
expect(true).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
40
api/src/services/parts/parts.js
Normal file
40
api/src/services/parts/parts.js
Normal file
@@ -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(),
|
||||||
|
}
|
||||||
9
api/src/services/parts/parts.test.js
Normal file
9
api/src/services/parts/parts.test.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
import { parts } from './parts'
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('parts', () => {
|
||||||
|
it('returns true', () => {
|
||||||
|
expect(true).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
38
api/src/services/users/users.js
Normal file
38
api/src/services/users/users.js
Normal file
@@ -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(),
|
||||||
|
}
|
||||||
9
api/src/services/users/users.test.js
Normal file
9
api/src/services/users/users.test.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
import { users } from './users'
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('users', () => {
|
||||||
|
it('returns true', () => {
|
||||||
|
expect(true).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -12,8 +12,24 @@ import { Router, Route, Private } from '@redwoodjs/router'
|
|||||||
const Routes = () => {
|
const Routes = () => {
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<Route path="/" page={PartsPage} name="home" />
|
<Route path="/part-reactions/new" page={NewPartReactionPage} name="newPartReaction" />
|
||||||
<Route path="/blah/*" page={PartsPage} name="home" />
|
<Route path="/part-reactions/{id}/edit" page={EditPartReactionPage} name="editPartReaction" />
|
||||||
|
<Route path="/part-reactions/{id}" page={PartReactionPage} name="partReaction" />
|
||||||
|
<Route path="/part-reactions" page={PartReactionsPage} name="partReactions" />
|
||||||
|
<Route path="/parts/new" page={NewPartPage} name="newPart" />
|
||||||
|
<Route path="/parts/{id}/edit" page={EditPartPage} name="editPart" />
|
||||||
|
<Route path="/parts/{id}" page={PartPage} name="part" />
|
||||||
|
<Route path="/parts" page={PartsPage} name="parts" />
|
||||||
|
<Route path="/comments/new" page={NewCommentPage} name="newComment" />
|
||||||
|
<Route path="/comments/{id}/edit" page={EditCommentPage} name="editComment" />
|
||||||
|
<Route path="/comments/{id}" page={CommentPage} name="comment" />
|
||||||
|
<Route path="/comments" page={CommentsPage} name="comments" />
|
||||||
|
<Route path="/users/new" page={NewUserPage} name="newUser" />
|
||||||
|
<Route path="/users/{id}/edit" page={EditUserPage} name="editUser" />
|
||||||
|
<Route path="/users/{id}" page={UserPage} name="user" />
|
||||||
|
<Route path="/users" page={UsersPage} name="users" />
|
||||||
|
<Route path="/" page={HomePage} name="home" />
|
||||||
|
{/* <Route path="/blah/*" page={PartsPage} name="home" /> */}
|
||||||
<Route notfound page={NotFoundPage} />
|
<Route notfound page={NotFoundPage} />
|
||||||
</Router>
|
</Router>
|
||||||
)
|
)
|
||||||
|
|||||||
103
web/src/components/Comment/Comment.js
Normal file
103
web/src/components/Comment/Comment.js
Normal file
@@ -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 (
|
||||||
|
<pre>
|
||||||
|
<code>{JSON.stringify(obj, null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeTag = (datetime) => {
|
||||||
|
return (
|
||||||
|
<time dateTime={datetime} title={datetime}>
|
||||||
|
{new Date(datetime).toUTCString()}
|
||||||
|
</time>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxInputTag = (checked) => {
|
||||||
|
return <input type="checkbox" checked={checked} disabled />
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">
|
||||||
|
Comment {comment.id} Detail
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
<table className="rw-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<td>{comment.id}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Text</th>
|
||||||
|
<td>{comment.text}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>User id</th>
|
||||||
|
<td>{comment.userId}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Part id</th>
|
||||||
|
<td>{comment.partId}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Created at</th>
|
||||||
|
<td>{timeTag(comment.createdAt)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Updated at</th>
|
||||||
|
<td>{timeTag(comment.updatedAt)}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<nav className="rw-button-group">
|
||||||
|
<Link
|
||||||
|
to={routes.editComment({ id: comment.id })}
|
||||||
|
className="rw-button rw-button-blue"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="rw-button rw-button-red"
|
||||||
|
onClick={() => onDeleteClick(comment.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Comment
|
||||||
22
web/src/components/CommentCell/CommentCell.js
Normal file
22
web/src/components/CommentCell/CommentCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
export const Empty = () => <div>Comment not found</div>
|
||||||
|
|
||||||
|
export const Success = ({ comment }) => {
|
||||||
|
return <Comment comment={comment} />
|
||||||
|
}
|
||||||
83
web/src/components/CommentForm/CommentForm.js
Normal file
83
web/src/components/CommentForm/CommentForm.js
Normal file
@@ -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 (
|
||||||
|
<div className="rw-form-wrapper">
|
||||||
|
<Form onSubmit={onSubmit} error={props.error}>
|
||||||
|
<FormError
|
||||||
|
error={props.error}
|
||||||
|
wrapperClassName="rw-form-error-wrapper"
|
||||||
|
titleClassName="rw-form-error-title"
|
||||||
|
listClassName="rw-form-error-list"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="text"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Text
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="text"
|
||||||
|
defaultValue={props.comment?.text}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="text" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="userId"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
User id
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="userId"
|
||||||
|
defaultValue={props.comment?.userId}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="userId" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="partId"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Part id
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="partId"
|
||||||
|
defaultValue={props.comment?.partId}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="partId" className="rw-field-error" />
|
||||||
|
|
||||||
|
<div className="rw-button-group">
|
||||||
|
<Submit disabled={props.loading} className="rw-button rw-button-blue">
|
||||||
|
Save
|
||||||
|
</Submit>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CommentForm
|
||||||
109
web/src/components/Comments/Comments.js
Normal file
109
web/src/components/Comments/Comments.js
Normal file
@@ -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 (
|
||||||
|
<time dateTime={datetime} title={datetime}>
|
||||||
|
{new Date(datetime).toUTCString()}
|
||||||
|
</time>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxInputTag = (checked) => {
|
||||||
|
return <input type="checkbox" checked={checked} disabled />
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="rw-segment rw-table-wrapper-responsive">
|
||||||
|
<table className="rw-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Text</th>
|
||||||
|
<th>User id</th>
|
||||||
|
<th>Part id</th>
|
||||||
|
<th>Created at</th>
|
||||||
|
<th>Updated at</th>
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{comments.map((comment) => (
|
||||||
|
<tr key={comment.id}>
|
||||||
|
<td>{truncate(comment.id)}</td>
|
||||||
|
<td>{truncate(comment.text)}</td>
|
||||||
|
<td>{truncate(comment.userId)}</td>
|
||||||
|
<td>{truncate(comment.partId)}</td>
|
||||||
|
<td>{timeTag(comment.createdAt)}</td>
|
||||||
|
<td>{timeTag(comment.updatedAt)}</td>
|
||||||
|
<td>
|
||||||
|
<nav className="rw-table-actions">
|
||||||
|
<Link
|
||||||
|
to={routes.comment({ id: comment.id })}
|
||||||
|
title={'Show comment ' + comment.id + ' detail'}
|
||||||
|
className="rw-button rw-button-small"
|
||||||
|
>
|
||||||
|
Show
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
to={routes.editComment({ id: comment.id })}
|
||||||
|
title={'Edit comment ' + comment.id}
|
||||||
|
className="rw-button rw-button-small rw-button-blue"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
title={'Delete comment ' + comment.id}
|
||||||
|
className="rw-button rw-button-small rw-button-red"
|
||||||
|
onClick={() => onDeleteClick(comment.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CommentsList
|
||||||
33
web/src/components/CommentsCell/CommentsCell.js
Normal file
33
web/src/components/CommentsCell/CommentsCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
export const Empty = () => {
|
||||||
|
return (
|
||||||
|
<div className="rw-text-center">
|
||||||
|
{'No comments yet. '}
|
||||||
|
<Link to={routes.newComment()} className="rw-link">
|
||||||
|
{'Create one?'}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Success = ({ comments }) => {
|
||||||
|
return <Comments comments={comments} />
|
||||||
|
}
|
||||||
60
web/src/components/EditCommentCell/EditCommentCell.js
Normal file
60
web/src/components/EditCommentCell/EditCommentCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">
|
||||||
|
Edit Comment {comment.id}
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
<div className="rw-segment-main">
|
||||||
|
<CommentForm
|
||||||
|
comment={comment}
|
||||||
|
onSave={onSave}
|
||||||
|
error={error}
|
||||||
|
loading={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
52
web/src/components/EditPartCell/EditPartCell.js
Normal file
52
web/src/components/EditPartCell/EditPartCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">Edit Part {part.id}</h2>
|
||||||
|
</header>
|
||||||
|
<div className="rw-segment-main">
|
||||||
|
<PartForm part={part} onSave={onSave} error={error} loading={loading} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">
|
||||||
|
Edit PartReaction {partReaction.id}
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
<div className="rw-segment-main">
|
||||||
|
<PartReactionForm
|
||||||
|
partReaction={partReaction}
|
||||||
|
onSave={onSave}
|
||||||
|
error={error}
|
||||||
|
loading={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
51
web/src/components/EditUserCell/EditUserCell.js
Normal file
51
web/src/components/EditUserCell/EditUserCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">Edit User {user.id}</h2>
|
||||||
|
</header>
|
||||||
|
<div className="rw-segment-main">
|
||||||
|
<UserForm user={user} onSave={onSave} error={error} loading={loading} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMutation, useFlash } from '@redwoodjs/web'
|
import { useMutation, useFlash } from '@redwoodjs/web'
|
||||||
import { navigate, routes } from '@redwoodjs/router'
|
import { navigate, routes } from '@redwoodjs/router'
|
||||||
import Part from 'src/components/Part'
|
// import Part from 'src/components/Part'
|
||||||
|
|
||||||
export const QUERY = gql`
|
export const QUERY = gql`
|
||||||
query FIND_PART_BY_ID($id: Int!) {
|
query FIND_PART_BY_ID($id: Int!) {
|
||||||
@@ -42,5 +42,6 @@ export const Success = ({ part }) => {
|
|||||||
console.log(id, input, 'wowow')
|
console.log(id, input, 'wowow')
|
||||||
updatePart({ variables: { id, input } })
|
updatePart({ variables: { id, input } })
|
||||||
}
|
}
|
||||||
return <Part part={{...part, code: part.code}} saveCode={saveCode} loading={loading} error={error} />
|
return <div>TODO part</div>
|
||||||
|
// return <Part part={{...part, code: part.code}} saveCode={saveCode} loading={loading} error={error} />
|
||||||
}
|
}
|
||||||
|
|||||||
41
web/src/components/NewComment/NewComment.js
Normal file
41
web/src/components/NewComment/NewComment.js
Normal file
@@ -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 (
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">New Comment</h2>
|
||||||
|
</header>
|
||||||
|
<div className="rw-segment-main">
|
||||||
|
<CommentForm onSave={onSave} loading={loading} error={error} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewComment
|
||||||
38
web/src/components/NewPart/NewPart.js
Normal file
38
web/src/components/NewPart/NewPart.js
Normal file
@@ -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 (
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">New Part</h2>
|
||||||
|
</header>
|
||||||
|
<div className="rw-segment-main">
|
||||||
|
<PartForm onSave={onSave} loading={loading} error={error} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewPart
|
||||||
41
web/src/components/NewPartReaction/NewPartReaction.js
Normal file
41
web/src/components/NewPartReaction/NewPartReaction.js
Normal file
@@ -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 (
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">New PartReaction</h2>
|
||||||
|
</header>
|
||||||
|
<div className="rw-segment-main">
|
||||||
|
<PartReactionForm onSave={onSave} loading={loading} error={error} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewPartReaction
|
||||||
38
web/src/components/NewUser/NewUser.js
Normal file
38
web/src/components/NewUser/NewUser.js
Normal file
@@ -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 (
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">New User</h2>
|
||||||
|
</header>
|
||||||
|
<div className="rw-segment-main">
|
||||||
|
<UserForm onSave={onSave} loading={loading} error={error} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewUser
|
||||||
111
web/src/components/Part/Part.js
Normal file
111
web/src/components/Part/Part.js
Normal file
@@ -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 (
|
||||||
|
<pre>
|
||||||
|
<code>{JSON.stringify(obj, null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeTag = (datetime) => {
|
||||||
|
return (
|
||||||
|
<time dateTime={datetime} title={datetime}>
|
||||||
|
{new Date(datetime).toUTCString()}
|
||||||
|
</time>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxInputTag = (checked) => {
|
||||||
|
return <input type="checkbox" checked={checked} disabled />
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">
|
||||||
|
Part {part.id} Detail
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
<table className="rw-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<td>{part.id}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Title</th>
|
||||||
|
<td>{part.title}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Description</th>
|
||||||
|
<td>{part.description}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Code</th>
|
||||||
|
<td>{part.code}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Main image</th>
|
||||||
|
<td>{part.mainImage}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Created at</th>
|
||||||
|
<td>{timeTag(part.createdAt)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Updated at</th>
|
||||||
|
<td>{timeTag(part.updatedAt)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>User id</th>
|
||||||
|
<td>{part.userId}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<nav className="rw-button-group">
|
||||||
|
<Link
|
||||||
|
to={routes.editPart({ id: part.id })}
|
||||||
|
className="rw-button rw-button-blue"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="rw-button rw-button-red"
|
||||||
|
onClick={() => onDeleteClick(part.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Part
|
||||||
24
web/src/components/PartCell/PartCell.js
Normal file
24
web/src/components/PartCell/PartCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
export const Empty = () => <div>Part not found</div>
|
||||||
|
|
||||||
|
export const Success = ({ part }) => {
|
||||||
|
return <Part part={part} />
|
||||||
|
}
|
||||||
@@ -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 (
|
|
||||||
<div className="m-8">
|
|
||||||
<div className="w-full relative" {...getRootProps()}>
|
|
||||||
{cloudinaryId && <button className="absolute z-10 w-full inset-0 bg-indigo-900 opacity-50 flex justify-center items-center">
|
|
||||||
<Svg name="pencil" strokeWidth={2} className="text-gray-300 h-48 w-48" />
|
|
||||||
</button>}
|
|
||||||
<input {...getInputProps()} />
|
|
||||||
{cloudinaryId && <div className="relative">
|
|
||||||
<CloudinaryImage
|
|
||||||
className="object-cover w-full rounded shadow"
|
|
||||||
cloudName="irevdev"
|
|
||||||
publicId={cloudinaryId}
|
|
||||||
width="600"
|
|
||||||
crop="scale"
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
{!cloudinaryId && <button className="absolute inset-0"></button>}
|
|
||||||
{!cloudinaryId && <div className="mt-3 text-indigo-500 border-dashed border border-indigo-500 py-8 text-center rounded-lg w-full">
|
|
||||||
Drop files here ...
|
|
||||||
or <span className="group flex w-full items-center justify-center py-4">
|
|
||||||
<span className="bg-indigo-500 shadow rounded text-gray-200 cursor-pointer p-2 hover:shadow-lg transform hover:-translate-y-1 transition-all duration-150">upload</span>
|
|
||||||
</span>
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
<Dialog
|
|
||||||
open={isModalOpen}
|
|
||||||
onClose={() => setIsModalOpen(false)}
|
|
||||||
>
|
|
||||||
<div className="p-4">
|
|
||||||
<ReactCrop src={file} crop={crop} onImageLoaded={(image) => setImageObj(image)} onChange={newCrop => setCrop(newCrop)} />
|
|
||||||
<Button onClick={handleImageUpload} variant="outlined">Upload</Button>
|
|
||||||
</div>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
115
web/src/components/PartForm/PartForm.js
Normal file
115
web/src/components/PartForm/PartForm.js
Normal file
@@ -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 (
|
||||||
|
<div className="rw-form-wrapper">
|
||||||
|
<Form onSubmit={onSubmit} error={props.error}>
|
||||||
|
<FormError
|
||||||
|
error={props.error}
|
||||||
|
wrapperClassName="rw-form-error-wrapper"
|
||||||
|
titleClassName="rw-form-error-title"
|
||||||
|
listClassName="rw-form-error-list"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="title"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Title
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="title"
|
||||||
|
defaultValue={props.part?.title}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="title" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="description"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Description
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="description"
|
||||||
|
defaultValue={props.part?.description}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="description" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="code"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Code
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="code"
|
||||||
|
defaultValue={props.part?.code}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="code" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="mainImage"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Main image
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="mainImage"
|
||||||
|
defaultValue={props.part?.mainImage}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="mainImage" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="userId"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
User id
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="userId"
|
||||||
|
defaultValue={props.part?.userId}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="userId" className="rw-field-error" />
|
||||||
|
|
||||||
|
<div className="rw-button-group">
|
||||||
|
<Submit disabled={props.loading} className="rw-button rw-button-blue">
|
||||||
|
Save
|
||||||
|
</Submit>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartForm
|
||||||
103
web/src/components/PartReaction/PartReaction.js
Normal file
103
web/src/components/PartReaction/PartReaction.js
Normal file
@@ -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 (
|
||||||
|
<pre>
|
||||||
|
<code>{JSON.stringify(obj, null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeTag = (datetime) => {
|
||||||
|
return (
|
||||||
|
<time dateTime={datetime} title={datetime}>
|
||||||
|
{new Date(datetime).toUTCString()}
|
||||||
|
</time>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxInputTag = (checked) => {
|
||||||
|
return <input type="checkbox" checked={checked} disabled />
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">
|
||||||
|
PartReaction {partReaction.id} Detail
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
<table className="rw-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<td>{partReaction.id}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Emote</th>
|
||||||
|
<td>{partReaction.emote}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>User id</th>
|
||||||
|
<td>{partReaction.userId}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Part id</th>
|
||||||
|
<td>{partReaction.partId}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Created at</th>
|
||||||
|
<td>{timeTag(partReaction.createdAt)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Updated at</th>
|
||||||
|
<td>{timeTag(partReaction.updatedAt)}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<nav className="rw-button-group">
|
||||||
|
<Link
|
||||||
|
to={routes.editPartReaction({ id: partReaction.id })}
|
||||||
|
className="rw-button rw-button-blue"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="rw-button rw-button-red"
|
||||||
|
onClick={() => onDeleteClick(partReaction.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartReaction
|
||||||
22
web/src/components/PartReactionCell/PartReactionCell.js
Normal file
22
web/src/components/PartReactionCell/PartReactionCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
export const Empty = () => <div>PartReaction not found</div>
|
||||||
|
|
||||||
|
export const Success = ({ partReaction }) => {
|
||||||
|
return <PartReaction partReaction={partReaction} />
|
||||||
|
}
|
||||||
83
web/src/components/PartReactionForm/PartReactionForm.js
Normal file
83
web/src/components/PartReactionForm/PartReactionForm.js
Normal file
@@ -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 (
|
||||||
|
<div className="rw-form-wrapper">
|
||||||
|
<Form onSubmit={onSubmit} error={props.error}>
|
||||||
|
<FormError
|
||||||
|
error={props.error}
|
||||||
|
wrapperClassName="rw-form-error-wrapper"
|
||||||
|
titleClassName="rw-form-error-title"
|
||||||
|
listClassName="rw-form-error-list"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="emote"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Emote
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="emote"
|
||||||
|
defaultValue={props.partReaction?.emote}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="emote" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="userId"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
User id
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="userId"
|
||||||
|
defaultValue={props.partReaction?.userId}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="userId" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="partId"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Part id
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="partId"
|
||||||
|
defaultValue={props.partReaction?.partId}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="partId" className="rw-field-error" />
|
||||||
|
|
||||||
|
<div className="rw-button-group">
|
||||||
|
<Submit disabled={props.loading} className="rw-button rw-button-blue">
|
||||||
|
Save
|
||||||
|
</Submit>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartReactionForm
|
||||||
112
web/src/components/PartReactions/PartReactions.js
Normal file
112
web/src/components/PartReactions/PartReactions.js
Normal file
@@ -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 (
|
||||||
|
<time dateTime={datetime} title={datetime}>
|
||||||
|
{new Date(datetime).toUTCString()}
|
||||||
|
</time>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxInputTag = (checked) => {
|
||||||
|
return <input type="checkbox" checked={checked} disabled />
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="rw-segment rw-table-wrapper-responsive">
|
||||||
|
<table className="rw-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Emote</th>
|
||||||
|
<th>User id</th>
|
||||||
|
<th>Part id</th>
|
||||||
|
<th>Created at</th>
|
||||||
|
<th>Updated at</th>
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{partReactions.map((partReaction) => (
|
||||||
|
<tr key={partReaction.id}>
|
||||||
|
<td>{truncate(partReaction.id)}</td>
|
||||||
|
<td>{truncate(partReaction.emote)}</td>
|
||||||
|
<td>{truncate(partReaction.userId)}</td>
|
||||||
|
<td>{truncate(partReaction.partId)}</td>
|
||||||
|
<td>{timeTag(partReaction.createdAt)}</td>
|
||||||
|
<td>{timeTag(partReaction.updatedAt)}</td>
|
||||||
|
<td>
|
||||||
|
<nav className="rw-table-actions">
|
||||||
|
<Link
|
||||||
|
to={routes.partReaction({ id: partReaction.id })}
|
||||||
|
title={'Show partReaction ' + partReaction.id + ' detail'}
|
||||||
|
className="rw-button rw-button-small"
|
||||||
|
>
|
||||||
|
Show
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
to={routes.editPartReaction({ id: partReaction.id })}
|
||||||
|
title={'Edit partReaction ' + partReaction.id}
|
||||||
|
className="rw-button rw-button-small rw-button-blue"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
title={'Delete partReaction ' + partReaction.id}
|
||||||
|
className="rw-button rw-button-small rw-button-red"
|
||||||
|
onClick={() => onDeleteClick(partReaction.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartReactionsList
|
||||||
33
web/src/components/PartReactionsCell/PartReactionsCell.js
Normal file
33
web/src/components/PartReactionsCell/PartReactionsCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
export const Empty = () => {
|
||||||
|
return (
|
||||||
|
<div className="rw-text-center">
|
||||||
|
{'No partReactions yet. '}
|
||||||
|
<Link to={routes.newPartReaction()} className="rw-link">
|
||||||
|
{'Create one?'}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Success = ({ partReactions }) => {
|
||||||
|
return <PartReactions partReactions={partReactions} />
|
||||||
|
}
|
||||||
113
web/src/components/Parts/Parts.js
Normal file
113
web/src/components/Parts/Parts.js
Normal file
@@ -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 (
|
||||||
|
<time dateTime={datetime} title={datetime}>
|
||||||
|
{new Date(datetime).toUTCString()}
|
||||||
|
</time>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxInputTag = (checked) => {
|
||||||
|
return <input type="checkbox" checked={checked} disabled />
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="rw-segment rw-table-wrapper-responsive">
|
||||||
|
<table className="rw-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Code</th>
|
||||||
|
<th>Main image</th>
|
||||||
|
<th>Created at</th>
|
||||||
|
<th>Updated at</th>
|
||||||
|
<th>User id</th>
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{parts.map((part) => (
|
||||||
|
<tr key={part.id}>
|
||||||
|
<td>{truncate(part.id)}</td>
|
||||||
|
<td>{truncate(part.title)}</td>
|
||||||
|
<td>{truncate(part.description)}</td>
|
||||||
|
<td>{truncate(part.code)}</td>
|
||||||
|
<td>{truncate(part.mainImage)}</td>
|
||||||
|
<td>{timeTag(part.createdAt)}</td>
|
||||||
|
<td>{timeTag(part.updatedAt)}</td>
|
||||||
|
<td>{truncate(part.userId)}</td>
|
||||||
|
<td>
|
||||||
|
<nav className="rw-table-actions">
|
||||||
|
<Link
|
||||||
|
to={routes.part({ id: part.id })}
|
||||||
|
title={'Show part ' + part.id + ' detail'}
|
||||||
|
className="rw-button rw-button-small"
|
||||||
|
>
|
||||||
|
Show
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
to={routes.editPart({ id: part.id })}
|
||||||
|
title={'Edit part ' + part.id}
|
||||||
|
className="rw-button rw-button-small rw-button-blue"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
title={'Delete part ' + part.id}
|
||||||
|
className="rw-button rw-button-small rw-button-red"
|
||||||
|
onClick={() => onDeleteClick(part.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartsList
|
||||||
35
web/src/components/PartsCell/PartsCell.js
Normal file
35
web/src/components/PartsCell/PartsCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
export const Empty = () => {
|
||||||
|
return (
|
||||||
|
<div className="rw-text-center">
|
||||||
|
{'No parts yet. '}
|
||||||
|
<Link to={routes.newPart()} className="rw-link">
|
||||||
|
{'Create one?'}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Success = ({ parts }) => {
|
||||||
|
return <Parts parts={parts} />
|
||||||
|
}
|
||||||
107
web/src/components/User/User.js
Normal file
107
web/src/components/User/User.js
Normal file
@@ -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 (
|
||||||
|
<pre>
|
||||||
|
<code>{JSON.stringify(obj, null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeTag = (datetime) => {
|
||||||
|
return (
|
||||||
|
<time dateTime={datetime} title={datetime}>
|
||||||
|
{new Date(datetime).toUTCString()}
|
||||||
|
</time>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxInputTag = (checked) => {
|
||||||
|
return <input type="checkbox" checked={checked} disabled />
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<div className="rw-segment">
|
||||||
|
<header className="rw-segment-header">
|
||||||
|
<h2 className="rw-heading rw-heading-secondary">
|
||||||
|
User {user.id} Detail
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
<table className="rw-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<td>{user.id}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>User name</th>
|
||||||
|
<td>{user.userName}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Email</th>
|
||||||
|
<td>{user.email}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Created at</th>
|
||||||
|
<td>{timeTag(user.createdAt)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Updated at</th>
|
||||||
|
<td>{timeTag(user.updatedAt)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Image</th>
|
||||||
|
<td>{user.image}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Bio</th>
|
||||||
|
<td>{user.bio}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<nav className="rw-button-group">
|
||||||
|
<Link
|
||||||
|
to={routes.editUser({ id: user.id })}
|
||||||
|
className="rw-button rw-button-blue"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="rw-button rw-button-red"
|
||||||
|
onClick={() => onDeleteClick(user.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default User
|
||||||
23
web/src/components/UserCell/UserCell.js
Normal file
23
web/src/components/UserCell/UserCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
export const Empty = () => <div>User not found</div>
|
||||||
|
|
||||||
|
export const Success = ({ user }) => {
|
||||||
|
return <User user={user} />
|
||||||
|
}
|
||||||
99
web/src/components/UserForm/UserForm.js
Normal file
99
web/src/components/UserForm/UserForm.js
Normal file
@@ -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 (
|
||||||
|
<div className="rw-form-wrapper">
|
||||||
|
<Form onSubmit={onSubmit} error={props.error}>
|
||||||
|
<FormError
|
||||||
|
error={props.error}
|
||||||
|
wrapperClassName="rw-form-error-wrapper"
|
||||||
|
titleClassName="rw-form-error-title"
|
||||||
|
listClassName="rw-form-error-list"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="userName"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
User name
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="userName"
|
||||||
|
defaultValue={props.user?.userName}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="userName" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="email"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Email
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="email"
|
||||||
|
defaultValue={props.user?.email}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="email" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="image"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Image
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="image"
|
||||||
|
defaultValue={props.user?.image}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="image" className="rw-field-error" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
name="bio"
|
||||||
|
className="rw-label"
|
||||||
|
errorClassName="rw-label rw-label-error"
|
||||||
|
>
|
||||||
|
Bio
|
||||||
|
</Label>
|
||||||
|
<TextField
|
||||||
|
name="bio"
|
||||||
|
defaultValue={props.user?.bio}
|
||||||
|
className="rw-input"
|
||||||
|
errorClassName="rw-input rw-input-error"
|
||||||
|
validation={{ required: true }}
|
||||||
|
/>
|
||||||
|
<FieldError name="bio" className="rw-field-error" />
|
||||||
|
|
||||||
|
<div className="rw-button-group">
|
||||||
|
<Submit disabled={props.loading} className="rw-button rw-button-blue">
|
||||||
|
Save
|
||||||
|
</Submit>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserForm
|
||||||
111
web/src/components/Users/Users.js
Normal file
111
web/src/components/Users/Users.js
Normal file
@@ -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 (
|
||||||
|
<time dateTime={datetime} title={datetime}>
|
||||||
|
{new Date(datetime).toUTCString()}
|
||||||
|
</time>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxInputTag = (checked) => {
|
||||||
|
return <input type="checkbox" checked={checked} disabled />
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="rw-segment rw-table-wrapper-responsive">
|
||||||
|
<table className="rw-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>User name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Created at</th>
|
||||||
|
<th>Updated at</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Bio</th>
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{users.map((user) => (
|
||||||
|
<tr key={user.id}>
|
||||||
|
<td>{truncate(user.id)}</td>
|
||||||
|
<td>{truncate(user.userName)}</td>
|
||||||
|
<td>{truncate(user.email)}</td>
|
||||||
|
<td>{timeTag(user.createdAt)}</td>
|
||||||
|
<td>{timeTag(user.updatedAt)}</td>
|
||||||
|
<td>{truncate(user.image)}</td>
|
||||||
|
<td>{truncate(user.bio)}</td>
|
||||||
|
<td>
|
||||||
|
<nav className="rw-table-actions">
|
||||||
|
<Link
|
||||||
|
to={routes.user({ id: user.id })}
|
||||||
|
title={'Show user ' + user.id + ' detail'}
|
||||||
|
className="rw-button rw-button-small"
|
||||||
|
>
|
||||||
|
Show
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
to={routes.editUser({ id: user.id })}
|
||||||
|
title={'Edit user ' + user.id}
|
||||||
|
className="rw-button rw-button-small rw-button-blue"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
title={'Delete user ' + user.id}
|
||||||
|
className="rw-button rw-button-small rw-button-red"
|
||||||
|
onClick={() => onDeleteClick(user.id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UsersList
|
||||||
34
web/src/components/UsersCell/UsersCell.js
Normal file
34
web/src/components/UsersCell/UsersCell.js
Normal file
@@ -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 = () => <div>Loading...</div>
|
||||||
|
|
||||||
|
export const Empty = () => {
|
||||||
|
return (
|
||||||
|
<div className="rw-text-center">
|
||||||
|
{'No users yet. '}
|
||||||
|
<Link to={routes.newUser()} className="rw-link">
|
||||||
|
{'Create one?'}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Success = ({ users }) => {
|
||||||
|
return <Users users={users} />
|
||||||
|
}
|
||||||
23
web/src/layouts/CommentsLayout/CommentsLayout.js
Normal file
23
web/src/layouts/CommentsLayout/CommentsLayout.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { Link, routes } from '@redwoodjs/router'
|
||||||
|
import { Flash } from '@redwoodjs/web'
|
||||||
|
|
||||||
|
const CommentsLayout = (props) => {
|
||||||
|
return (
|
||||||
|
<div className="rw-scaffold">
|
||||||
|
<Flash timeout={1000} />
|
||||||
|
<header className="rw-header">
|
||||||
|
<h1 className="rw-heading rw-heading-primary">
|
||||||
|
<Link to={routes.comments()} className="rw-link">
|
||||||
|
Comments
|
||||||
|
</Link>
|
||||||
|
</h1>
|
||||||
|
<Link to={routes.newComment()} className="rw-button rw-button-green">
|
||||||
|
<div className="rw-button-icon">+</div> New Comment
|
||||||
|
</Link>
|
||||||
|
</header>
|
||||||
|
<main className="rw-main">{props.children}</main>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CommentsLayout
|
||||||
@@ -18,7 +18,7 @@ const MainLayout = ({ children }) => {
|
|||||||
<Link to={routes.home()}>
|
<Link to={routes.home()}>
|
||||||
<Tooltip title="We need a logo!" >
|
<Tooltip title="We need a logo!" >
|
||||||
|
|
||||||
<img src={logo} style={{marginLeft : '50px'}}/>
|
<img src={logo} style={{marginLeft : '50px'}}/>
|
||||||
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -35,9 +35,9 @@ const MainLayout = ({ children }) => {
|
|||||||
</ul>
|
</ul>
|
||||||
<ul className="flex items-center">
|
<ul className="flex items-center">
|
||||||
<li className="mr-8 h-10 w-10 rounded-full border-2 border-indigo-300 flex items-center justify-center">
|
<li className="mr-8 h-10 w-10 rounded-full border-2 border-indigo-300 flex items-center justify-center">
|
||||||
<Link to={routes.newPart()}>
|
{/* <Link to={routes.newPart()}> */}
|
||||||
<Svg name="plus" className="text-indigo-300" />
|
<Svg name="plus" className="text-indigo-300" />
|
||||||
</Link>
|
{/* </Link> */}
|
||||||
</li>
|
</li>
|
||||||
{
|
{
|
||||||
isAuthenticated ?
|
isAuthenticated ?
|
||||||
|
|||||||
26
web/src/layouts/PartReactionsLayout/PartReactionsLayout.js
Normal file
26
web/src/layouts/PartReactionsLayout/PartReactionsLayout.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Link, routes } from '@redwoodjs/router'
|
||||||
|
import { Flash } from '@redwoodjs/web'
|
||||||
|
|
||||||
|
const PartReactionsLayout = (props) => {
|
||||||
|
return (
|
||||||
|
<div className="rw-scaffold">
|
||||||
|
<Flash timeout={1000} />
|
||||||
|
<header className="rw-header">
|
||||||
|
<h1 className="rw-heading rw-heading-primary">
|
||||||
|
<Link to={routes.partReactions()} className="rw-link">
|
||||||
|
PartReactions
|
||||||
|
</Link>
|
||||||
|
</h1>
|
||||||
|
<Link
|
||||||
|
to={routes.newPartReaction()}
|
||||||
|
className="rw-button rw-button-green"
|
||||||
|
>
|
||||||
|
<div className="rw-button-icon">+</div> New PartReaction
|
||||||
|
</Link>
|
||||||
|
</header>
|
||||||
|
<main className="rw-main">{props.children}</main>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartReactionsLayout
|
||||||
23
web/src/layouts/PartsLayout/PartsLayout.js
Normal file
23
web/src/layouts/PartsLayout/PartsLayout.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { Link, routes } from '@redwoodjs/router'
|
||||||
|
import { Flash } from '@redwoodjs/web'
|
||||||
|
|
||||||
|
const PartsLayout = (props) => {
|
||||||
|
return (
|
||||||
|
<div className="rw-scaffold">
|
||||||
|
<Flash timeout={1000} />
|
||||||
|
<header className="rw-header">
|
||||||
|
<h1 className="rw-heading rw-heading-primary">
|
||||||
|
<Link to={routes.parts()} className="rw-link">
|
||||||
|
Parts
|
||||||
|
</Link>
|
||||||
|
</h1>
|
||||||
|
<Link to={routes.newPart()} className="rw-button rw-button-green">
|
||||||
|
<div className="rw-button-icon">+</div> New Part
|
||||||
|
</Link>
|
||||||
|
</header>
|
||||||
|
<main className="rw-main">{props.children}</main>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartsLayout
|
||||||
23
web/src/layouts/UsersLayout/UsersLayout.js
Normal file
23
web/src/layouts/UsersLayout/UsersLayout.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { Link, routes } from '@redwoodjs/router'
|
||||||
|
import { Flash } from '@redwoodjs/web'
|
||||||
|
|
||||||
|
const UsersLayout = (props) => {
|
||||||
|
return (
|
||||||
|
<div className="rw-scaffold">
|
||||||
|
<Flash timeout={1000} />
|
||||||
|
<header className="rw-header">
|
||||||
|
<h1 className="rw-heading rw-heading-primary">
|
||||||
|
<Link to={routes.users()} className="rw-link">
|
||||||
|
Users
|
||||||
|
</Link>
|
||||||
|
</h1>
|
||||||
|
<Link to={routes.newUser()} className="rw-button rw-button-green">
|
||||||
|
<div className="rw-button-icon">+</div> New User
|
||||||
|
</Link>
|
||||||
|
</header>
|
||||||
|
<main className="rw-main">{props.children}</main>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UsersLayout
|
||||||
12
web/src/pages/CommentPage/CommentPage.js
Normal file
12
web/src/pages/CommentPage/CommentPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import CommentsLayout from 'src/layouts/CommentsLayout'
|
||||||
|
import CommentCell from 'src/components/CommentCell'
|
||||||
|
|
||||||
|
const CommentPage = ({ id }) => {
|
||||||
|
return (
|
||||||
|
<CommentsLayout>
|
||||||
|
<CommentCell id={id} />
|
||||||
|
</CommentsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CommentPage
|
||||||
12
web/src/pages/CommentsPage/CommentsPage.js
Normal file
12
web/src/pages/CommentsPage/CommentsPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import CommentsLayout from 'src/layouts/CommentsLayout'
|
||||||
|
import CommentsCell from 'src/components/CommentsCell'
|
||||||
|
|
||||||
|
const CommentsPage = () => {
|
||||||
|
return (
|
||||||
|
<CommentsLayout>
|
||||||
|
<CommentsCell />
|
||||||
|
</CommentsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CommentsPage
|
||||||
12
web/src/pages/EditCommentPage/EditCommentPage.js
Normal file
12
web/src/pages/EditCommentPage/EditCommentPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import CommentsLayout from 'src/layouts/CommentsLayout'
|
||||||
|
import EditCommentCell from 'src/components/EditCommentCell'
|
||||||
|
|
||||||
|
const EditCommentPage = ({ id }) => {
|
||||||
|
return (
|
||||||
|
<CommentsLayout>
|
||||||
|
<EditCommentCell id={id} />
|
||||||
|
</CommentsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditCommentPage
|
||||||
12
web/src/pages/EditPartPage/EditPartPage.js
Normal file
12
web/src/pages/EditPartPage/EditPartPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import PartsLayout from 'src/layouts/PartsLayout'
|
||||||
|
import EditPartCell from 'src/components/EditPartCell'
|
||||||
|
|
||||||
|
const EditPartPage = ({ id }) => {
|
||||||
|
return (
|
||||||
|
<PartsLayout>
|
||||||
|
<EditPartCell id={id} />
|
||||||
|
</PartsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditPartPage
|
||||||
12
web/src/pages/EditPartReactionPage/EditPartReactionPage.js
Normal file
12
web/src/pages/EditPartReactionPage/EditPartReactionPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import PartReactionsLayout from 'src/layouts/PartReactionsLayout'
|
||||||
|
import EditPartReactionCell from 'src/components/EditPartReactionCell'
|
||||||
|
|
||||||
|
const EditPartReactionPage = ({ id }) => {
|
||||||
|
return (
|
||||||
|
<PartReactionsLayout>
|
||||||
|
<EditPartReactionCell id={id} />
|
||||||
|
</PartReactionsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditPartReactionPage
|
||||||
12
web/src/pages/EditUserPage/EditUserPage.js
Normal file
12
web/src/pages/EditUserPage/EditUserPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import UsersLayout from 'src/layouts/UsersLayout'
|
||||||
|
import EditUserCell from 'src/components/EditUserCell'
|
||||||
|
|
||||||
|
const EditUserPage = ({ id }) => {
|
||||||
|
return (
|
||||||
|
<UsersLayout>
|
||||||
|
<EditUserCell id={id} />
|
||||||
|
</UsersLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditUserPage
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import MainLayout from 'src/layouts/MainLayout'
|
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 { initialize } from 'src/cascade/js/MainPage/CascadeMain'
|
||||||
import { useEffect, useState } from 'react'
|
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!
|
// 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)
|
const [code, setCode] = useState(starterCode)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sickCallback = (code) => setCode(code)
|
const sickCallback = (code) => setCode(code)
|
||||||
@@ -73,4 +73,12 @@ const HomePage = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HomePage = () => {
|
||||||
|
return (
|
||||||
|
<MainLayout>
|
||||||
|
hi
|
||||||
|
</MainLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default HomePage
|
export default HomePage
|
||||||
|
|||||||
12
web/src/pages/NewCommentPage/NewCommentPage.js
Normal file
12
web/src/pages/NewCommentPage/NewCommentPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import CommentsLayout from 'src/layouts/CommentsLayout'
|
||||||
|
import NewComment from 'src/components/NewComment'
|
||||||
|
|
||||||
|
const NewCommentPage = () => {
|
||||||
|
return (
|
||||||
|
<CommentsLayout>
|
||||||
|
<NewComment />
|
||||||
|
</CommentsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewCommentPage
|
||||||
12
web/src/pages/NewPartPage/NewPartPage.js
Normal file
12
web/src/pages/NewPartPage/NewPartPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import PartsLayout from 'src/layouts/PartsLayout'
|
||||||
|
import NewPart from 'src/components/NewPart'
|
||||||
|
|
||||||
|
const NewPartPage = () => {
|
||||||
|
return (
|
||||||
|
<PartsLayout>
|
||||||
|
<NewPart />
|
||||||
|
</PartsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewPartPage
|
||||||
12
web/src/pages/NewPartReactionPage/NewPartReactionPage.js
Normal file
12
web/src/pages/NewPartReactionPage/NewPartReactionPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import PartReactionsLayout from 'src/layouts/PartReactionsLayout'
|
||||||
|
import NewPartReaction from 'src/components/NewPartReaction'
|
||||||
|
|
||||||
|
const NewPartReactionPage = () => {
|
||||||
|
return (
|
||||||
|
<PartReactionsLayout>
|
||||||
|
<NewPartReaction />
|
||||||
|
</PartReactionsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewPartReactionPage
|
||||||
12
web/src/pages/NewUserPage/NewUserPage.js
Normal file
12
web/src/pages/NewUserPage/NewUserPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import UsersLayout from 'src/layouts/UsersLayout'
|
||||||
|
import NewUser from 'src/components/NewUser'
|
||||||
|
|
||||||
|
const NewUserPage = () => {
|
||||||
|
return (
|
||||||
|
<UsersLayout>
|
||||||
|
<NewUser />
|
||||||
|
</UsersLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewUserPage
|
||||||
12
web/src/pages/PartPage/PartPage.js
Normal file
12
web/src/pages/PartPage/PartPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import PartsLayout from 'src/layouts/PartsLayout'
|
||||||
|
import PartCell from 'src/components/PartCell'
|
||||||
|
|
||||||
|
const PartPage = ({ id }) => {
|
||||||
|
return (
|
||||||
|
<PartsLayout>
|
||||||
|
<PartCell id={id} />
|
||||||
|
</PartsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartPage
|
||||||
12
web/src/pages/PartReactionPage/PartReactionPage.js
Normal file
12
web/src/pages/PartReactionPage/PartReactionPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import PartReactionsLayout from 'src/layouts/PartReactionsLayout'
|
||||||
|
import PartReactionCell from 'src/components/PartReactionCell'
|
||||||
|
|
||||||
|
const PartReactionPage = ({ id }) => {
|
||||||
|
return (
|
||||||
|
<PartReactionsLayout>
|
||||||
|
<PartReactionCell id={id} />
|
||||||
|
</PartReactionsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartReactionPage
|
||||||
12
web/src/pages/PartReactionsPage/PartReactionsPage.js
Normal file
12
web/src/pages/PartReactionsPage/PartReactionsPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import PartReactionsLayout from 'src/layouts/PartReactionsLayout'
|
||||||
|
import PartReactionsCell from 'src/components/PartReactionsCell'
|
||||||
|
|
||||||
|
const PartReactionsPage = () => {
|
||||||
|
return (
|
||||||
|
<PartReactionsLayout>
|
||||||
|
<PartReactionsCell />
|
||||||
|
</PartReactionsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartReactionsPage
|
||||||
12
web/src/pages/PartsPage/PartsPage.js
Normal file
12
web/src/pages/PartsPage/PartsPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import PartsLayout from 'src/layouts/PartsLayout'
|
||||||
|
import PartsCell from 'src/components/PartsCell'
|
||||||
|
|
||||||
|
const PartsPage = () => {
|
||||||
|
return (
|
||||||
|
<PartsLayout>
|
||||||
|
<PartsCell />
|
||||||
|
</PartsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PartsPage
|
||||||
12
web/src/pages/UserPage/UserPage.js
Normal file
12
web/src/pages/UserPage/UserPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import UsersLayout from 'src/layouts/UsersLayout'
|
||||||
|
import UserCell from 'src/components/UserCell'
|
||||||
|
|
||||||
|
const UserPage = ({ id }) => {
|
||||||
|
return (
|
||||||
|
<UsersLayout>
|
||||||
|
<UserCell id={id} />
|
||||||
|
</UsersLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserPage
|
||||||
12
web/src/pages/UsersPage/UsersPage.js
Normal file
12
web/src/pages/UsersPage/UsersPage.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import UsersLayout from 'src/layouts/UsersLayout'
|
||||||
|
import UsersCell from 'src/components/UsersCell'
|
||||||
|
|
||||||
|
const UsersPage = () => {
|
||||||
|
return (
|
||||||
|
<UsersLayout>
|
||||||
|
<UsersCell />
|
||||||
|
</UsersLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UsersPage
|
||||||
Reference in New Issue
Block a user