Skip to content

Commit

Permalink
deleting and reordering resets linked list of design types
Browse files Browse the repository at this point in the history
  • Loading branch information
goodeats committed Mar 5, 2024
1 parent 5a95907 commit 8a35b60
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 21 deletions.
2 changes: 2 additions & 0 deletions app/models/design.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export interface IDesignWithType {
type: string
visible: boolean
createdAt: Date | string
nextId: string | null
prevId: string | null
ownerId: string
artboardId: string | null
palette: IPalette | null
Expand Down
213 changes: 195 additions & 18 deletions app/routes/sketch+/artboards+/$slug_+/actions/artboard-design.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,169 @@ export async function artboardDesignReorderAction({
}

// changes
const { id } = submission.value
const { id, direction } = submission.value
try {
await prisma.$transaction(async prisma => {
const design = await prisma.design.findFirst({
where: { id, ownerId: userId },
})
if (!design) return submissionErrorResponse(submission)
const { nextId, prevId } = design

// remove unique constraints on current design
const currentDesignRemoveNodes = prisma.design.update({
where: { id },
data: { prevId: null, nextId: null },
})

if (direction === 'up') {
// if design is head, do nothing
if (!prevId) return submissionErrorResponse(submission)

// CURRENT DESIGN PREV DESIGN (required unless was head)
const prev = await prisma.design.findFirst({
where: { id: prevId },
})
if (!prev) return submissionErrorResponse(submission)

const prevDesignRemoveNodes = prisma.design.update({
where: { id: prevId },
data: { prevId: null, nextId: null },
})

const prevDesignUpdateNodes = prisma.design.update({
where: { id: prevId },
data: { nextId, prevId: id },
})

// CURRENT DESIGN PREV PREV DESIGN (required unless prev was head)
// check if prev design had its own prev design
// and set nextId of prev prev design to current id of design
let prevPrevDesignUpdateNext
if (prev.prevId) {
const prevPrevDesign = await prisma.design.findFirst({
where: { id: prev.prevId },
})
if (prevPrevDesign) {
prevPrevDesignUpdateNext = prisma.design.update({
where: { id: prev.prevId },
data: { nextId: id },
})
}
}

// CURRENT DESIGN NEXT DESIGN (optional if was tail)
let nextDesignRemovePrev, nextDesignUpdatePrev
if (nextId) {
const next = await prisma.design.findFirst({
where: { id: nextId },
})
if (next) {
nextDesignRemovePrev = prisma.design.update({
where: { id: nextId },
data: { prevId: null },
})

nextDesignUpdatePrev = prisma.design.update({
where: { id: nextId },
data: { prevId },
})
}
}

// update prevId of current design to prevId of prev design
// and nextId of current design to id of prev design
const currentDesignUpdateNodes = prisma.design.update({
where: { id },
data: { prevId: prev.prevId, nextId: prevId },
})

// order of promises is important
// since unique constraints will fail the transaction
const promises = []
promises.push(currentDesignRemoveNodes)
promises.push(prevDesignRemoveNodes)
if (nextDesignRemovePrev) promises.push(nextDesignRemovePrev)
if (nextDesignUpdatePrev) promises.push(nextDesignUpdatePrev)
promises.push(prevPrevDesignUpdateNext)
promises.push(prevDesignUpdateNodes)
promises.push(currentDesignUpdateNodes)
await Promise.all(promises)
} else if (direction === 'down') {
console.log('down')
// if design is tail, do nothing
if (!nextId) return submissionErrorResponse(submission)

// CURRENT DESIGN NEXT DESIGN (required unless was tail)
const next = await prisma.design.findFirst({
where: { id: nextId },
})
if (!next) return submissionErrorResponse(submission)

const nextDesignRemoveNodes = prisma.design.update({
where: { id: nextId },
data: { prevId: null, nextId: null },
})

const nextDesignUpdateNodes = prisma.design.update({
where: { id: nextId },
data: { nextId: id, prevId },
})

// TODO: reorder here
// CURRENT DESIGN NEXT NEXT DESIGN (required unless next was tail)
// check if next design had its own next design
// and set nextId of next next design to current id of design
let nextNextDesignUpdatePrev
if (next.nextId) {
const nextNextDesign = await prisma.design.findFirst({
where: { id: next.nextId },
})
if (nextNextDesign) {
nextNextDesignUpdatePrev = prisma.design.update({
where: { id: next.nextId },
data: { prevId: id },
})
}
}

// CURRENT DESIGN PREV DESIGN (optional if was head)
let prevDesignRemoveNext, prevDesignUpdateNext
if (prevId) {
const prev = await prisma.design.findFirst({
where: { id: prevId },
})
if (prev) {
prevDesignRemoveNext = prisma.design.update({
where: { id: prevId },
data: { nextId: null },
})

prevDesignUpdateNext = prisma.design.update({
where: { id: prevId },
data: { nextId },
})
}
}

// update nextId of current design to nextId of prev design
// and nextId of current design to id of prev design
const currentDesignUpdateNodes = prisma.design.update({
where: { id },
data: { nextId: next.nextId, prevId: nextId },
})

// order of promises is important
// since unique constraints will fail the transaction
const promises = []
promises.push(currentDesignRemoveNodes)
promises.push(nextDesignRemoveNodes)
if (prevDesignRemoveNext) promises.push(prevDesignRemoveNext)
if (prevDesignUpdateNext) promises.push(prevDesignUpdateNext)
promises.push(nextNextDesignUpdatePrev)
promises.push(nextDesignUpdateNodes)
promises.push(currentDesignUpdateNodes)
await Promise.all(promises)
}
})
} catch (error) {
console.log(error)
Expand Down Expand Up @@ -114,41 +268,64 @@ export async function artboardDesignDeleteAction({
where: { id },
})
if (!design) return submissionErrorResponse(submission)
// get nextId and prevId from design
const { nextId, prevId } = design

// delete design will cascade delete type relation
await prisma.design.delete({
where: { id },
})

// if design is the only design in the artboard
if (!design.prevId && !design.nextId) return
if (!prevId && !nextId) return

if (!design.prevId && design.nextId) {
if (!prevId && nextId) {
// if head
// remove prevId from next design, becomes head
await prisma.design.update({
where: { id: design.nextId },
data: { prevId: null },
const nextDesign = await prisma.design.findFirst({
where: { id: nextId },
})
} else if (design.prevId && !design.nextId) {
if (nextDesign) {
await prisma.design.update({
where: { id: nextId },
data: { prevId: null },
})
}
} else if (prevId && !nextId) {
// if tail
// remove nextId from prev design, becomes tail
await prisma.design.update({
where: { id: design.prevId },
data: { nextId: null },
const prevDesign = await prisma.design.findFirst({
where: { id: prevId },
})
} else if (design.prevId && design.nextId) {
if (prevDesign) {
await prisma.design.update({
where: { id: prevId },
data: { nextId: null },
})
}
} else if (prevId && nextId) {
// if in middle
// replace nextId for prev design with nextId of deleted design
await prisma.design.update({
where: { id: design.prevId },
data: { nextId: design.nextId },
const prevDesign = await prisma.design.findFirst({
where: { id: prevId },
})
if (prevDesign) {
await prisma.design.update({
where: { id: prevId },
data: { nextId: nextId },
})
}

// replace prevId for next design with prevId of deleted design
await prisma.design.update({
where: { id: design.nextId },
data: { prevId: design.prevId },
const nextDesign = await prisma.design.findFirst({
where: { id: nextId },
})
if (nextDesign) {
await prisma.design.update({
where: { id: nextId },
data: { prevId: prevId },
})
}
}
})
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import {
PanelRowIconContainer,
PanelRowOrderContainer,
PanelRowValueContainer,
// PanelRow,
// PanelRowContainer,
PanelTitle,
} from '#app/components/shared'
import { type IDesignWithPalette } from '#app/models/design.server'
Expand All @@ -25,6 +23,27 @@ export const PanelContentArtboardDesignPalette = ({
artboard: PickedArtboardType
designPalettes: IDesignWithPalette[]
}) => {
const orderedDesignPalettes = designPalettes.reduce(
(acc: IDesignWithPalette[], designPalette) => {
if (!designPalette.prevId) {
acc.unshift(designPalette) // Add the head of the list to the start
} else {
let currentDesignIndex = acc.findIndex(
d => d.id === designPalette.prevId,
)
if (currentDesignIndex !== -1) {
// Insert the designPalette right after its predecessor
acc.splice(currentDesignIndex + 1, 0, designPalette)
} else {
// If predecessor is not found, add it to the end as a fallback
acc.push(designPalette)
}
}
return acc
},
[],
)

const designCount = designPalettes.length
return (
<Panel>
Expand All @@ -34,7 +53,7 @@ export const PanelContentArtboardDesignPalette = ({
<PanelFormArtboardDesignNewPalette artboardId={artboard.id} />
</div>
</PanelHeader>
{designPalettes.map((designPalette, index) => {
{orderedDesignPalettes.map((designPalette, index) => {
const { id, visible, palette } = designPalette
return (
<PanelRow key={palette.id}>
Expand Down

0 comments on commit 8a35b60

Please sign in to comment.