Reverted New UI Design of WeKan v8.29 and added more fixes and performance improvements.

Thanks to xet7 !
This commit is contained in:
Lauri Ojansivu 2026-02-08 00:48:39 +02:00
parent d152d8fc1b
commit 1b8b8d2eef
196 changed files with 17659 additions and 10028 deletions

View file

@ -23,7 +23,7 @@ Meteor.methods({
if (process.env.DEBUG === 'true') {
console.log('Starting duplicate lists fix for all boards...');
}
const allBoards = Boards.find({}).fetch();
let totalFixed = 0;
let totalBoardsProcessed = 0;
@ -33,7 +33,7 @@ Meteor.methods({
const result = fixDuplicateListsForBoard(board._id);
totalFixed += result.fixed;
totalBoardsProcessed++;
if (result.fixed > 0 && process.env.DEBUG === 'true') {
console.log(`Fixed ${result.fixed} duplicate lists in board "${board.title}" (${board._id})`);
}
@ -45,7 +45,7 @@ Meteor.methods({
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`,
totalFixed,
@ -55,7 +55,7 @@ Meteor.methods({
'fixDuplicateLists.fixBoard'(boardId) {
check(boardId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized');
}
@ -74,13 +74,13 @@ function fixDuplicateListsForBoard(boardId) {
if (process.env.DEBUG === 'true') {
console.log(`Fixing duplicate lists for board ${boardId}...`);
}
// First, fix duplicate swimlanes
const swimlaneResult = fixDuplicateSwimlanes(boardId);
// Then, fix duplicate lists
const listResult = fixDuplicateLists(boardId);
return {
boardId,
fixedSwimlanes: swimlaneResult.fixed,
@ -193,7 +193,7 @@ function fixDuplicateLists(boardId) {
{ $set: { listId: keepList._id } },
{ multi: true }
);
// Remove duplicate list
Lists.remove(list._id);
fixed++;
@ -223,7 +223,7 @@ Meteor.methods({
for (const board of allBoards) {
const swimlanes = Swimlanes.find({ boardId: board._id }).fetch();
const lists = Lists.find({ boardId: board._id }).fetch();
// Check for duplicate swimlanes
const swimlaneGroups = {};
swimlanes.forEach(swimlane => {

View file

@ -15,21 +15,21 @@ Meteor.methods({
*/
'positionHistory.trackSwimlane'(swimlaneId) {
check(swimlaneId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const swimlane = Swimlanes.findOne(swimlaneId);
if (!swimlane) {
throw new Meteor.Error('swimlane-not-found', 'Swimlane not found');
}
const board = ReactiveCache.getBoard(swimlane.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return swimlane.trackOriginalPosition();
},
@ -38,21 +38,21 @@ Meteor.methods({
*/
'positionHistory.trackList'(listId) {
check(listId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const list = Lists.findOne(listId);
if (!list) {
throw new Meteor.Error('list-not-found', 'List not found');
}
const board = ReactiveCache.getBoard(list.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return list.trackOriginalPosition();
},
@ -61,21 +61,21 @@ Meteor.methods({
*/
'positionHistory.trackCard'(cardId) {
check(cardId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const card = Cards.findOne(cardId);
if (!card) {
throw new Meteor.Error('card-not-found', 'Card not found');
}
const board = ReactiveCache.getBoard(card.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return card.trackOriginalPosition();
},
@ -84,21 +84,21 @@ Meteor.methods({
*/
'positionHistory.getSwimlaneOriginalPosition'(swimlaneId) {
check(swimlaneId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const swimlane = Swimlanes.findOne(swimlaneId);
if (!swimlane) {
throw new Meteor.Error('swimlane-not-found', 'Swimlane not found');
}
const board = ReactiveCache.getBoard(swimlane.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return swimlane.getOriginalPosition();
},
@ -107,21 +107,21 @@ Meteor.methods({
*/
'positionHistory.getListOriginalPosition'(listId) {
check(listId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const list = Lists.findOne(listId);
if (!list) {
throw new Meteor.Error('list-not-found', 'List not found');
}
const board = ReactiveCache.getBoard(list.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return list.getOriginalPosition();
},
@ -130,21 +130,21 @@ Meteor.methods({
*/
'positionHistory.getCardOriginalPosition'(cardId) {
check(cardId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const card = Cards.findOne(cardId);
if (!card) {
throw new Meteor.Error('card-not-found', 'Card not found');
}
const board = ReactiveCache.getBoard(card.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return card.getOriginalPosition();
},
@ -153,21 +153,21 @@ Meteor.methods({
*/
'positionHistory.hasSwimlaneMoved'(swimlaneId) {
check(swimlaneId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const swimlane = Swimlanes.findOne(swimlaneId);
if (!swimlane) {
throw new Meteor.Error('swimlane-not-found', 'Swimlane not found');
}
const board = ReactiveCache.getBoard(swimlane.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return swimlane.hasMovedFromOriginalPosition();
},
@ -176,21 +176,21 @@ Meteor.methods({
*/
'positionHistory.hasListMoved'(listId) {
check(listId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const list = Lists.findOne(listId);
if (!list) {
throw new Meteor.Error('list-not-found', 'List not found');
}
const board = ReactiveCache.getBoard(list.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return list.hasMovedFromOriginalPosition();
},
@ -199,21 +199,21 @@ Meteor.methods({
*/
'positionHistory.hasCardMoved'(cardId) {
check(cardId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const card = Cards.findOne(cardId);
if (!card) {
throw new Meteor.Error('card-not-found', 'Card not found');
}
const board = ReactiveCache.getBoard(card.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return card.hasMovedFromOriginalPosition();
},
@ -222,21 +222,21 @@ Meteor.methods({
*/
'positionHistory.getSwimlaneDescription'(swimlaneId) {
check(swimlaneId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const swimlane = Swimlanes.findOne(swimlaneId);
if (!swimlane) {
throw new Meteor.Error('swimlane-not-found', 'Swimlane not found');
}
const board = ReactiveCache.getBoard(swimlane.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return swimlane.getOriginalPositionDescription();
},
@ -245,21 +245,21 @@ Meteor.methods({
*/
'positionHistory.getListDescription'(listId) {
check(listId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const list = Lists.findOne(listId);
if (!list) {
throw new Meteor.Error('list-not-found', 'List not found');
}
const board = ReactiveCache.getBoard(list.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return list.getOriginalPositionDescription();
},
@ -268,21 +268,21 @@ Meteor.methods({
*/
'positionHistory.getCardDescription'(cardId) {
check(cardId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const card = Cards.findOne(cardId);
if (!card) {
throw new Meteor.Error('card-not-found', 'Card not found');
}
const board = ReactiveCache.getBoard(card.boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return card.getOriginalPositionDescription();
},
@ -291,16 +291,16 @@ Meteor.methods({
*/
'positionHistory.getBoardHistory'(boardId) {
check(boardId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const board = ReactiveCache.getBoard(boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
return PositionHistory.find({
boardId: boardId,
}, {
@ -314,20 +314,20 @@ Meteor.methods({
'positionHistory.getBoardHistoryByType'(boardId, entityType) {
check(boardId, String);
check(entityType, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'You must be logged in.');
}
const board = ReactiveCache.getBoard(boardId);
if (!board || !board.isVisibleBy({ _id: this.userId })) {
throw new Meteor.Error('not-authorized', 'You do not have access to this board.');
}
if (!['swimlane', 'list', 'card'].includes(entityType)) {
throw new Meteor.Error('invalid-entity-type', 'Entity type must be swimlane, list, or card');
}
return PositionHistory.find({
boardId: boardId,
entityType: entityType,