mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 15:30:13 +01:00
Fix duplicated lists and do not show debug messages when env DEBUG is not true. Part 3.
Thanks to xet7 ! Fixes #5952
This commit is contained in:
parent
1761f43afa
commit
58df525b49
5 changed files with 113 additions and 308 deletions
|
|
@ -63,7 +63,9 @@ BlazeComponent.extendComponent({
|
||||||
title: 'Default',
|
title: 'Default',
|
||||||
boardId: boardId,
|
boardId: boardId,
|
||||||
});
|
});
|
||||||
console.log(`Created default swimlane ${swimlaneId} for board ${boardId}`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Created default swimlane ${swimlaneId} for board ${boardId}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this._swimlaneCreated.add(boardId);
|
this._swimlaneCreated.add(boardId);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -123,6 +125,9 @@ BlazeComponent.extendComponent({
|
||||||
// Fix missing lists migration (for cards with wrong listId references)
|
// Fix missing lists migration (for cards with wrong listId references)
|
||||||
await this.fixMissingLists(boardId);
|
await this.fixMissingLists(boardId);
|
||||||
|
|
||||||
|
// Fix duplicate lists created by WeKan 8.10
|
||||||
|
await this.fixDuplicateLists(boardId);
|
||||||
|
|
||||||
// Start attachment migration in background if needed
|
// Start attachment migration in background if needed
|
||||||
this.startAttachmentMigrationIfNeeded(boardId);
|
this.startAttachmentMigrationIfNeeded(boardId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -312,7 +317,9 @@ BlazeComponent.extendComponent({
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result && result.success) {
|
if (result && result.success) {
|
||||||
console.log(`Successfully fixed missing lists for board ${boardId}: created ${result.createdLists} lists, updated ${result.updatedCards} cards`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Successfully fixed missing lists for board ${boardId}: created ${result.createdLists} lists, updated ${result.updatedCards} cards`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -320,6 +327,55 @@ BlazeComponent.extendComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async fixDuplicateLists(boardId) {
|
||||||
|
try {
|
||||||
|
const board = ReactiveCache.getBoard(boardId);
|
||||||
|
if (!board) return;
|
||||||
|
|
||||||
|
// Check if board has already been processed for duplicate lists fix
|
||||||
|
if (board.fixDuplicateListsCompleted) {
|
||||||
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Board ${boardId} has already been processed for duplicate lists fix`);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Starting duplicate lists fix for board ${boardId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute the duplicate lists fix
|
||||||
|
const result = await new Promise((resolve, reject) => {
|
||||||
|
Meteor.call('fixDuplicateLists.fixBoard', boardId, (error, result) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result && result.fixed > 0) {
|
||||||
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Successfully fixed ${result.fixed} duplicate lists for board ${boardId}: ${result.fixedSwimlanes} swimlanes, ${result.fixedLists} lists`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark board as processed
|
||||||
|
Meteor.call('boards.update', boardId, { $set: { fixDuplicateListsCompleted: true } });
|
||||||
|
} else if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`No duplicate lists found for board ${boardId}`);
|
||||||
|
// Still mark as processed to avoid repeated checks
|
||||||
|
Meteor.call('boards.update', boardId, { $set: { fixDuplicateListsCompleted: true } });
|
||||||
|
} else {
|
||||||
|
// Still mark as processed to avoid repeated checks
|
||||||
|
Meteor.call('boards.update', boardId, { $set: { fixDuplicateListsCompleted: true } });
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fixing duplicate lists:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async startAttachmentMigrationIfNeeded(boardId) {
|
async startAttachmentMigrationIfNeeded(boardId) {
|
||||||
try {
|
try {
|
||||||
// Check if board has already been migrated
|
// Check if board has already been migrated
|
||||||
|
|
@ -1201,9 +1257,13 @@ BlazeComponent.extendComponent({
|
||||||
const firstSwimlane = currentBoard.swimlanes()[0];
|
const firstSwimlane = currentBoard.swimlanes()[0];
|
||||||
Meteor.call('createCardWithDueDate', currentBoard._id, firstList._id, myTitle, startDate.toDate(), firstSwimlane._id, function(error, result) {
|
Meteor.call('createCardWithDueDate', currentBoard._id, firstList._id, myTitle, startDate.toDate(), firstSwimlane._id, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.log(error);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("Card Created", result);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log("Card Created", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
|
||||||
|
|
@ -82,18 +82,26 @@ BlazeComponent.extendComponent({
|
||||||
},
|
},
|
||||||
'click .js-toggle-board-view': Popup.open('boardChangeView'),
|
'click .js-toggle-board-view': Popup.open('boardChangeView'),
|
||||||
'click .js-toggle-sidebar'() {
|
'click .js-toggle-sidebar'() {
|
||||||
console.log('Hamburger menu clicked');
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log('Hamburger menu clicked');
|
||||||
|
}
|
||||||
// Use the same approach as keyboard shortcuts
|
// Use the same approach as keyboard shortcuts
|
||||||
if (typeof Sidebar !== 'undefined' && Sidebar && typeof Sidebar.toggle === 'function') {
|
if (typeof Sidebar !== 'undefined' && Sidebar && typeof Sidebar.toggle === 'function') {
|
||||||
console.log('Using Sidebar.toggle()');
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log('Using Sidebar.toggle()');
|
||||||
|
}
|
||||||
Sidebar.toggle();
|
Sidebar.toggle();
|
||||||
} else {
|
} else {
|
||||||
console.warn('Sidebar not available, trying alternative approach');
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.warn('Sidebar not available, trying alternative approach');
|
||||||
|
}
|
||||||
// Try to trigger the sidebar through the global Blaze helper
|
// Try to trigger the sidebar through the global Blaze helper
|
||||||
if (typeof Blaze !== 'undefined' && Blaze._globalHelpers && Blaze._globalHelpers.Sidebar) {
|
if (typeof Blaze !== 'undefined' && Blaze._globalHelpers && Blaze._globalHelpers.Sidebar) {
|
||||||
const sidebar = Blaze._globalHelpers.Sidebar();
|
const sidebar = Blaze._globalHelpers.Sidebar();
|
||||||
if (sidebar && typeof sidebar.toggle === 'function') {
|
if (sidebar && typeof sidebar.toggle === 'function') {
|
||||||
console.log('Using Blaze helper Sidebar.toggle()');
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log('Using Blaze helper Sidebar.toggle()');
|
||||||
|
}
|
||||||
sidebar.toggle();
|
sidebar.toggle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,287 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standalone script to fix duplicate lists created by WeKan 8.10
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* node fix-duplicate-lists.js
|
|
||||||
*
|
|
||||||
* This script will:
|
|
||||||
* 1. Connect to the MongoDB database
|
|
||||||
* 2. Identify boards with duplicate lists/swimlanes
|
|
||||||
* 3. Fix the duplicates by merging them
|
|
||||||
* 4. Report the results
|
|
||||||
*/
|
|
||||||
|
|
||||||
const { MongoClient } = require('mongodb');
|
|
||||||
|
|
||||||
// Configuration - adjust these for your setup
|
|
||||||
const MONGO_URL = process.env.MONGO_URL || 'mongodb://localhost:27017/wekan';
|
|
||||||
const DB_NAME = process.env.MONGO_DB_NAME || 'wekan';
|
|
||||||
|
|
||||||
class DuplicateListsFixer {
|
|
||||||
constructor() {
|
|
||||||
this.client = null;
|
|
||||||
this.db = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async connect() {
|
|
||||||
console.log('Connecting to MongoDB...');
|
|
||||||
this.client = new MongoClient(MONGO_URL);
|
|
||||||
await this.client.connect();
|
|
||||||
this.db = this.client.db(DB_NAME);
|
|
||||||
console.log('Connected to MongoDB');
|
|
||||||
}
|
|
||||||
|
|
||||||
async disconnect() {
|
|
||||||
if (this.client) {
|
|
||||||
await this.client.close();
|
|
||||||
console.log('Disconnected from MongoDB');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getReport() {
|
|
||||||
console.log('Analyzing boards for duplicate lists...');
|
|
||||||
|
|
||||||
const boards = await this.db.collection('boards').find({}).toArray();
|
|
||||||
const report = [];
|
|
||||||
|
|
||||||
for (const board of boards) {
|
|
||||||
const swimlanes = await this.db.collection('swimlanes').find({ boardId: board._id }).toArray();
|
|
||||||
const lists = await this.db.collection('lists').find({ boardId: board._id }).toArray();
|
|
||||||
|
|
||||||
// Check for duplicate swimlanes
|
|
||||||
const swimlaneGroups = {};
|
|
||||||
swimlanes.forEach(swimlane => {
|
|
||||||
const key = swimlane.title || 'Default';
|
|
||||||
if (!swimlaneGroups[key]) {
|
|
||||||
swimlaneGroups[key] = [];
|
|
||||||
}
|
|
||||||
swimlaneGroups[key].push(swimlane);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check for duplicate lists
|
|
||||||
const listGroups = {};
|
|
||||||
lists.forEach(list => {
|
|
||||||
const key = `${list.swimlaneId || 'null'}-${list.title}`;
|
|
||||||
if (!listGroups[key]) {
|
|
||||||
listGroups[key] = [];
|
|
||||||
}
|
|
||||||
listGroups[key].push(list);
|
|
||||||
});
|
|
||||||
|
|
||||||
const duplicateSwimlanes = Object.values(swimlaneGroups).filter(group => group.length > 1);
|
|
||||||
const duplicateLists = Object.values(listGroups).filter(group => group.length > 1);
|
|
||||||
|
|
||||||
if (duplicateSwimlanes.length > 0 || duplicateLists.length > 0) {
|
|
||||||
report.push({
|
|
||||||
boardId: board._id,
|
|
||||||
boardTitle: board.title,
|
|
||||||
duplicateSwimlanes: duplicateSwimlanes.length,
|
|
||||||
duplicateLists: duplicateLists.length,
|
|
||||||
totalSwimlanes: swimlanes.length,
|
|
||||||
totalLists: lists.length
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
totalBoards: boards.length,
|
|
||||||
boardsWithDuplicates: report.length,
|
|
||||||
report
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async fixBoard(boardId) {
|
|
||||||
console.log(`Fixing duplicate lists for board ${boardId}...`);
|
|
||||||
|
|
||||||
// Fix duplicate swimlanes
|
|
||||||
const swimlaneResult = await this.fixDuplicateSwimlanes(boardId);
|
|
||||||
|
|
||||||
// Fix duplicate lists
|
|
||||||
const listResult = await this.fixDuplicateLists(boardId);
|
|
||||||
|
|
||||||
return {
|
|
||||||
boardId,
|
|
||||||
fixedSwimlanes: swimlaneResult.fixed,
|
|
||||||
fixedLists: listResult.fixed,
|
|
||||||
fixed: swimlaneResult.fixed + listResult.fixed
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async fixDuplicateSwimlanes(boardId) {
|
|
||||||
const swimlanes = await this.db.collection('swimlanes').find({ boardId }).toArray();
|
|
||||||
const swimlaneGroups = {};
|
|
||||||
let fixed = 0;
|
|
||||||
|
|
||||||
// Group swimlanes by title
|
|
||||||
swimlanes.forEach(swimlane => {
|
|
||||||
const key = swimlane.title || 'Default';
|
|
||||||
if (!swimlaneGroups[key]) {
|
|
||||||
swimlaneGroups[key] = [];
|
|
||||||
}
|
|
||||||
swimlaneGroups[key].push(swimlane);
|
|
||||||
});
|
|
||||||
|
|
||||||
// For each group with duplicates, keep the oldest and remove the rest
|
|
||||||
for (const [title, group] of Object.entries(swimlaneGroups)) {
|
|
||||||
if (group.length > 1) {
|
|
||||||
// Sort by creation date, keep the oldest
|
|
||||||
group.sort((a, b) => new Date(a.createdAt || 0) - new Date(b.createdAt || 0));
|
|
||||||
const keepSwimlane = group[0];
|
|
||||||
const removeSwimlanes = group.slice(1);
|
|
||||||
|
|
||||||
console.log(`Found ${group.length} duplicate swimlanes with title "${title}", keeping oldest (${keepSwimlane._id})`);
|
|
||||||
|
|
||||||
// Move all lists from duplicate swimlanes to the kept swimlane
|
|
||||||
for (const swimlane of removeSwimlanes) {
|
|
||||||
const lists = await this.db.collection('lists').find({ swimlaneId: swimlane._id }).toArray();
|
|
||||||
for (const list of lists) {
|
|
||||||
// Check if a list with the same title already exists in the kept swimlane
|
|
||||||
const existingList = await this.db.collection('lists').findOne({
|
|
||||||
boardId,
|
|
||||||
swimlaneId: keepSwimlane._id,
|
|
||||||
title: list.title
|
|
||||||
});
|
|
||||||
|
|
||||||
if (existingList) {
|
|
||||||
// Move cards to existing list
|
|
||||||
await this.db.collection('cards').updateMany(
|
|
||||||
{ listId: list._id },
|
|
||||||
{ $set: { listId: existingList._id } }
|
|
||||||
);
|
|
||||||
// Remove duplicate list
|
|
||||||
await this.db.collection('lists').deleteOne({ _id: list._id });
|
|
||||||
console.log(`Moved cards from duplicate list "${list.title}" to existing list in kept swimlane`);
|
|
||||||
} else {
|
|
||||||
// Move list to kept swimlane
|
|
||||||
await this.db.collection('lists').updateOne(
|
|
||||||
{ _id: list._id },
|
|
||||||
{ $set: { swimlaneId: keepSwimlane._id } }
|
|
||||||
);
|
|
||||||
console.log(`Moved list "${list.title}" to kept swimlane`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove duplicate swimlane
|
|
||||||
await this.db.collection('swimlanes').deleteOne({ _id: swimlane._id });
|
|
||||||
fixed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { fixed };
|
|
||||||
}
|
|
||||||
|
|
||||||
async fixDuplicateLists(boardId) {
|
|
||||||
const lists = await this.db.collection('lists').find({ boardId }).toArray();
|
|
||||||
const listGroups = {};
|
|
||||||
let fixed = 0;
|
|
||||||
|
|
||||||
// Group lists by title and swimlaneId
|
|
||||||
lists.forEach(list => {
|
|
||||||
const key = `${list.swimlaneId || 'null'}-${list.title}`;
|
|
||||||
if (!listGroups[key]) {
|
|
||||||
listGroups[key] = [];
|
|
||||||
}
|
|
||||||
listGroups[key].push(list);
|
|
||||||
});
|
|
||||||
|
|
||||||
// For each group with duplicates, keep the oldest and remove the rest
|
|
||||||
for (const [key, group] of Object.entries(listGroups)) {
|
|
||||||
if (group.length > 1) {
|
|
||||||
// Sort by creation date, keep the oldest
|
|
||||||
group.sort((a, b) => new Date(a.createdAt || 0) - new Date(b.createdAt || 0));
|
|
||||||
const keepList = group[0];
|
|
||||||
const removeLists = group.slice(1);
|
|
||||||
|
|
||||||
console.log(`Found ${group.length} duplicate lists with title "${keepList.title}" in swimlane ${keepList.swimlaneId}, keeping oldest (${keepList._id})`);
|
|
||||||
|
|
||||||
// Move all cards from duplicate lists to the kept list
|
|
||||||
for (const list of removeLists) {
|
|
||||||
await this.db.collection('cards').updateMany(
|
|
||||||
{ listId: list._id },
|
|
||||||
{ $set: { listId: keepList._id } }
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove duplicate list
|
|
||||||
await this.db.collection('lists').deleteOne({ _id: list._id });
|
|
||||||
fixed++;
|
|
||||||
console.log(`Moved cards from duplicate list "${list.title}" to kept list`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { fixed };
|
|
||||||
}
|
|
||||||
|
|
||||||
async fixAllBoards() {
|
|
||||||
console.log('Starting duplicate lists fix for all boards...');
|
|
||||||
|
|
||||||
const allBoards = await this.db.collection('boards').find({}).toArray();
|
|
||||||
let totalFixed = 0;
|
|
||||||
let totalBoardsProcessed = 0;
|
|
||||||
|
|
||||||
for (const board of allBoards) {
|
|
||||||
try {
|
|
||||||
const result = await this.fixBoard(board._id);
|
|
||||||
totalFixed += result.fixed;
|
|
||||||
totalBoardsProcessed++;
|
|
||||||
|
|
||||||
if (result.fixed > 0) {
|
|
||||||
console.log(`Fixed ${result.fixed} duplicate lists in board "${board.title}" (${board._id})`);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error fixing board ${board._id}:`, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Duplicate lists fix completed. Processed ${totalBoardsProcessed} boards, fixed ${totalFixed} duplicate lists.`);
|
|
||||||
|
|
||||||
return {
|
|
||||||
message: `Fixed ${totalFixed} duplicate lists across ${totalBoardsProcessed} boards`,
|
|
||||||
totalFixed,
|
|
||||||
totalBoardsProcessed
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main execution
|
|
||||||
async function main() {
|
|
||||||
const fixer = new DuplicateListsFixer();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await fixer.connect();
|
|
||||||
|
|
||||||
// Get report first
|
|
||||||
const report = await fixer.getReport();
|
|
||||||
|
|
||||||
if (report.boardsWithDuplicates === 0) {
|
|
||||||
console.log('No duplicate lists found!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Found ${report.boardsWithDuplicates} boards with duplicate lists:`);
|
|
||||||
report.report.forEach(board => {
|
|
||||||
console.log(`- Board "${board.boardTitle}" (${board.boardId}): ${board.duplicateSwimlanes} duplicate swimlanes, ${board.duplicateLists} duplicate lists`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Perform the fix
|
|
||||||
const result = await fixer.fixAllBoards();
|
|
||||||
console.log('Fix completed:', result);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error:', error);
|
|
||||||
process.exit(1);
|
|
||||||
} finally {
|
|
||||||
await fixer.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run if called directly
|
|
||||||
if (require.main === module) {
|
|
||||||
main();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = DuplicateListsFixer;
|
|
||||||
|
|
||||||
|
|
@ -15,7 +15,9 @@ Meteor.methods({
|
||||||
throw new Meteor.Error('not-authorized');
|
throw new Meteor.Error('not-authorized');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Starting duplicate lists fix for all boards...');
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log('Starting duplicate lists fix for all boards...');
|
||||||
|
}
|
||||||
|
|
||||||
const allBoards = Boards.find({}).fetch();
|
const allBoards = Boards.find({}).fetch();
|
||||||
let totalFixed = 0;
|
let totalFixed = 0;
|
||||||
|
|
@ -27,7 +29,7 @@ Meteor.methods({
|
||||||
totalFixed += result.fixed;
|
totalFixed += result.fixed;
|
||||||
totalBoardsProcessed++;
|
totalBoardsProcessed++;
|
||||||
|
|
||||||
if (result.fixed > 0) {
|
if (result.fixed > 0 && process.env.DEBUG === 'true') {
|
||||||
console.log(`Fixed ${result.fixed} duplicate lists in board "${board.title}" (${board._id})`);
|
console.log(`Fixed ${result.fixed} duplicate lists in board "${board.title}" (${board._id})`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -35,7 +37,9 @@ Meteor.methods({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Duplicate lists fix completed. Processed ${totalBoardsProcessed} boards, fixed ${totalFixed} duplicate lists.`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Duplicate lists fix completed. Processed ${totalBoardsProcessed} boards, fixed ${totalFixed} duplicate lists.`);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: `Fixed ${totalFixed} duplicate lists across ${totalBoardsProcessed} boards`,
|
message: `Fixed ${totalFixed} duplicate lists across ${totalBoardsProcessed} boards`,
|
||||||
|
|
@ -55,7 +59,9 @@ Meteor.methods({
|
||||||
},
|
},
|
||||||
|
|
||||||
fixDuplicateListsForBoard(boardId) {
|
fixDuplicateListsForBoard(boardId) {
|
||||||
console.log(`Fixing duplicate lists for board ${boardId}...`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Fixing duplicate lists for board ${boardId}...`);
|
||||||
|
}
|
||||||
|
|
||||||
// First, fix duplicate swimlanes
|
// First, fix duplicate swimlanes
|
||||||
const swimlaneResult = this.fixDuplicateSwimlanes(boardId);
|
const swimlaneResult = this.fixDuplicateSwimlanes(boardId);
|
||||||
|
|
@ -94,7 +100,9 @@ Meteor.methods({
|
||||||
const keepSwimlane = group[0];
|
const keepSwimlane = group[0];
|
||||||
const removeSwimlanes = group.slice(1);
|
const removeSwimlanes = group.slice(1);
|
||||||
|
|
||||||
console.log(`Found ${group.length} duplicate swimlanes with title "${title}", keeping oldest (${keepSwimlane._id})`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Found ${group.length} duplicate swimlanes with title "${title}", keeping oldest (${keepSwimlane._id})`);
|
||||||
|
}
|
||||||
|
|
||||||
// Move all lists from duplicate swimlanes to the kept swimlane
|
// Move all lists from duplicate swimlanes to the kept swimlane
|
||||||
removeSwimlanes.forEach(swimlane => {
|
removeSwimlanes.forEach(swimlane => {
|
||||||
|
|
@ -116,11 +124,15 @@ Meteor.methods({
|
||||||
);
|
);
|
||||||
// Remove duplicate list
|
// Remove duplicate list
|
||||||
Lists.remove(list._id);
|
Lists.remove(list._id);
|
||||||
console.log(`Moved cards from duplicate list "${list.title}" to existing list in kept swimlane`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Moved cards from duplicate list "${list.title}" to existing list in kept swimlane`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Move list to kept swimlane
|
// Move list to kept swimlane
|
||||||
Lists.update(list._id, { $set: { swimlaneId: keepSwimlane._id } });
|
Lists.update(list._id, { $set: { swimlaneId: keepSwimlane._id } });
|
||||||
console.log(`Moved list "${list.title}" to kept swimlane`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Moved list "${list.title}" to kept swimlane`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -157,7 +169,9 @@ Meteor.methods({
|
||||||
const keepList = group[0];
|
const keepList = group[0];
|
||||||
const removeLists = group.slice(1);
|
const removeLists = group.slice(1);
|
||||||
|
|
||||||
console.log(`Found ${group.length} duplicate lists with title "${keepList.title}" in swimlane ${keepList.swimlaneId}, keeping oldest (${keepList._id})`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Found ${group.length} duplicate lists with title "${keepList.title}" in swimlane ${keepList.swimlaneId}, keeping oldest (${keepList._id})`);
|
||||||
|
}
|
||||||
|
|
||||||
// Move all cards from duplicate lists to the kept list
|
// Move all cards from duplicate lists to the kept list
|
||||||
removeLists.forEach(list => {
|
removeLists.forEach(list => {
|
||||||
|
|
@ -170,7 +184,9 @@ Meteor.methods({
|
||||||
// Remove duplicate list
|
// Remove duplicate list
|
||||||
Lists.remove(list._id);
|
Lists.remove(list._id);
|
||||||
fixed++;
|
fixed++;
|
||||||
console.log(`Moved cards from duplicate list "${list.title}" to kept list`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Moved cards from duplicate list "${list.title}" to kept list`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,9 @@ class FixMissingListsMigration {
|
||||||
for (const card of cards) {
|
for (const card of cards) {
|
||||||
const expectedSwimlaneId = listSwimlaneMap.get(card.listId);
|
const expectedSwimlaneId = listSwimlaneMap.get(card.listId);
|
||||||
if (expectedSwimlaneId && expectedSwimlaneId !== card.swimlaneId) {
|
if (expectedSwimlaneId && expectedSwimlaneId !== card.swimlaneId) {
|
||||||
console.log(`Found mismatched card: ${card._id}, listId: ${card.listId}, card swimlaneId: ${card.swimlaneId}, list swimlaneId: ${expectedSwimlaneId}`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Found mismatched card: ${card._id}, listId: ${card.listId}, card swimlaneId: ${card.swimlaneId}, list swimlaneId: ${expectedSwimlaneId}`);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +74,9 @@ class FixMissingListsMigration {
|
||||||
*/
|
*/
|
||||||
async executeMigration(boardId) {
|
async executeMigration(boardId) {
|
||||||
try {
|
try {
|
||||||
console.log(`Starting fix missing lists migration for board ${boardId}`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Starting fix missing lists migration for board ${boardId}`);
|
||||||
|
}
|
||||||
|
|
||||||
const board = ReactiveCache.getBoard(boardId);
|
const board = ReactiveCache.getBoard(boardId);
|
||||||
if (!board) {
|
if (!board) {
|
||||||
|
|
@ -165,7 +169,9 @@ class FixMissingListsMigration {
|
||||||
targetList = { _id: newListId, ...newListData };
|
targetList = { _id: newListId, ...newListData };
|
||||||
createdLists++;
|
createdLists++;
|
||||||
|
|
||||||
console.log(`Created new list "${originalList.title}" for swimlane ${swimlaneId}`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Created new list "${originalList.title}" for swimlane ${swimlaneId}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update all cards in this group to use the correct listId
|
// Update all cards in this group to use the correct listId
|
||||||
|
|
@ -189,7 +195,9 @@ class FixMissingListsMigration {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`Fix missing lists migration completed for board ${boardId}: created ${createdLists} lists, updated ${updatedCards} cards`);
|
if (process.env.DEBUG === 'true') {
|
||||||
|
console.log(`Fix missing lists migration completed for board ${boardId}: created ${createdLists} lists, updated ${updatedCards} cards`);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue