feat: add GIF Mood Board workshop
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m5s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m5s
- New workshop where each team member shares up to 5 GIFs with notes to express their weekly mood - Per-user week rating (1-5 stars) visible next to each member's section - Masonry-style grid with adjustable column count (3/4/5) toggle - Handwriting font (Caveat) for GIF notes - Full real-time collaboration via SSE - Clean migration (add_gif_mood_workshop) safe for production deploy - DB backup via cp before each migration in docker-entrypoint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
-- DropTable
|
||||
PRAGMA foreign_keys=off;
|
||||
DROP TABLE "Emotion";
|
||||
PRAGMA foreign_keys=on;
|
||||
|
||||
-- DropTable
|
||||
PRAGMA foreign_keys=off;
|
||||
DROP TABLE "KeyResultStatus";
|
||||
PRAGMA foreign_keys=on;
|
||||
|
||||
-- DropTable
|
||||
PRAGMA foreign_keys=off;
|
||||
DROP TABLE "OKRStatus";
|
||||
PRAGMA foreign_keys=on;
|
||||
|
||||
-- DropTable
|
||||
PRAGMA foreign_keys=off;
|
||||
DROP TABLE "TeamRole";
|
||||
PRAGMA foreign_keys=on;
|
||||
|
||||
-- DropTable
|
||||
PRAGMA foreign_keys=off;
|
||||
DROP TABLE "WeeklyCheckInCategory";
|
||||
PRAGMA foreign_keys=on;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "GifMoodSession" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"title" TEXT NOT NULL,
|
||||
"date" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"userId" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "GifMoodSession_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "GifMoodUserRating" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"rating" INTEGER NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "GifMoodUserRating_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "GifMoodSession" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT "GifMoodUserRating_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "GifMoodItem" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"gifUrl" TEXT NOT NULL,
|
||||
"note" TEXT,
|
||||
"order" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "GifMoodItem_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "GifMoodSession" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT "GifMoodItem_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "GMSessionShare" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"role" TEXT NOT NULL DEFAULT 'EDITOR',
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "GMSessionShare_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "GifMoodSession" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT "GMSessionShare_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "GMSessionEvent" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"payload" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "GMSessionEvent_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "GifMoodSession" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT "GMSessionEvent_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- RedefineTables
|
||||
PRAGMA defer_foreign_keys=ON;
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_WeeklyCheckInItem" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"content" TEXT NOT NULL,
|
||||
"category" TEXT NOT NULL,
|
||||
"emotion" TEXT NOT NULL DEFAULT 'NONE',
|
||||
"order" INTEGER NOT NULL DEFAULT 0,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "WeeklyCheckInItem_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "WeeklyCheckInSession" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
INSERT INTO "new_WeeklyCheckInItem" ("category", "content", "createdAt", "emotion", "id", "order", "sessionId", "updatedAt") SELECT "category", "content", "createdAt", "emotion", "id", "order", "sessionId", "updatedAt" FROM "WeeklyCheckInItem";
|
||||
DROP TABLE "WeeklyCheckInItem";
|
||||
ALTER TABLE "new_WeeklyCheckInItem" RENAME TO "WeeklyCheckInItem";
|
||||
CREATE INDEX "WeeklyCheckInItem_sessionId_idx" ON "WeeklyCheckInItem"("sessionId");
|
||||
CREATE INDEX "WeeklyCheckInItem_sessionId_category_idx" ON "WeeklyCheckInItem"("sessionId", "category");
|
||||
PRAGMA foreign_keys=ON;
|
||||
PRAGMA defer_foreign_keys=OFF;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GifMoodSession_userId_idx" ON "GifMoodSession"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GifMoodSession_date_idx" ON "GifMoodSession"("date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GifMoodUserRating_sessionId_idx" ON "GifMoodUserRating"("sessionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "GifMoodUserRating_sessionId_userId_key" ON "GifMoodUserRating"("sessionId", "userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GifMoodItem_sessionId_userId_idx" ON "GifMoodItem"("sessionId", "userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GifMoodItem_sessionId_idx" ON "GifMoodItem"("sessionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GMSessionShare_sessionId_idx" ON "GMSessionShare"("sessionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GMSessionShare_userId_idx" ON "GMSessionShare"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "GMSessionShare_sessionId_userId_key" ON "GMSessionShare"("sessionId", "userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "GMSessionEvent_sessionId_createdAt_idx" ON "GMSessionEvent"("sessionId", "createdAt");
|
||||
|
||||
@@ -34,6 +34,12 @@ model User {
|
||||
sharedWeatherSessions WeatherSessionShare[]
|
||||
weatherSessionEvents WeatherSessionEvent[]
|
||||
weatherEntries WeatherEntry[]
|
||||
// GIF Mood Board relations
|
||||
gifMoodSessions GifMoodSession[]
|
||||
gifMoodItems GifMoodItem[]
|
||||
sharedGifMoodSessions GMSessionShare[]
|
||||
gifMoodSessionEvents GMSessionEvent[]
|
||||
gifMoodRatings GifMoodUserRating[]
|
||||
// Teams & OKRs relations
|
||||
createdTeams Team[]
|
||||
teamMembers TeamMember[]
|
||||
@@ -525,3 +531,81 @@ model WeatherSessionEvent {
|
||||
|
||||
@@index([sessionId, createdAt])
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// GIF Mood Board Workshop
|
||||
// ============================================
|
||||
|
||||
model GifMoodSession {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
date DateTime @default(now())
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
items GifMoodItem[]
|
||||
shares GMSessionShare[]
|
||||
events GMSessionEvent[]
|
||||
ratings GifMoodUserRating[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([userId])
|
||||
@@index([date])
|
||||
}
|
||||
|
||||
model GifMoodUserRating {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
session GifMoodSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
rating Int // 1-5
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([sessionId, userId])
|
||||
@@index([sessionId])
|
||||
}
|
||||
|
||||
model GifMoodItem {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
session GifMoodSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
gifUrl String
|
||||
note String?
|
||||
order Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([sessionId, userId])
|
||||
@@index([sessionId])
|
||||
}
|
||||
|
||||
model GMSessionShare {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
session GifMoodSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
role ShareRole @default(EDITOR)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([sessionId, userId])
|
||||
@@index([sessionId])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model GMSessionEvent {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
session GifMoodSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
type String // GIF_ADDED, GIF_UPDATED, GIF_DELETED, SESSION_UPDATED
|
||||
payload String // JSON payload
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([sessionId, createdAt])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user