Browse Source

Fix duplicated lists and do not show debug messages when env DEBUG is not true. Part 3.

Thanks to xet7 !

Fixes #5952
Lauri Ojansivu 1 day ago
parent
commit
58df525b49

+ 64 - 4
client/components/boards/boardBody.js

@@ -63,7 +63,9 @@ BlazeComponent.extendComponent({
             title: 'Default',
             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);
       } else {
@@ -123,6 +125,9 @@ BlazeComponent.extendComponent({
       // Fix missing lists migration (for cards with wrong listId references)
       await this.fixMissingLists(boardId);
 
+      // Fix duplicate lists created by WeKan 8.10
+      await this.fixDuplicateLists(boardId);
+
       // Start attachment migration in background if needed
       this.startAttachmentMigrationIfNeeded(boardId);
     } catch (error) {
@@ -312,7 +317,9 @@ BlazeComponent.extendComponent({
       });
 
       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) {
@@ -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) {
     try {
       // Check if board has already been migrated
@@ -1201,9 +1257,13 @@ BlazeComponent.extendComponent({
             const firstSwimlane = currentBoard.swimlanes()[0];
             Meteor.call('createCardWithDueDate', currentBoard._id, firstList._id, myTitle, startDate.toDate(), firstSwimlane._id, function(error, result) {
               if (error) {
-                console.log(error);
+                if (process.env.DEBUG === 'true') {
+                  console.log(error);
+                }
               } else {
-                console.log("Card Created", result);
+                if (process.env.DEBUG === 'true') {
+                  console.log("Card Created", result);
+                }
               }
             });
             closeModal();

+ 12 - 4
client/components/boards/boardHeader.js

@@ -82,18 +82,26 @@ BlazeComponent.extendComponent({
         },
         'click .js-toggle-board-view': Popup.open('boardChangeView'),
         '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
           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();
           } 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
             if (typeof Blaze !== 'undefined' && Blaze._globalHelpers && Blaze._globalHelpers.Sidebar) {
               const sidebar = Blaze._globalHelpers.Sidebar();
               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();
               }
             }

+ 0 - 287
fix-duplicate-lists.js

@@ -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;
-

+ 25 - 9
server/methods/fixDuplicateLists.js

@@ -15,7 +15,9 @@ Meteor.methods({
       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();
     let totalFixed = 0;
@@ -27,7 +29,7 @@ Meteor.methods({
         totalFixed += result.fixed;
         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})`);
         }
       } 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 {
       message: `Fixed ${totalFixed} duplicate lists across ${totalBoardsProcessed} boards`,
@@ -55,7 +59,9 @@ Meteor.methods({
   },
 
   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
     const swimlaneResult = this.fixDuplicateSwimlanes(boardId);
@@ -94,7 +100,9 @@ Meteor.methods({
         const keepSwimlane = group[0];
         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
         removeSwimlanes.forEach(swimlane => {
@@ -116,11 +124,15 @@ Meteor.methods({
               );
               // Remove duplicate list
               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 {
               // Move list to kept swimlane
               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 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
         removeLists.forEach(list => {
@@ -170,7 +184,9 @@ Meteor.methods({
           // Remove duplicate list
           Lists.remove(list._id);
           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`);
+          }
         });
       }
     });

+ 12 - 4
server/migrations/fixMissingListsMigration.js

@@ -55,7 +55,9 @@ class FixMissingListsMigration {
       for (const card of cards) {
         const expectedSwimlaneId = listSwimlaneMap.get(card.listId);
         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;
         }
       }
@@ -72,7 +74,9 @@ class FixMissingListsMigration {
    */
   async executeMigration(boardId) {
     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);
       if (!board) {
@@ -165,7 +169,9 @@ class FixMissingListsMigration {
             targetList = { _id: newListId, ...newListData };
             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
@@ -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 {
         success: true,