Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/main/api/dto/folders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ const foldersAdd = t.Object({
})

const foldersUpdate = t.Object({
name: t.String(),
icon: t.Union([t.String(), t.Null()]),
defaultLanguage: t.String(),
parentId: t.Union([t.Number(), t.Null()]),
isOpen: t.Number({ minimum: 0, maximum: 1 }),
orderIndex: t.Number(),
name: t.Optional(t.String()),
icon: t.Optional(t.Union([t.String(), t.Null()])),
defaultLanguage: t.Optional(t.String()),
parentId: t.Optional(t.Union([t.Number(), t.Null()])),
isOpen: t.Optional(t.Number({ minimum: 0, maximum: 1 })),
orderIndex: t.Optional(t.Number()),
})

const foldersItem = t.Object({
Expand Down
17 changes: 12 additions & 5 deletions src/main/api/dto/snippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ const snippetsAdd = t.Object({
})

const snippetsUpdate = t.Object({
...snippetsAdd.properties,
folderId: t.Union([t.Number(), t.Null()]),
description: t.Union([t.String(), t.Null()]),
isDeleted: t.Number({ minimum: 0, maximum: 1 }),
isFavorites: t.Number({ minimum: 0, maximum: 1 }),
name: t.Optional(t.String()),
folderId: t.Optional(t.Union([t.Number(), t.Null()])),
description: t.Optional(t.Union([t.String(), t.Null()])),
isDeleted: t.Optional(t.Number({ minimum: 0, maximum: 1 })),
isFavorites: t.Optional(t.Number({ minimum: 0, maximum: 1 })),
})

const snippetContentsAdd = t.Object({
Expand All @@ -20,6 +20,12 @@ const snippetContentsAdd = t.Object({
language: t.String(), // TODO: enum
})

const snippetContentsUpdate = t.Object({
label: t.Optional(t.String()),
value: t.Optional(t.Union([t.String(), t.Null()])),
language: t.Optional(t.String()), // TODO: enum
})

const snippetItem = t.Object({
id: t.Number(),
name: t.String(),
Expand Down Expand Up @@ -54,6 +60,7 @@ const snippetsResponse = t.Array(snippetItem)

export const snippetsDTO = new Elysia().model({
snippetContentsAdd,
snippetContentsUpdate,
snippetsAdd,
snippetsUpdate,
snippetsQuery: t.Object({
Expand Down
214 changes: 123 additions & 91 deletions src/main/api/routes/folders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,119 +136,151 @@ app
},
)
// Обновление папки
.put(
.patch(
'/:id',
({ params, body, error }) => {
const now = Date.now()
const { id } = params
const { name, icon, defaultLanguage, parentId, isOpen, orderIndex }
= body
const now = Date.now()

const updateFields: string[] = []
const updateParams: any[] = []
let needOrderUpdate = false
let newParentId: number | null | undefined
let newOrderIndex: number | undefined

if ('name' in body) {
updateFields.push('name = ?')
updateParams.push(body.name)
}

if ('icon' in body) {
updateFields.push('icon = ?')
updateParams.push(body.icon)
}

if ('defaultLanguage' in body) {
updateFields.push('defaultLanguage = ?')
updateParams.push(body.defaultLanguage)
}

if ('isOpen' in body) {
updateFields.push('isOpen = ?')
updateParams.push(body.isOpen)
}

if ('parentId' in body) {
updateFields.push('parentId = ?')
updateParams.push(body.parentId)
newParentId = body.parentId
needOrderUpdate = true
}

if ('orderIndex' in body) {
updateFields.push('orderIndex = ?')
updateParams.push(body.orderIndex)
newOrderIndex = body.orderIndex
needOrderUpdate = true
}

if (updateFields.length === 0) {
return error(400, { message: 'Need at least one field to update' })
}

updateFields.push('updatedAt = ?')

updateParams.push(now)
updateParams.push(id)

const transaction = db.transaction(() => {
// Получаем текущие данные папки
const folder = db
.prepare(
`
SELECT parentId, orderIndex
FROM folders
WHERE id = ?
`,
)
.get(id) as { parentId: number | null, orderIndex: number }
.prepare('SELECT parentId, orderIndex FROM folders WHERE id = ?')
.get(id) as
| { parentId: number | null, orderIndex: number }
| undefined

if (!folder) {
return error(404, { message: 'Folder not found' })
}

// Если изменился родитель или позиция
if (parentId !== folder.parentId || orderIndex !== folder.orderIndex) {
if (parentId === folder.parentId) {
// Перемещение в пределах одного родителя
if (orderIndex > folder.orderIndex) {
// Двигаем вниз - уменьшаем индексы папок между старой и новой позицией
// Обновляем порядок, только если изменился родитель или индекс
if (needOrderUpdate) {
const currentParentId = folder.parentId
const currentOrderIndex = folder.orderIndex
const targetParentId
= newParentId === undefined ? currentParentId : newParentId
const targetOrderIndex
= newOrderIndex === undefined ? currentOrderIndex : newOrderIndex

if (
targetParentId !== currentParentId
|| targetOrderIndex !== currentOrderIndex
) {
if (targetParentId === currentParentId) {
// Перемещение в пределах одного родителя
if (targetOrderIndex > currentOrderIndex) {
// Двигаем вниз - уменьшаем индексы папок между старой и новой позицией
db.prepare(
`UPDATE folders
SET orderIndex = orderIndex - 1
WHERE parentId ${currentParentId === null ? 'IS NULL' : '= ?'}
AND orderIndex > ?
AND orderIndex <= ?`,
).run(
...(currentParentId === null
? [currentOrderIndex, targetOrderIndex]
: [currentParentId, currentOrderIndex, targetOrderIndex]),
)
}
else {
// Двигаем вверх - увеличиваем индексы папок между новой и старой позицией
db.prepare(
`UPDATE folders
SET orderIndex = orderIndex + 1
WHERE parentId ${currentParentId === null ? 'IS NULL' : '= ?'}
AND orderIndex >= ?
AND orderIndex < ?`,
).run(
...(currentParentId === null
? [targetOrderIndex, currentOrderIndex]
: [currentParentId, targetOrderIndex, currentOrderIndex]),
)
}
}
else {
// Перемещение между разными родителями
// 1. Обновляем индексы в старом родителе
db.prepare(
`
UPDATE folders
SET orderIndex = orderIndex - 1
WHERE parentId ${folder.parentId === null ? 'IS NULL' : '= ?'}
AND orderIndex > ?
AND orderIndex <= ?
`,
`UPDATE folders
SET orderIndex = orderIndex - 1
WHERE parentId ${currentParentId === null ? 'IS NULL' : '= ?'}
AND orderIndex > ?`,
).run(
...(folder.parentId === null
? [folder.orderIndex, orderIndex]
: [folder.parentId, folder.orderIndex, orderIndex]),
...(currentParentId === null
? [currentOrderIndex]
: [currentParentId, currentOrderIndex]),
)
}
else {
// Двигаем вверх - увеличиваем индексы папок между новой и старой позицией

// 2. Обновляем индексы в новом родителе
db.prepare(
`
UPDATE folders
SET orderIndex = orderIndex + 1
WHERE parentId ${folder.parentId === null ? 'IS NULL' : '= ?'}
AND orderIndex >= ?
AND orderIndex < ?
`,
`UPDATE folders
SET orderIndex = orderIndex + 1
WHERE parentId ${targetParentId === null ? 'IS NULL' : '= ?'}
AND orderIndex >= ?`,
).run(
...(folder.parentId === null
? [orderIndex, folder.orderIndex]
: [folder.parentId, orderIndex, folder.orderIndex]),
...(targetParentId === null
? [targetOrderIndex]
: [targetParentId, targetOrderIndex]),
)
}
}
else {
// Перемещение между разными родителями
// 1. Обновляем индексы в старом родителе
db.prepare(
`
UPDATE folders
SET orderIndex = orderIndex - 1
WHERE parentId ${folder.parentId === null ? 'IS NULL' : '= ?'}
AND orderIndex > ?
`,
).run(
...(folder.parentId === null
? [folder.orderIndex]
: [folder.parentId, folder.orderIndex]),
)

// 2. Обновляем индексы в новом родителе
db.prepare(
`
UPDATE folders
SET orderIndex = orderIndex + 1
WHERE parentId ${parentId === null ? 'IS NULL' : '= ?'}
AND orderIndex >= ?
`,
).run(
...(parentId === null ? [orderIndex] : [parentId, orderIndex]),
)
}
}

// Обновляем саму папку
db.prepare(
`
UPDATE folders
SET name = ?,
icon = ?,
defaultLanguage = ?,
isOpen = ?,
parentId = ?,
orderIndex = ?,
updatedAt = ?
WHERE id = ?
`,
).run(
name,
icon,
defaultLanguage,
isOpen,
parentId,
orderIndex,
now,
id,
)
const updateStmt = db.prepare(`
UPDATE folders SET ${updateFields.join(', ')} WHERE id = ?
`)
updateStmt.run(...updateParams)
})

transaction()
Expand Down
Loading