fix: add brainstorm tables migration + calm ghost cursor
- Create migration for BrainstormSession, BrainstormIdea, BrainstormNoteRef, BrainstormParticipant, BrainstormActivity, BrainstormShare, BrainstormSnapshot - Ghost cursor: only moves toward a target element, no random wandering, 120ms interval instead of 60fps, hidden when no target - Remove animate-ping that caused visual noise
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import React, { useEffect, useRef } from 'react'
|
import React, { useEffect, useRef } from 'react'
|
||||||
import { motion, AnimatePresence } from 'motion/react'
|
|
||||||
|
|
||||||
interface GhostCursorProps {
|
interface GhostCursorProps {
|
||||||
isActive: boolean
|
isActive: boolean
|
||||||
@@ -10,12 +9,9 @@ interface GhostCursorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function GhostCursor({ isActive, containerRef, targetId }: GhostCursorProps) {
|
export function GhostCursor({ isActive, containerRef, targetId }: GhostCursorProps) {
|
||||||
const positionRef = useRef({ x: 0, y: 0 })
|
|
||||||
const visibleRef = useRef(false)
|
|
||||||
const elRef = useRef<HTMLDivElement>(null)
|
const elRef = useRef<HTMLDivElement>(null)
|
||||||
const rafRef = useRef<number | null>(null)
|
const rafRef = useRef<number | null>(null)
|
||||||
const targetRef = useRef({ x: 0, y: 0 })
|
const posRef = useRef<{ x: number; y: number; visible: boolean }>({ x: 0, y: 0, visible: false })
|
||||||
const initializedRef = useRef(false)
|
|
||||||
const targetIdRef = useRef(targetId)
|
const targetIdRef = useRef(targetId)
|
||||||
targetIdRef.current = targetId
|
targetIdRef.current = targetId
|
||||||
const isActiveRef = useRef(isActive)
|
const isActiveRef = useRef(isActive)
|
||||||
@@ -23,52 +19,34 @@ export function GhostCursor({ isActive, containerRef, targetId }: GhostCursorPro
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isActive) {
|
if (!isActive) {
|
||||||
visibleRef.current = false
|
posRef.current.visible = false
|
||||||
initializedRef.current = false
|
|
||||||
if (elRef.current) elRef.current.style.opacity = '0'
|
if (elRef.current) elRef.current.style.opacity = '0'
|
||||||
if (rafRef.current) cancelAnimationFrame(rafRef.current)
|
if (rafRef.current) cancelAnimationFrame(rafRef.current)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let angle = Math.random() * Math.PI * 2
|
let lastMove = 0
|
||||||
|
const MOVE_INTERVAL = 120
|
||||||
const init = () => {
|
|
||||||
const container = containerRef.current
|
|
||||||
if (!container) { rafRef.current = requestAnimationFrame(init); return }
|
|
||||||
const rect = container.getBoundingClientRect()
|
|
||||||
if (rect.width === 0 || rect.height === 0) { rafRef.current = requestAnimationFrame(init); return }
|
|
||||||
|
|
||||||
const cx = rect.width / 2
|
|
||||||
const cy = rect.height / 2
|
|
||||||
targetRef.current = { x: cx + (Math.random() - 0.5) * 200, y: cy + (Math.random() - 0.5) * 200 }
|
|
||||||
positionRef.current = { ...targetRef.current }
|
|
||||||
initializedRef.current = true
|
|
||||||
visibleRef.current = true
|
|
||||||
if (elRef.current) {
|
|
||||||
elRef.current.style.opacity = '1'
|
|
||||||
elRef.current.style.transform = `translate(${positionRef.current.x}px, ${positionRef.current.y}px)`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rafRef.current = requestAnimationFrame(init)
|
|
||||||
|
|
||||||
const tick = () => {
|
const tick = () => {
|
||||||
if (!isActiveRef.current || !initializedRef.current) {
|
if (!isActiveRef.current) return
|
||||||
|
|
||||||
|
const now = performance.now()
|
||||||
|
if (now - lastMove < MOVE_INTERVAL) {
|
||||||
rafRef.current = requestAnimationFrame(tick)
|
rafRef.current = requestAnimationFrame(tick)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
lastMove = now
|
||||||
|
|
||||||
const container = containerRef.current
|
const container = containerRef.current
|
||||||
if (!container) { rafRef.current = requestAnimationFrame(tick); return }
|
if (!container) { rafRef.current = requestAnimationFrame(tick); return }
|
||||||
const containerRect = container.getBoundingClientRect()
|
const containerRect = container.getBoundingClientRect()
|
||||||
if (containerRect.width === 0 || containerRect.height === 0) { rafRef.current = requestAnimationFrame(tick); return }
|
if (containerRect.width === 0 || containerRect.height === 0) { rafRef.current = requestAnimationFrame(tick); return }
|
||||||
|
|
||||||
const cx = containerRect.width / 2
|
|
||||||
const cy = containerRect.height / 2
|
|
||||||
let tx = targetRef.current.x
|
|
||||||
let ty = targetRef.current.y
|
|
||||||
|
|
||||||
const currentTargetId = targetIdRef.current
|
const currentTargetId = targetIdRef.current
|
||||||
|
let tx: number | null = null
|
||||||
|
let ty: number | null = null
|
||||||
|
|
||||||
if (currentTargetId) {
|
if (currentTargetId) {
|
||||||
const nodeElement = container.querySelector(`[data-id="${currentTargetId}"]`) as HTMLElement | null
|
const nodeElement = container.querySelector(`[data-id="${currentTargetId}"]`) as HTMLElement | null
|
||||||
if (nodeElement) {
|
if (nodeElement) {
|
||||||
@@ -78,29 +56,34 @@ export function GhostCursor({ isActive, containerRef, targetId }: GhostCursorPro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const prev = positionRef.current
|
if (tx === null || ty === null) {
|
||||||
const dx = tx - prev.x
|
if (posRef.current.visible) {
|
||||||
const dy = ty - prev.y
|
posRef.current.visible = false
|
||||||
const dist = Math.sqrt(dx * dx + dy * dy)
|
if (elRef.current) elRef.current.style.opacity = '0'
|
||||||
|
}
|
||||||
if (!currentTargetId && dist < 20) {
|
rafRef.current = requestAnimationFrame(tick)
|
||||||
angle = Math.random() * Math.PI * 2
|
return
|
||||||
const radius = 150 + Math.random() * 200
|
|
||||||
tx = cx + Math.cos(angle) * radius
|
|
||||||
ty = cy + Math.sin(angle) * radius
|
|
||||||
targetRef.current = { x: tx, y: ty }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const speed = currentTargetId ? 0.12 : 0.04
|
const pos = posRef.current
|
||||||
let newX = prev.x + (tx - prev.x) * speed
|
const speed = 0.15
|
||||||
let newY = prev.y + (ty - prev.y) * speed
|
const newX = pos.x + (tx - pos.x) * speed
|
||||||
if (isNaN(newX)) newX = cx
|
const newY = pos.y + (ty - pos.y) * speed
|
||||||
if (isNaN(newY)) newY = cy
|
|
||||||
|
|
||||||
positionRef.current = { x: newX, y: newY }
|
if (!pos.visible) {
|
||||||
|
pos.x = tx
|
||||||
if (elRef.current) {
|
pos.y = ty
|
||||||
elRef.current.style.transform = `translate(${newX}px, ${newY}px)`
|
pos.visible = true
|
||||||
|
if (elRef.current) {
|
||||||
|
elRef.current.style.opacity = '1'
|
||||||
|
elRef.current.style.transform = `translate(${tx}px, ${ty}px)`
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pos.x = isNaN(newX) ? tx : newX
|
||||||
|
pos.y = isNaN(newY) ? ty : newY
|
||||||
|
if (elRef.current) {
|
||||||
|
elRef.current.style.transform = `translate(${pos.x}px, ${pos.y}px)`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rafRef.current = requestAnimationFrame(tick)
|
rafRef.current = requestAnimationFrame(tick)
|
||||||
@@ -121,7 +104,7 @@ export function GhostCursor({ isActive, containerRef, targetId }: GhostCursorPro
|
|||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
transition: 'opacity 0.3s ease',
|
transition: 'opacity 0.4s ease, transform 0.15s ease-out',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
@@ -129,11 +112,10 @@ export function GhostCursor({ isActive, containerRef, targetId }: GhostCursorPro
|
|||||||
<path d="M0 0L16 6L8 8L6 16L0 0Z" fill="#a78bfa" />
|
<path d="M0 0L16 6L8 8L6 16L0 0Z" fill="#a78bfa" />
|
||||||
</svg>
|
</svg>
|
||||||
<div className="absolute -top-1 -right-1 w-3 h-3">
|
<div className="absolute -top-1 -right-1 w-3 h-3">
|
||||||
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-violet-400 opacity-50" />
|
|
||||||
<span className="relative inline-flex rounded-full h-3 w-3 bg-violet-500" />
|
<span className="relative inline-flex rounded-full h-3 w-3 bg-violet-500" />
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-3 ml-3 px-2 py-0.5 rounded-full text-[10px] font-bold text-white whitespace-nowrap shadow-lg bg-gradient-to-r from-violet-500 to-purple-600">
|
<div className="mt-3 ml-3 px-2 py-0.5 rounded-full text-[10px] font-bold text-white whitespace-nowrap shadow-lg bg-gradient-to-r from-violet-500 to-purple-600">
|
||||||
AI ✦
|
AI
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
CREATE TABLE "BrainstormSession" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"seedIdea" TEXT NOT NULL,
|
||||||
|
"sourceNoteId" TEXT,
|
||||||
|
"contextNoteIds" TEXT,
|
||||||
|
"exportedNoteId" TEXT,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
"inviteToken" TEXT,
|
||||||
|
"inviteExpiry" TIMESTAMP(3),
|
||||||
|
"liveblocksRoomId" TEXT,
|
||||||
|
"isPublic" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"guestCanEdit" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"status" TEXT NOT NULL DEFAULT 'active',
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "BrainstormSession_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "BrainstormIdea" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"sessionId" TEXT NOT NULL,
|
||||||
|
"waveNumber" INTEGER NOT NULL,
|
||||||
|
"title" TEXT NOT NULL,
|
||||||
|
"description" TEXT NOT NULL,
|
||||||
|
"connectionToSeed" TEXT,
|
||||||
|
"noveltyScore" INTEGER,
|
||||||
|
"parentIdeaId" TEXT,
|
||||||
|
"convertedToNoteId" TEXT,
|
||||||
|
"relatedNoteIds" TEXT,
|
||||||
|
"status" TEXT NOT NULL DEFAULT 'active',
|
||||||
|
"positionX" DOUBLE PRECISION,
|
||||||
|
"positionY" DOUBLE PRECISION,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"createdBy" TEXT,
|
||||||
|
"createdByType" TEXT DEFAULT 'ai',
|
||||||
|
|
||||||
|
CONSTRAINT "BrainstormIdea_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "BrainstormNoteRef" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"ideaId" TEXT NOT NULL,
|
||||||
|
"noteId" TEXT,
|
||||||
|
"relation" TEXT NOT NULL,
|
||||||
|
"explanation" TEXT NOT NULL,
|
||||||
|
"verdict" TEXT NOT NULL DEFAULT 'unresolved',
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"visibility" TEXT NOT NULL DEFAULT 'participants',
|
||||||
|
|
||||||
|
CONSTRAINT "BrainstormNoteRef_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "BrainstormParticipant" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"sessionId" TEXT NOT NULL,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
"role" TEXT NOT NULL DEFAULT 'viewer',
|
||||||
|
"joinedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"lastSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "BrainstormParticipant_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "BrainstormActivity" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"sessionId" TEXT NOT NULL,
|
||||||
|
"userId" TEXT,
|
||||||
|
"action" TEXT NOT NULL,
|
||||||
|
"details" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "BrainstormActivity_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "BrainstormShare" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"sessionId" TEXT NOT NULL,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
"sharedBy" TEXT NOT NULL,
|
||||||
|
"status" TEXT NOT NULL DEFAULT 'pending',
|
||||||
|
"permission" TEXT NOT NULL DEFAULT 'editor',
|
||||||
|
"notifiedAt" TIMESTAMP(3),
|
||||||
|
"respondedAt" TIMESTAMP(3),
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "BrainstormShare_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "BrainstormSnapshot" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"sessionId" TEXT NOT NULL,
|
||||||
|
"activityId" TEXT,
|
||||||
|
"step" INTEGER NOT NULL,
|
||||||
|
"label" TEXT,
|
||||||
|
"ideaGraph" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "BrainstormSnapshot_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX "BrainstormSession_inviteToken_key" ON "BrainstormSession"("inviteToken");
|
||||||
|
CREATE INDEX "BrainstormSession_userId_idx" ON "BrainstormSession"("userId");
|
||||||
|
CREATE INDEX "BrainstormSession_userId_createdAt_idx" ON "BrainstormSession"("userId", "createdAt");
|
||||||
|
CREATE INDEX "BrainstormSession_inviteToken_idx" ON "BrainstormSession"("inviteToken");
|
||||||
|
CREATE INDEX "BrainstormSession_isPublic_idx" ON "BrainstormSession"("isPublic");
|
||||||
|
|
||||||
|
CREATE INDEX "BrainstormIdea_sessionId_idx" ON "BrainstormIdea"("sessionId");
|
||||||
|
CREATE INDEX "BrainstormIdea_waveNumber_idx" ON "BrainstormIdea"("waveNumber");
|
||||||
|
CREATE INDEX "BrainstormIdea_status_idx" ON "BrainstormIdea"("status");
|
||||||
|
CREATE INDEX "BrainstormIdea_parentIdeaId_idx" ON "BrainstormIdea"("parentIdeaId");
|
||||||
|
CREATE INDEX "BrainstormIdea_sessionId_status_idx" ON "BrainstormIdea"("sessionId", "status");
|
||||||
|
CREATE INDEX "BrainstormIdea_sessionId_waveNumber_createdAt_idx" ON "BrainstormIdea"("sessionId", "waveNumber", "createdAt");
|
||||||
|
|
||||||
|
CREATE INDEX "BrainstormNoteRef_ideaId_idx" ON "BrainstormNoteRef"("ideaId");
|
||||||
|
CREATE INDEX "BrainstormNoteRef_noteId_idx" ON "BrainstormNoteRef"("noteId");
|
||||||
|
CREATE INDEX "BrainstormNoteRef_noteId_relation_idx" ON "BrainstormNoteRef"("noteId", "relation");
|
||||||
|
CREATE INDEX "BrainstormNoteRef_visibility_idx" ON "BrainstormNoteRef"("visibility");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX "BrainstormParticipant_sessionId_userId_key" ON "BrainstormParticipant"("sessionId", "userId");
|
||||||
|
CREATE INDEX "BrainstormParticipant_sessionId_idx" ON "BrainstormParticipant"("sessionId");
|
||||||
|
CREATE INDEX "BrainstormParticipant_userId_idx" ON "BrainstormParticipant"("userId");
|
||||||
|
CREATE INDEX "BrainstormParticipant_sessionId_userId_role_idx" ON "BrainstormParticipant"("sessionId", "userId", "role");
|
||||||
|
|
||||||
|
CREATE INDEX "BrainstormActivity_sessionId_createdAt_asc_idx" ON "BrainstormActivity"("sessionId", "createdAt");
|
||||||
|
CREATE INDEX "BrainstormActivity_sessionId_createdAt_desc_idx" ON "BrainstormActivity"("sessionId", "createdAt" DESC);
|
||||||
|
CREATE INDEX "BrainstormActivity_sessionId_createdAt_idx" ON "BrainstormActivity"("sessionId", "createdAt");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX "BrainstormShare_sessionId_userId_key" ON "BrainstormShare"("sessionId", "userId");
|
||||||
|
CREATE INDEX "BrainstormShare_userId_idx" ON "BrainstormShare"("userId");
|
||||||
|
CREATE INDEX "BrainstormShare_status_idx" ON "BrainstormShare"("status");
|
||||||
|
|
||||||
|
CREATE INDEX "BrainstormSnapshot_sessionId_step_idx" ON "BrainstormSnapshot"("sessionId", "step");
|
||||||
|
CREATE INDEX "BrainstormSnapshot_sessionId_createdAt_idx" ON "BrainstormSnapshot"("sessionId", "createdAt");
|
||||||
|
CREATE INDEX "BrainstormSnapshot_activityId_idx" ON "BrainstormSnapshot"("activityId");
|
||||||
|
|
||||||
|
ALTER TABLE "BrainstormSession" ADD CONSTRAINT "BrainstormSession_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormSession" ADD CONSTRAINT "BrainstormSession_sourceNoteId_fkey" FOREIGN KEY ("sourceNoteId") REFERENCES "Note"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormSession" ADD CONSTRAINT "BrainstormSession_exportedNoteId_fkey" FOREIGN KEY ("exportedNoteId") REFERENCES "Note"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE "BrainstormIdea" ADD CONSTRAINT "BrainstormIdea_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "BrainstormSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormIdea" ADD CONSTRAINT "BrainstormIdea_parentIdeaId_fkey" FOREIGN KEY ("parentIdeaId") REFERENCES "BrainstormIdea"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormIdea" ADD CONSTRAINT "BrainstormIdea_convertedToNoteId_fkey" FOREIGN KEY ("convertedToNoteId") REFERENCES "Note"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE "BrainstormNoteRef" ADD CONSTRAINT "BrainstormNoteRef_ideaId_fkey" FOREIGN KEY ("ideaId") REFERENCES "BrainstormIdea"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormNoteRef" ADD CONSTRAINT "BrainstormNoteRef_noteId_fkey" FOREIGN KEY ("noteId") REFERENCES "Note"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE "BrainstormParticipant" ADD CONSTRAINT "BrainstormParticipant_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "BrainstormSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormParticipant" ADD CONSTRAINT "BrainstormParticipant_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE "BrainstormActivity" ADD CONSTRAINT "BrainstormActivity_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "BrainstormSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormActivity" ADD CONSTRAINT "BrainstormActivity_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE "BrainstormShare" ADD CONSTRAINT "BrainstormShare_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "BrainstormSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormShare" ADD CONSTRAINT "BrainstormShare_sharedBy_fkey" FOREIGN KEY ("sharedBy") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
ALTER TABLE "BrainstormShare" ADD CONSTRAINT "BrainstormShare_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE "BrainstormSnapshot" ADD CONSTRAINT "BrainstormSnapshot_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "BrainstormSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
Reference in New Issue
Block a user