From 0b4c5164199eff677c629934d31d1a0474735ea7 Mon Sep 17 00:00:00 2001 From: Gabriel Stein Date: Thu, 22 Jun 2023 17:27:05 +0200 Subject: [PATCH 1/7] techref: Pub tables and Workflows --- TECH_REF.MD | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/TECH_REF.MD b/TECH_REF.MD index 08462c3607..35d14bf1a9 100644 --- a/TECH_REF.MD +++ b/TECH_REF.MD @@ -1,5 +1,22 @@ # Technical Reference +## For Next Time +- Review and confirm our workflow terminology: + - Workflow actions: do not modify Pub metadata + - Internal side effects: modify Pub metadata, but directly in the app + - External side effects: modify Pub metadata, but via an integration +- How do we handle internal and external side effects? + +## Thursday, June 22, 2023 + +### Pub Tables +- Existence of a field on a pub is sufficient validation for PubTypes for the MVP -- both for integrations and stages. +- EAV vs. JSONB: going to maintain both for now so we can look into performance as we build. + +### Workflows +- Integrations can be connected to any stage. +- Workflow stage actions generally shouldn't change Pub metadata — Pub metadata should be changed in side effects or integrations. + ## Wednesday, June 21, 2023 ### Pub Types From 649bfee278c0f880dadc169556843d44e948282c Mon Sep 17 00:00:00 2001 From: Travis Rich Date: Thu, 22 Jun 2023 14:54:56 -0400 Subject: [PATCH 2/7] update: Adjust schema approach to metadata fields and values --- app/@community/(community)/pubs/page.tsx | 22 ++- package-lock.json | 18 ++- package.json | 4 +- .../migration.sql | 51 +++++++ .../migration.sql | 2 + prisma/schema.prisma | 55 ++++--- prisma/seed.ts | 138 ++++++++++-------- 7 files changed, 199 insertions(+), 91 deletions(-) create mode 100644 prisma/migrations/20230622182329_metadata_refactor/migration.sql create mode 100644 prisma/migrations/20230622182626_blob_optional/migration.sql diff --git a/app/@community/(community)/pubs/page.tsx b/app/@community/(community)/pubs/page.tsx index efdd0d1d81..e6c4fff8f1 100644 --- a/app/@community/(community)/pubs/page.tsx +++ b/app/@community/(community)/pubs/page.tsx @@ -8,15 +8,21 @@ export default async function Page() { } const pubs = await prisma.pub.findMany({ where: { communityId: onlyCommunity.id, parentId: null }, - select: { - id: true, - pubType: { select: { name: true, fields: true } }, - metadata: { select: { type: true, value: true } }, + include: { + pubType: { + include: { + metadataFields: true, + }, + }, + metadataValues: true, children: { - select: { - id: true, - pubType: { select: { name: true, fields: true } }, - metadata: { select: { type: true, value: true } }, + include: { + pubType: { + include: { + metadataFields: true, + }, + }, + metadataValues: true, }, }, }, diff --git a/package-lock.json b/package-lock.json index 8381799b95..d1d556ca8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,8 @@ "jsonwebtoken": "^9.0.0", "next": "13.4.5", "react": "18.2.0", - "react-dom": "18.2.0" + "react-dom": "18.2.0", + "uuid": "^9.0.0" }, "devDependencies": { "@types/diacritics": "^1.3.1", @@ -27,6 +28,7 @@ "@types/node": "20.3.1", "@types/react": "18.2.12", "@types/react-dom": "18.2.5", + "@types/uuid": "^9.0.2", "dotenv-cli": "^7.2.1", "lint-staged": "^13.2.2", "prettier": "^2.8.8", @@ -2371,6 +2373,12 @@ "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", "devOptional": true }, + "node_modules/@types/uuid": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "dev": true + }, "node_modules/@types/web-bluetooth": { "version": "0.0.17", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz", @@ -5342,6 +5350,14 @@ "node": ">=6.14.2" } }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index 2e8f26a317..21bd78b987 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "jsonwebtoken": "^9.0.0", "next": "13.4.5", "react": "18.2.0", - "react-dom": "18.2.0" + "react-dom": "18.2.0", + "uuid": "^9.0.0" }, "devDependencies": { "@types/diacritics": "^1.3.1", @@ -54,6 +55,7 @@ "@types/node": "20.3.1", "@types/react": "18.2.12", "@types/react-dom": "18.2.5", + "@types/uuid": "^9.0.2", "dotenv-cli": "^7.2.1", "lint-staged": "^13.2.2", "prettier": "^2.8.8", diff --git a/prisma/migrations/20230622182329_metadata_refactor/migration.sql b/prisma/migrations/20230622182329_metadata_refactor/migration.sql new file mode 100644 index 0000000000..9650613742 --- /dev/null +++ b/prisma/migrations/20230622182329_metadata_refactor/migration.sql @@ -0,0 +1,51 @@ +/* + Warnings: + + - You are about to drop the column `fields` on the `pub_types` table. All the data in the column will be lost. + - You are about to drop the `metadata` table. If the table is not empty, all the data it contains will be lost. + - Added the required column `metadataBlob` to the `pubs` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "metadata" DROP CONSTRAINT "metadata_pub_id_fkey"; + +-- AlterTable +ALTER TABLE "pub_types" DROP COLUMN "fields"; + +-- AlterTable +ALTER TABLE "pubs" ADD COLUMN "metadataBlob" JSONB NOT NULL; + +-- DropTable +DROP TABLE "metadata"; + +-- CreateTable +CREATE TABLE "metadata_fields" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "pub_type_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "metadata_fields_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "metadata_values" ( + "id" TEXT NOT NULL, + "field_id" TEXT NOT NULL, + "value" JSONB NOT NULL, + "pub_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "metadata_values_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "metadata_fields" ADD CONSTRAINT "metadata_fields_pub_type_id_fkey" FOREIGN KEY ("pub_type_id") REFERENCES "pub_types"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "metadata_values" ADD CONSTRAINT "metadata_values_field_id_fkey" FOREIGN KEY ("field_id") REFERENCES "metadata_fields"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "metadata_values" ADD CONSTRAINT "metadata_values_pub_id_fkey" FOREIGN KEY ("pub_id") REFERENCES "pubs"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20230622182626_blob_optional/migration.sql b/prisma/migrations/20230622182626_blob_optional/migration.sql new file mode 100644 index 0000000000..29a9101cae --- /dev/null +++ b/prisma/migrations/20230622182626_blob_optional/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "pubs" ALTER COLUMN "metadataBlob" DROP NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 4e775bae0d..95979a42bb 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -36,18 +36,19 @@ model Community { } model Pub { - id String @id @default(uuid()) - parent Pub? @relation("parent_child", fields: [parentId], references: [id]) - parentId String? @map(name: "parent_id") - pubType PubType @relation(fields: [pubTypeId], references: [id]) - pubTypeId String @map(name: "pub_type_id") - community Community @relation(fields: [communityId], references: [id]) - communityId String @map(name: "community_id") - createdAt DateTime @default(now()) @map(name: "created_at") - updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") - - children Pub[] @relation("parent_child") - metadata Metadata[] + id String @id @default(uuid()) + metadataBlob Json? + parent Pub? @relation("parent_child", fields: [parentId], references: [id]) + parentId String? @map(name: "parent_id") + pubType PubType @relation(fields: [pubTypeId], references: [id]) + pubTypeId String @map(name: "pub_type_id") + community Community @relation(fields: [communityId], references: [id]) + communityId String @map(name: "community_id") + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + + children Pub[] @relation("parent_child") + metadataValues MetadataValue[] @@map(name: "pubs") } @@ -55,27 +56,41 @@ model Pub { model PubType { id String @id @default(uuid()) name String - fields Json community Community @relation(fields: [communityId], references: [id]) communityId String @map(name: "community_id") createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") - pubs Pub[] + pubs Pub[] + metadataFields MetadataField[] @@map(name: "pub_types") } -model Metadata { +model MetadataField { id String @id @default(uuid()) - type String - value Json - pub Pub @relation(fields: [pubId], references: [id]) - pubId String @map(name: "pub_id") + name String + pubType PubType @relation(fields: [pubTypeId], references: [id]) + pubTypeId String @map(name: "pub_type_id") createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") - @@map(name: "metadata") + values MetadataValue[] + + @@map(name: "metadata_fields") +} + +model MetadataValue { + id String @id @default(uuid()) + field MetadataField @relation(fields: [fieldId], references: [id]) + fieldId String @map(name: "field_id") + value Json + pub Pub @relation(fields: [pubId], references: [id]) + pubId String @map(name: "pub_id") + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + + @@map(name: "metadata_values") } model Workflow { diff --git a/prisma/seed.ts b/prisma/seed.ts index 89a64a9a4a..1eef3a9704 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,4 +1,6 @@ import { PrismaClient } from "@prisma/client"; +import { v4 as uuidv4 } from "uuid"; + const prisma = new PrismaClient(); async function main() { const mainUserId = "a9a09993-8eb1-4122-abbf-b999d5c8afe3"; @@ -10,8 +12,9 @@ async function main() { name: "Atta Test", }, }); - const communityUUID = "33222293-8eb1-4122-abbf-b999d5c8afe3"; - const frankensteinUUID = "a9a09993-8eb1-4122-abbf-b999d5c8afe3"; + const communityUUID = uuidv4(); + const frankensteinUUID = uuidv4(); + const fieldIDs = [...Array(6)].map((x) => uuidv4()); const community = await prisma.community.create({ data: { id: communityUUID, @@ -20,99 +23,112 @@ async function main() { create: [ { name: "Book", - fields: ["title", "isbn", "publicationDate"], + metadataFields: { + create: [ + { id: fieldIDs[0], name: "title" }, + { id: fieldIDs[1], name: "isbn" }, + { id: fieldIDs[2], name: "publicationDate" }, + ], + }, pubs: { create: [ { id: frankensteinUUID, communityId: communityUUID, - metadata: { + metadataBlob: [ + { fieldId: fieldIDs[0], value: "Frankenstein" }, + { fieldId: fieldIDs[1], value: "10234-123414" }, + { fieldId: fieldIDs[2], value: "1959" }, + ], + metadataValues: { create: [ - { - type: "title", - value: "Frankenstein" - }, - { - type: "ISBN", - value: "10234-123414" - }, - { - type: "publicationDate", - value: "1959" - } - ] - } - } - ] - } + { fieldId: fieldIDs[0], value: "Frankenstein" }, + { fieldId: fieldIDs[1], value: "10234-123414" }, + { fieldId: fieldIDs[2], value: "1959" }, + ], + }, + }, + ], + }, }, { name: "Chapter", - fields: ["title", "files"], + metadataFields: { + create: [ + { id: fieldIDs[3], name: "title" }, + { id: fieldIDs[4], name: "files" }, + ], + }, pubs: { create: [ { communityId: communityUUID, parentId: frankensteinUUID, - metadata: { + metadataBlob: [ + { fieldId: fieldIDs[3], value: "Chapter 1" }, + { fieldId: fieldIDs[4], value: ["internet/chapter1.html"] }, + ], + metadataValues: { create: [ + { fieldId: fieldIDs[3], value: "Chapter 1" }, { - type: "title", - value: "Chapter 1" - }, - { - type: "files", - value: ["internet/chapter1.html"] + fieldId: fieldIDs[4], + value: ["internet/chapter1.html"], }, - - ] - } + ], + }, }, { communityId: communityUUID, parentId: frankensteinUUID, - metadata: { + metadataBlob: [ + { fieldId: fieldIDs[3], value: "Chapter 2" }, + { fieldId: fieldIDs[4], value: ["internet/chapter2.html"] }, + ], + metadataValues: { create: [ + { fieldId: fieldIDs[3], value: "Chapter 2" }, { - type: "title", - value: "Chapter 2" + fieldId: fieldIDs[4], + value: ["internet/chapter2.html"], }, - { - type: "files", - value: ["internet/chapter2.html"] - }, - - ] - } + ], + }, }, { communityId: communityUUID, parentId: frankensteinUUID, - metadata: { + metadataBlob: [ + { fieldId: fieldIDs[3], value: "Chapter 3" }, + { fieldId: fieldIDs[4], value: ["internet/chapter3.html"] }, + ], + metadataValues: { create: [ + { fieldId: fieldIDs[3], value: "Chapter 3" }, { - type: "title", - value: "Chapter 3" + fieldId: fieldIDs[4], + value: ["internet/chapter3.html"], }, - { - type: "files", - value: ["internet/chapter3.html"] - }, - - ] - } - } - ] - } + ], + }, + }, + ], + }, }, { name: "Journal", - fields: ["title", "publisher", "publicationDate"], - } - ] - } - } - }) + metadataFields: { + create: [ + { name: "title" }, + { name: "publisher" }, + { name: "publicationDate" }, + ], + }, + }, + ], + }, + }, + }); } main() .then(async () => { From a5e32262c065345a0154af8a4eed17a67c782954 Mon Sep 17 00:00:00 2001 From: Travis Rich Date: Thu, 22 Jun 2023 16:05:46 -0400 Subject: [PATCH 3/7] dev: Update prisma schema to have first pass at workflows and stages structure --- app/@community/(community)/workflows/page.tsx | 20 +++- .../migration.sql | 94 ++++++++++++++++ .../migration.sql | 11 ++ .../migration.sql | 14 +++ prisma/schema.prisma | 101 +++++++++++++++--- prisma/seed.ts | 54 ++++++++++ 6 files changed, 277 insertions(+), 17 deletions(-) create mode 100644 prisma/migrations/20230622194921_workflow_init/migration.sql create mode 100644 prisma/migrations/20230622195031_workflows_to_community/migration.sql create mode 100644 prisma/migrations/20230622195558_stage_names_order/migration.sql diff --git a/app/@community/(community)/workflows/page.tsx b/app/@community/(community)/workflows/page.tsx index f0cd4ec665..eb1f22dde7 100644 --- a/app/@community/(community)/workflows/page.tsx +++ b/app/@community/(community)/workflows/page.tsx @@ -1,7 +1,25 @@ -export default function Page() { +import prisma from "prisma/db"; + +export default async function Page() { + /* Normally, we would get the community based on the url or logged in user session */ + const onlyCommunity = await prisma.community.findFirst(); + if (!onlyCommunity) { + return null; + } + const workflows = await prisma.workflow.findMany({ + where: { communityId: onlyCommunity.id }, + include: { + stages: { + include: { + moveConstraints: true, + }, + }, + }, + }); return ( <>

