fix: federated spaces in folders + DnD double indicator line
Remove FK constraint on space_folder_members.space_id so federated space IDs (which don't exist in the local spaces table) can be added to folders without silently failing. Add migration to recreate the table for existing databases and explicit cleanup on space deletion. Offset drop indicator lines by 3px into the mb-1.5 gap so adjacent items share one visual position instead of showing two lines. Extract TransferOwnershipModal (~165 lines) to its own file.
This commit is contained in:
@@ -174,7 +174,8 @@ function createTables(db: Database.Database): void {
|
||||
|
||||
CREATE TABLE IF NOT EXISTS space_folder_members (
|
||||
folder_id TEXT NOT NULL REFERENCES space_folders(id) ON DELETE CASCADE,
|
||||
space_id TEXT NOT NULL REFERENCES spaces(id) ON DELETE CASCADE,
|
||||
space_id TEXT NOT NULL,
|
||||
position INTEGER DEFAULT 0,
|
||||
PRIMARY KEY (folder_id, space_id)
|
||||
);
|
||||
|
||||
|
||||
@@ -251,6 +251,28 @@ export function runMigrations(db: Database.Database): void {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Remove FK constraint from space_folder_members (federated spaces) ────
|
||||
{
|
||||
const tableInfo = db.prepare(
|
||||
"SELECT sql FROM sqlite_master WHERE type='table' AND name='space_folder_members'"
|
||||
).get() as { sql: string } | undefined;
|
||||
|
||||
if (tableInfo && tableInfo.sql.includes('REFERENCES spaces')) {
|
||||
console.log('Migrating: Removing FK constraint from space_folder_members...');
|
||||
db.exec(`
|
||||
CREATE TABLE space_folder_members_new (
|
||||
folder_id TEXT NOT NULL REFERENCES space_folders(id) ON DELETE CASCADE,
|
||||
space_id TEXT NOT NULL,
|
||||
position INTEGER DEFAULT 0,
|
||||
PRIMARY KEY (folder_id, space_id)
|
||||
);
|
||||
INSERT INTO space_folder_members_new SELECT folder_id, space_id, position FROM space_folder_members;
|
||||
DROP TABLE space_folder_members;
|
||||
ALTER TABLE space_folder_members_new RENAME TO space_folder_members;
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Migrations complete.');
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ export const spaceFolders = sqliteTable('space_folders', {
|
||||
|
||||
export const spaceFolderMembers = sqliteTable('space_folder_members', {
|
||||
folderId: text('folder_id').notNull().references(() => spaceFolders.id, { onDelete: 'cascade' }),
|
||||
spaceId: text('space_id').notNull().references(() => spaces.id, { onDelete: 'cascade' }),
|
||||
spaceId: text('space_id').notNull(), // No FK — federated space IDs don't exist locally
|
||||
position: integer('position').default(0),
|
||||
}, (table) => ({
|
||||
pk: primaryKey({ columns: [table.folderId, table.spaceId] }),
|
||||
|
||||
@@ -420,10 +420,11 @@ export async function spaceRoutes(app: FastifyInstance): Promise<void> {
|
||||
return reply.code(403).send({ error: 'Only the space owner can delete the space', statusCode: 403 });
|
||||
}
|
||||
|
||||
// Delete all channels (messages cascade), members, then server atomically
|
||||
// Delete all channels (messages cascade), members, folder refs, then space atomically
|
||||
db.transaction((tx) => {
|
||||
tx.delete(schema.channels).where(eq(schema.channels.spaceId, id)).run();
|
||||
tx.delete(schema.spaceMembers).where(eq(schema.spaceMembers.spaceId, id)).run();
|
||||
tx.delete(schema.spaceFolderMembers).where(eq(schema.spaceFolderMembers.spaceId, id)).run();
|
||||
tx.delete(schema.spaces).where(eq(schema.spaces.id, id)).run();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user