Workflows

+
{JSON.stringify(workflows, null, 4)}
); } diff --git a/prisma/migrations/20230622194921_workflow_init/migration.sql b/prisma/migrations/20230622194921_workflow_init/migration.sql new file mode 100644 index 0000000000..2bfdb051e5 --- /dev/null +++ b/prisma/migrations/20230622194921_workflow_init/migration.sql @@ -0,0 +1,94 @@ +/* + Warnings: + + - Added the required column `workflow_id` to the `stages` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "stages" ADD COLUMN "workflow_id" TEXT NOT NULL; + +-- CreateTable +CREATE TABLE "move_constraint" ( + "id" TEXT NOT NULL, + "stage_id" TEXT NOT NULL, + "destination_id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "move_constraint_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "action_claim" ( + "id" TEXT NOT NULL, + "stage_id" TEXT NOT NULL, + "pub_id" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "releasedAt" TIMESTAMP(3), + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "action_claim_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "action_move" ( + "id" TEXT NOT NULL, + "source_stage_id" TEXT NOT NULL, + "destination_stage_id" TEXT NOT NULL, + "pub_id" TEXT NOT NULL, + "user_id" TEXT NOT NULL, + "note" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "action_move_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_PubToStage" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "_PubToStage_AB_unique" ON "_PubToStage"("A", "B"); + +-- CreateIndex +CREATE INDEX "_PubToStage_B_index" ON "_PubToStage"("B"); + +-- AddForeignKey +ALTER TABLE "stages" ADD CONSTRAINT "stages_workflow_id_fkey" FOREIGN KEY ("workflow_id") REFERENCES "workflows"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "move_constraint" ADD CONSTRAINT "move_constraint_stage_id_fkey" FOREIGN KEY ("stage_id") REFERENCES "stages"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "move_constraint" ADD CONSTRAINT "move_constraint_destination_id_fkey" FOREIGN KEY ("destination_id") REFERENCES "stages"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "action_claim" ADD CONSTRAINT "action_claim_stage_id_fkey" FOREIGN KEY ("stage_id") REFERENCES "stages"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "action_claim" ADD CONSTRAINT "action_claim_pub_id_fkey" FOREIGN KEY ("pub_id") REFERENCES "pubs"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "action_claim" ADD CONSTRAINT "action_claim_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "action_move" ADD CONSTRAINT "action_move_source_stage_id_fkey" FOREIGN KEY ("source_stage_id") REFERENCES "stages"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "action_move" ADD CONSTRAINT "action_move_destination_stage_id_fkey" FOREIGN KEY ("destination_stage_id") REFERENCES "stages"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "action_move" ADD CONSTRAINT "action_move_pub_id_fkey" FOREIGN KEY ("pub_id") REFERENCES "pubs"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "action_move" ADD CONSTRAINT "action_move_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_PubToStage" ADD CONSTRAINT "_PubToStage_A_fkey" FOREIGN KEY ("A") REFERENCES "pubs"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_PubToStage" ADD CONSTRAINT "_PubToStage_B_fkey" FOREIGN KEY ("B") REFERENCES "stages"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20230622195031_workflows_to_community/migration.sql b/prisma/migrations/20230622195031_workflows_to_community/migration.sql new file mode 100644 index 0000000000..0b0100b12a --- /dev/null +++ b/prisma/migrations/20230622195031_workflows_to_community/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - Added the required column `community_id` to the `workflows` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "workflows" ADD COLUMN "community_id" TEXT NOT NULL; + +-- AddForeignKey +ALTER TABLE "workflows" ADD CONSTRAINT "workflows_community_id_fkey" FOREIGN KEY ("community_id") REFERENCES "communities"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20230622195558_stage_names_order/migration.sql b/prisma/migrations/20230622195558_stage_names_order/migration.sql new file mode 100644 index 0000000000..132cf3bc59 --- /dev/null +++ b/prisma/migrations/20230622195558_stage_names_order/migration.sql @@ -0,0 +1,14 @@ +/* + Warnings: + + - Added the required column `name` to the `stages` table without a default value. This is not possible if the table is not empty. + - Added the required column `order` to the `stages` table without a default value. This is not possible if the table is not empty. + - Added the required column `name` to the `workflows` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "stages" ADD COLUMN "name" TEXT NOT NULL, +ADD COLUMN "order" TEXT NOT NULL; + +-- AlterTable +ALTER TABLE "workflows" ADD COLUMN "name" TEXT NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 95979a42bb..26fef14285 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -12,13 +12,15 @@ generator client { } model User { - id String @id @default(uuid()) - slug String @unique - email String @unique - name String - avatar String? - createdAt DateTime @default(now()) @map(name: "created_at") - updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + id String @id @default(uuid()) + slug String @unique + email String @unique + name String + avatar String? + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + ActionClaim ActionClaim[] + ActionMove ActionMove[] @@map(name: "users") } @@ -29,8 +31,9 @@ model Community { createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") - pubTypes PubType[] - pubs Pub[] + pubTypes PubType[] + pubs Pub[] + workflows Workflow[] @@map(name: "communities") } @@ -49,6 +52,9 @@ model Pub { children Pub[] @relation("parent_child") metadataValues MetadataValue[] + stages Stage[] + ActionClaim ActionClaim[] + ActionMove ActionMove[] @@map(name: "pubs") } @@ -94,27 +100,90 @@ model MetadataValue { } model Workflow { - id String @id @default(uuid()) - createdAt DateTime @default(now()) @map(name: "created_at") - updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + id String @id @default(uuid()) + name String + community Community @relation(fields: [communityId], references: [id]) + communityId String @map(name: "community_id") + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + + stages Stage[] @@map(name: "workflows") } model Stage { - id String @id @default(uuid()) - createdAt DateTime @default(now()) @map(name: "created_at") - updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + id String @id @default(uuid()) + name String + order String + workflow Workflow @relation(fields: [workflowId], references: [id]) + workflowId String @map(name: "workflow_id") + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + + pubs Pub[] + moveConstraints MoveConstraint[] @relation("move_constraint") + moveConstraintSources MoveConstraint[] @relation("move_constraint_destination") + claims ActionClaim[] + movesFrom ActionMove[] @relation("move_source_stage") + movesTo ActionMove[] @relation("move_destination_stage") @@map(name: "stages") } +// Pub-Stage m:m relationship is implicit. If we need additional data on that relationship, we can make it explicit + +model MoveConstraint { + id String @id @default(uuid()) + stage Stage @relation("move_constraint", fields: [stageId], references: [id]) + stageId String @map(name: "stage_id") + destination Stage @relation("move_constraint_destination", fields: [destinationId], references: [id]) + destinationId String @map(name: "destination_id") + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + + @@map(name: "move_constraint") +} + + +model ActionClaim { + id String @id @default(uuid()) + stage Stage @relation(fields: [stageId], references: [id]) + stageId String @map(name: "stage_id") + pub Pub @relation(fields: [pubId], references: [id]) + pubId String @map(name: "pub_id") + user User @relation(fields: [userId], references: [id]) + userId String @map(name: "user_id") + releasedAt DateTime? + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + + @@map(name: "action_claim") +} + +model ActionMove { + id String @id @default(uuid()) + sourceStage Stage @relation("move_source_stage", fields: [sourceStageId], references: [id]) + sourceStageId String @map(name: "source_stage_id") + destinationStage Stage @relation("move_destination_stage", fields: [destinationStageId], references: [id]) + destinationStageId String @map(name: "destination_stage_id") + pub Pub @relation(fields: [pubId], references: [id]) + pubId String @map(name: "pub_id") + user User @relation(fields: [userId], references: [id]) + userId String @map(name: "user_id") + note String + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + + @@map(name: "action_move") +} + model Members { id String @id @default(uuid()) createdAt DateTime @default(now()) @map(name: "created_at") updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") - // Permissions can be scoped to whole community or a selection of pubs + // Permissions can be scoped to whole community or a selection of pubs @@map(name: "members") } diff --git a/prisma/seed.ts b/prisma/seed.ts index 1eef3a9704..9b964743df 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -14,6 +14,7 @@ async function main() { }); const communityUUID = uuidv4(); const frankensteinUUID = uuidv4(); + const workflowUUID = uuidv4(); const fieldIDs = [...Array(6)].map((x) => uuidv4()); const community = await prisma.community.create({ data: { @@ -127,6 +128,59 @@ async function main() { }, ], }, + workflows: { + create: [ + { + id: workflowUUID, + name: "Our great review workflow", + stages: { + create: [ + { + name: "Drafting", + order: "aa", + moveConstraints: { + create: [ + { + destination: { + create: { + name: "Ready for Review", + order: "bb", + workflowId: workflowUUID, + moveConstraints: { + create: [ + { + destination: { + create: { + name: "Completed", + order: "cc", + workflowId: + workflowUUID, + }, + }, + }, + { + destination: { + create: { + name: "Discarded", + order: "dd", + workflowId: + workflowUUID, + }, + }, + }, + ], + }, + }, + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, }, }); } From 9b5bd59d1ef583d7104376cea2a1ee3f25949a64 Mon Sep 17 00:00:00 2001 From: Travis Rich Date: Thu, 22 Jun 2023 16:16:06 -0400 Subject: [PATCH 4/7] dev: Fix User relation names --- prisma/schema.prisma | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 26fef14285..0eb91acf9c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -12,15 +12,16 @@ generator client { } model User { - id String @id @default(uuid()) - slug String @unique - email String @unique - name String - avatar String? - createdAt DateTime @default(now()) @map(name: "created_at") - updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") - ActionClaim ActionClaim[] - ActionMove ActionMove[] + id String @id @default(uuid()) + slug String @unique + email String @unique + name String + avatar String? + createdAt DateTime @default(now()) @map(name: "created_at") + updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at") + + claims ActionClaim[] + moves ActionMove[] @@map(name: "users") } @@ -145,7 +146,6 @@ model MoveConstraint { @@map(name: "move_constraint") } - model ActionClaim { id String @id @default(uuid()) stage Stage @relation(fields: [stageId], references: [id]) From d828cc45d45d8a3d1611144e5242878a2723ce3f Mon Sep 17 00:00:00 2001 From: Travis Rich Date: Thu, 22 Jun 2023 16:23:35 -0400 Subject: [PATCH 5/7] dev: Fix Pub relation names --- prisma/schema.prisma | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 0eb91acf9c..65fb0115e8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -54,8 +54,8 @@ model Pub { children Pub[] @relation("parent_child") metadataValues MetadataValue[] stages Stage[] - ActionClaim ActionClaim[] - ActionMove ActionMove[] + claims ActionClaim[] + moves ActionMove[] @@map(name: "pubs") } From f752085204c09de5b565e128870b413de81aa85f Mon Sep 17 00:00:00 2001 From: Gabriel Stein Date: Mon, 26 Jun 2023 16:27:35 +0200 Subject: [PATCH 6/7] Update TECH_REF.MD to reflect some clarifications on 06-26-23. --- TECH_REF.MD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TECH_REF.MD b/TECH_REF.MD index 35d14bf1a9..a16fccabfa 100644 --- a/TECH_REF.MD +++ b/TECH_REF.MD @@ -14,8 +14,8 @@ - EAV vs. JSONB: going to maintain both for now so we can look into performance as we build. ### Workflows -- Integrations can be connected to any stage. -- Workflow stage actions generally shouldn't change Pub metadata — Pub metadata should be changed in side effects or integrations. +- Integrations can be connected to any workflow stage. +- Workflow stage actions shouldn't change Pub metadata — Pub metadata should be directly edited or changed via integrations. ## Wednesday, June 21, 2023 From 34b929a3266af9e7ef58475576cef8b638c1edb1 Mon Sep 17 00:00:00 2001 From: Gabriel Stein Date: Mon, 26 Jun 2023 16:36:23 +0200 Subject: [PATCH 7/7] Update TECH_REF.MD --- TECH_REF.MD | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TECH_REF.MD b/TECH_REF.MD index a16fccabfa..837ef40b0a 100644 --- a/TECH_REF.MD +++ b/TECH_REF.MD @@ -15,7 +15,9 @@ ### Workflows - Integrations can be connected to any workflow stage. -- Workflow stage actions shouldn't change Pub metadata — Pub metadata should be directly edited or changed via integrations. + - An integration doesn't know anything about the workflow or stage. Either modifies pub metadata or performs a side effect. +- Anything that modifies a Pub's relationship with the workflow is an action. + - Actions shouldn't change Pub metadata — Pub metadata should be directly edited or changed via integrations. ## Wednesday, June 21, 2023