소스 검색

At Public Board, drag resize list width and swimlane height. For logged in users, fix adding labels.

Thanks to xet7 !

Fixes #5922
Lauri Ojansivu 4 일 전
부모
커밋
3514335247

+ 2 - 1
CHANGELOG.md

@@ -34,7 +34,8 @@ This release fixes the following bugs:
 - [Fix unable to see My Due Cards](https://github.com/wekan/wekan/commit/66b444e2b0c9b2ed5f98cd1ff0cd9222b2d0c624).
   Thanks to xet7.
 - Fix drag drop lists.
-  [Part 1](https://github.com/wekan/wekan/commit/324f3f7794aace800022a24deb5fd5fb36ebd384).
+  [Part 1](https://github.com/wekan/wekan/commit/324f3f7794aace800022a24deb5fd5fb36ebd384),
+  [Part 2](https://github.com/wekan/wekan/commit/ff516ec696ef499f11b04b30053eeb9d3f96d8d1).
   Thanks to xet7.
 - [Removed extra pipe characters](https://github.com/wekan/wekan/commit/caa6e615ff3c3681bf2b470a625eb39c6009b825).
   Thanks to xet7.

+ 6 - 1
client/components/cards/cardCustomFields.js

@@ -168,7 +168,12 @@ CardCustomField.register('cardCustomField');
   }
 
   showWeekOfYear() {
-    return ReactiveCache.getCurrentUser().isShowWeekOfYear();
+    const user = ReactiveCache.getCurrentUser();
+    if (!user) {
+      // For non-logged-in users, week of year is not shown
+      return false;
+    }
+    return user.isShowWeekOfYear();
   }
 
   showDate() {

+ 12 - 2
client/components/cards/cardDate.js

@@ -131,7 +131,12 @@ const CardDate = BlazeComponent.extendComponent({
   },
 
   showWeekOfYear() {
-    return ReactiveCache.getCurrentUser().isShowWeekOfYear();
+    const user = ReactiveCache.getCurrentUser();
+    if (!user) {
+      // For non-logged-in users, week of year is not shown
+      return false;
+    }
+    return user.isShowWeekOfYear();
   },
 
   showDate() {
@@ -301,7 +306,12 @@ class CardCustomFieldDate extends CardDate {
   }
 
   showWeekOfYear() {
-    return ReactiveCache.getCurrentUser().isShowWeekOfYear();
+    const user = ReactiveCache.getCurrentUser();
+    if (!user) {
+      // For non-logged-in users, week of year is not shown
+      return false;
+    }
+    return user.isShowWeekOfYear();
   }
 
   showDate() {

+ 26 - 4
client/components/cards/labels.js

@@ -125,8 +125,19 @@ Template.createLabelPopup.events({
       .$('#labelName')
       .val()
       .trim();
-    const color = Blaze.getData(templateInstance.find('.fa-check')).color;
-    board.addLabel(name, color);
+    
+    // Find the selected color by looking for the palette color that contains the checkmark
+    let selectedColor = null;
+    templateInstance.$('.js-palette-color').each(function() {
+      if ($(this).text().includes('✅')) {
+        selectedColor = Blaze.getData(this).color;
+        return false; // break out of loop
+      }
+    });
+    
+    if (selectedColor) {
+      board.addLabel(name, selectedColor);
+    }
     Popup.back();
   },
 });
@@ -144,8 +155,19 @@ Template.editLabelPopup.events({
       .$('#labelName')
       .val()
       .trim();
-    const color = Blaze.getData(templateInstance.find('.fa-check')).color;
-    board.editLabel(this._id, name, color);
+    
+    // Find the selected color by looking for the palette color that contains the checkmark
+    let selectedColor = null;
+    templateInstance.$('.js-palette-color').each(function() {
+      if ($(this).text().includes('✅')) {
+        selectedColor = Blaze.getData(this).color;
+        return false; // break out of loop
+      }
+    });
+    
+    if (selectedColor) {
+      board.editLabel(this._id, name, selectedColor);
+    }
     Popup.back();
   },
 });

+ 84 - 9
client/components/lists/list.js

@@ -197,20 +197,60 @@ BlazeComponent.extendComponent({
   listWidth() {
     const user = ReactiveCache.getCurrentUser();
     const list = Template.currentData();
-    if (!user || !list) return 270; // Return default width if user or list is not available
-    return user.getListWidthFromStorage(list.boardId, list._id);
+    if (!list) return 270; // Return default width if list is not available
+    
+    if (user) {
+      // For logged-in users, get from user profile
+      return user.getListWidthFromStorage(list.boardId, list._id);
+    } else {
+      // For non-logged-in users, get from localStorage
+      try {
+        const stored = localStorage.getItem('wekan-list-widths');
+        if (stored) {
+          const widths = JSON.parse(stored);
+          if (widths[list.boardId] && widths[list.boardId][list._id]) {
+            return widths[list.boardId][list._id];
+          }
+        }
+      } catch (e) {
+        console.warn('Error reading list width from localStorage:', e);
+      }
+      return 270; // Return default width if not found
+    }
   },
 
   listConstraint() {
     const user = ReactiveCache.getCurrentUser();
     const list = Template.currentData();
-    if (!user || !list) return 550; // Return default constraint if user or list is not available
-    return user.getListConstraintFromStorage(list.boardId, list._id);
+    if (!list) return 550; // Return default constraint if list is not available
+    
+    if (user) {
+      // For logged-in users, get from user profile
+      return user.getListConstraintFromStorage(list.boardId, list._id);
+    } else {
+      // For non-logged-in users, get from localStorage
+      try {
+        const stored = localStorage.getItem('wekan-list-constraints');
+        if (stored) {
+          const constraints = JSON.parse(stored);
+          if (constraints[list.boardId] && constraints[list.boardId][list._id]) {
+            return constraints[list.boardId][list._id];
+          }
+        }
+      } catch (e) {
+        console.warn('Error reading list constraint from localStorage:', e);
+      }
+      return 550; // Return default constraint if not found
+    }
   },
 
   autoWidth() {
     const user = ReactiveCache.getCurrentUser();
     const list = Template.currentData();
+    if (!user) {
+      // For non-logged-in users, auto-width is disabled
+      return false;
+    }
     return user.isAutoWidth(list.boardId);
   },
 
@@ -329,14 +369,49 @@ BlazeComponent.extendComponent({
       // Use the new storage method that handles both logged-in and non-logged-in users
       if (process.env.DEBUG === 'true') {
       }
-      Meteor.call('applyListWidthToStorage', boardId, listId, finalWidth, listConstraint, (error, result) => {
-        if (error) {
-          console.error('Error saving list width:', error);
-        } else {
+      
+      const currentUser = ReactiveCache.getCurrentUser();
+      if (currentUser) {
+        // For logged-in users, use server method
+        Meteor.call('applyListWidthToStorage', boardId, listId, finalWidth, listConstraint, (error, result) => {
+          if (error) {
+            console.error('Error saving list width:', error);
+          } else {
+            if (process.env.DEBUG === 'true') {
+            }
+          }
+        });
+      } else {
+        // For non-logged-in users, save to localStorage directly
+        try {
+          // Save list width
+          const storedWidths = localStorage.getItem('wekan-list-widths');
+          let widths = storedWidths ? JSON.parse(storedWidths) : {};
+          
+          if (!widths[boardId]) {
+            widths[boardId] = {};
+          }
+          widths[boardId][listId] = finalWidth;
+          
+          localStorage.setItem('wekan-list-widths', JSON.stringify(widths));
+          
+          // Save list constraint
+          const storedConstraints = localStorage.getItem('wekan-list-constraints');
+          let constraints = storedConstraints ? JSON.parse(storedConstraints) : {};
+          
+          if (!constraints[boardId]) {
+            constraints[boardId] = {};
+          }
+          constraints[boardId][listId] = listConstraint;
+          
+          localStorage.setItem('wekan-list-constraints', JSON.stringify(constraints));
+          
           if (process.env.DEBUG === 'true') {
           }
+        } catch (e) {
+          console.warn('Error saving list width/constraint to localStorage:', e);
         }
-      });
+      }
       
       e.preventDefault();
     };

+ 1 - 0
client/components/main/header.css

@@ -220,6 +220,7 @@
   margin: 0;
   margin-top: 1px;
 }
+
 #header-quick-access #header-user-bar .header-user-bar-name,
 #header-quick-access #header-help  {
   margin: 4px 8px 0 0;

+ 6 - 6
client/components/sidebar/sidebar.jade

@@ -28,7 +28,6 @@ template(name="sidebar")
         +Template.dynamic(template=getViewTemplate)
 
 template(name='homeSidebar')
-  hr
   +membersWidget
   hr
   +labelsWidget
@@ -38,11 +37,12 @@ template(name='homeSidebar')
       span {{_ 'hide-minicard-label-text'}}
       b  
       .materialCheckBox(class="{{#if hiddenMinicardLabelText}}is-checked{{/if}}")
-  ul#cards.vertical-scrollbars-toggle
-    a.flex.js-vertical-scrollbars-toggle(title="{{_ 'enable-vertical-scrollbars'}}")
-      span {{_ 'enable-vertical-scrollbars'}}
-      b  
-      .materialCheckBox(class="{{#if isVerticalScrollbars}}is-checked{{/if}}")
+  if currentUser
+    ul#cards.vertical-scrollbars-toggle
+      a.flex.js-vertical-scrollbars-toggle(title="{{_ 'enable-vertical-scrollbars'}}")
+        span {{_ 'enable-vertical-scrollbars'}}
+        b  
+        .materialCheckBox(class="{{#if isVerticalScrollbars}}is-checked{{/if}}")
   ul#cards.show-week-of-year-toggle
     a.flex.js-show-week-of-year-toggle(title="{{_ 'show-week-of-year'}}")
       span {{_ 'show-week-of-year'}}

+ 2 - 0
client/components/sidebar/sidebar.js

@@ -203,6 +203,8 @@ BlazeComponent.extendComponent({
   },
 }).register('homeSidebar');
 
+
+
 Template.boardInfoOnMyBoardsPopup.helpers({
   hideCardCounterList() {
     return Utils.isMiniScreen() && Session.get('currentBoard');

+ 59 - 56
client/components/swimlanes/swimlaneHeader.jade

@@ -23,26 +23,27 @@ template(name="swimlaneFixedHeader")
         +viewer
           | {{isTitleDefault title}}
   .swimlane-header-menu
-    unless currentUser.isCommentOnly
-      a.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}")
-        | ➕
-      a.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}")
-        | ☰
-      //// TODO: Collapse Swimlane: make button working, etc.
-      //unless collapsed
-      //  a.js-collapse-swimlane(title="{{_ 'collapse'}}")
-      //    i.fa.fa-arrow-down.swimlane-header-collapse-down
-      //    ⬆️.swimlane-header-collapse-up
-      //if collapsed
-      //  a.js-collapse-swimlane(title="{{_ 'uncollapse'}}")
-      //    ⬆️.swimlane-header-collapse-up
-      //    i.fa.fa-arrow-down.swimlane-header-collapse-down
-      unless isTouchScreen
-        a.swimlane-header-handle.handle.js-swimlane-header-handle
-          | ↕️
-      if isTouchScreen
-        a.swimlane-header-miniscreen-handle.handle.js-swimlane-header-handle
-          | ↕️
+    if currentUser
+      unless currentUser.isCommentOnly
+        a.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}")
+          | ➕
+        a.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}")
+          | ☰
+        //// TODO: Collapse Swimlane: make button working, etc.
+        //unless collapsed
+        //  a.js-collapse-swimlane(title="{{_ 'collapse'}}")
+        //    i.fa.fa-arrow-down.swimlane-header-collapse-down
+        //    ⬆️.swimlane-header-collapse-up
+        //if collapsed
+        //  a.js-collapse-swimlane(title="{{_ 'uncollapse'}}")
+        //    ⬆️.swimlane-header-collapse-up
+        //    i.fa.fa-arrow-down.swimlane-header-collapse-down
+        unless isTouchScreen
+          a.swimlane-header-handle.handle.js-swimlane-header-handle
+            | ↕️
+        if isTouchScreen
+          a.swimlane-header-miniscreen-handle.handle.js-swimlane-header-handle
+            | ↕️
 
 template(name="editSwimlaneTitleForm")
   .list-composer
@@ -53,44 +54,46 @@ template(name="editSwimlaneTitleForm")
         | ❌
 
 template(name="swimlaneActionPopup")
-  unless currentUser.isCommentOnly
-    ul.pop-over-list
-       if currentUser.isBoardAdmin
-         li: a.js-set-swimlane-color
-          | 🎨
-          | {{_ 'select-color'}}
-       li: a.js-set-swimlane-height
-        | ↕️
-        |  {{_ 'set-swimlane-height'}}
-    if currentUser.isBoardAdmin
-      unless this.isTemplateContainer
-        hr
-        ul.pop-over-list
-          li: a.js-close-swimlane
-            | ▶️
-            | 📦
-            | {{_ 'archive-swimlane'}}
-        ul.pop-over-list
-          li: a.js-copy-swimlane
-            | 📋
-            | {{_ 'copy-swimlane'}}
-        ul.pop-over-list
-          li: a.js-move-swimlane
-            | ⬆️
-            | {{_ 'move-swimlane'}}
+  if currentUser
+    unless currentUser.isCommentOnly
+      ul.pop-over-list
+         if currentUser.isBoardAdmin
+           li: a.js-set-swimlane-color
+             | 🎨
+             | {{_ 'select-color'}}
+         li: a.js-set-swimlane-height
+           | ↕️
+           |  {{_ 'set-swimlane-height'}}
+      if currentUser.isBoardAdmin
+        unless this.isTemplateContainer
+          hr
+          ul.pop-over-list
+            li: a.js-close-swimlane
+              | ▶️
+              | 📦
+              | {{_ 'archive-swimlane'}}
+          ul.pop-over-list
+            li: a.js-copy-swimlane
+              | 📋
+              | {{_ 'copy-swimlane'}}
+          ul.pop-over-list
+            li: a.js-move-swimlane
+              | ⬆️
+              | {{_ 'move-swimlane'}}
 
 template(name="swimlaneAddPopup")
-  unless currentUser.isCommentOnly
-    form
-      input.swimlane-name-input.full-line(type="text" placeholder="{{_ 'add-swimlane'}}"
-        autocomplete="off" autofocus)
-      .edit-controls.clearfix
-        button.primary.confirm(type="submit") {{_ 'add'}}
-        unless currentBoard.isTemplatesBoard
-          unless currentBoard.isTemplateBoard
-            span.quiet
-              | {{_ 'or'}}
-              a.js-swimlane-template {{_ 'template'}}
+  if currentUser
+    unless currentUser.isCommentOnly
+      form
+        input.swimlane-name-input.full-line(type="text" placeholder="{{_ 'add-swimlane'}}"
+          autocomplete="off" autofocus)
+        .edit-controls.clearfix
+          button.primary.confirm(type="submit") {{_ 'add'}}
+          unless currentBoard.isTemplatesBoard
+            unless currentBoard.isTemplateBoard
+              span.quiet
+                | {{_ 'or'}}
+                a.js-swimlane-template {{_ 'template'}}
 
 template(name="setSwimlaneColorPopup")
   form.edit-label.swimlane-color-popup

+ 16 - 14
client/components/swimlanes/swimlanes.jade

@@ -72,21 +72,23 @@ template(name="addListForm")
               | ➕
 
 template(name="moveSwimlanePopup")
-  unless currentUser.isWorker
-    label {{_ 'boards'}}:
-    select.js-select-boards(autofocus)
-      each toBoard in toBoards
-        option(value="{{toBoard._id}}") {{toBoard.title}}
+  if currentUser
+    unless currentUser.isWorker
+      label {{_ 'boards'}}:
+      select.js-select-boards(autofocus)
+        each toBoard in toBoards
+          option(value="{{toBoard._id}}") {{toBoard.title}}
 
-  .edit-controls.clearfix
-    button.primary.confirm.js-done {{_ 'done'}}
+      .edit-controls.clearfix
+        button.primary.confirm.js-done {{_ 'done'}}
 
 template(name="copySwimlanePopup")
-  unless currentUser.isWorker
-    label {{_ 'boards'}}:
-    select.js-select-boards(autofocus)
-      each toBoard in toBoards
-        option(value="{{toBoard._id}}" selected="{{#if $eq toBoard.title board.title}}1{{/if}}") {{toBoard.title}}
+  if currentUser
+    unless currentUser.isWorker
+      label {{_ 'boards'}}:
+      select.js-select-boards(autofocus)
+        each toBoard in toBoards
+          option(value="{{toBoard._id}}" selected="{{#if $eq toBoard.title board.title}}1{{/if}}") {{toBoard.title}}
 
-  .edit-controls.clearfix
-    button.primary.confirm.js-done {{_ 'done'}}
+      .edit-controls.clearfix
+        button.primary.confirm.js-done {{_ 'done'}}

+ 52 - 7
client/components/swimlanes/swimlanes.js

@@ -423,7 +423,31 @@ BlazeComponent.extendComponent({
   swimlaneHeight() {
     const user = ReactiveCache.getCurrentUser();
     const swimlane = Template.currentData();
-    const height = user.getSwimlaneHeightFromStorage(swimlane.boardId, swimlane._id);
+    
+    let height;
+    if (user) {
+      // For logged-in users, get from user profile
+      height = user.getSwimlaneHeightFromStorage(swimlane.boardId, swimlane._id);
+    } else {
+      // For non-logged-in users, get from localStorage
+      try {
+        const stored = localStorage.getItem('wekan-swimlane-heights');
+        if (stored) {
+          const heights = JSON.parse(stored);
+          if (heights[swimlane.boardId] && heights[swimlane.boardId][swimlane._id]) {
+            height = heights[swimlane.boardId][swimlane._id];
+          } else {
+            height = -1;
+          }
+        } else {
+          height = -1;
+        }
+      } catch (e) {
+        console.warn('Error reading swimlane height from localStorage:', e);
+        height = -1;
+      }
+    }
+    
     return height == -1 ? "auto" : (height + 5 + "px");
   },
 
@@ -537,15 +561,36 @@ BlazeComponent.extendComponent({
       if (process.env.DEBUG === 'true') {
       }
       
-      // Use the new storage method that handles both logged-in and non-logged-in users
-      Meteor.call('applySwimlaneHeightToStorage', boardId, swimlaneId, finalHeight, (error, result) => {
-        if (error) {
-          console.error('Error saving swimlane height:', error);
-        } else {
+      const currentUser = ReactiveCache.getCurrentUser();
+      if (currentUser) {
+        // For logged-in users, use server method
+        Meteor.call('applySwimlaneHeightToStorage', boardId, swimlaneId, finalHeight, (error, result) => {
+          if (error) {
+            console.error('Error saving swimlane height:', error);
+          } else {
+            if (process.env.DEBUG === 'true') {
+            }
+          }
+        });
+      } else {
+        // For non-logged-in users, save to localStorage directly
+        try {
+          const stored = localStorage.getItem('wekan-swimlane-heights');
+          let heights = stored ? JSON.parse(stored) : {};
+          
+          if (!heights[boardId]) {
+            heights[boardId] = {};
+          }
+          heights[boardId][swimlaneId] = finalHeight;
+          
+          localStorage.setItem('wekan-swimlane-heights', JSON.stringify(heights));
+          
           if (process.env.DEBUG === 'true') {
           }
+        } catch (e) {
+          console.warn('Error saving swimlane height to localStorage:', e);
         }
-      });
+      }
       
       e.preventDefault();
     };

+ 4 - 0
client/lib/popup.js

@@ -101,6 +101,10 @@ window.Popup = new (class {
       // our internal dependency, and since we just changed the top element of
       // our internal stack, the popup will be updated with the new data.
       if (!self.isOpen()) {
+        if (!Template[popupName]) {
+          console.error('Template not found:', popupName);
+          return;
+        }
         self.current = Blaze.renderWithData(
           self.template,
           () => {

+ 9 - 3
models/users.js

@@ -1619,7 +1619,10 @@ Meteor.methods({
     check(swimlaneId, String);
     check(height, Number);
     const user = ReactiveCache.getCurrentUser();
-    user.setSwimlaneHeightToStorage(boardId, swimlaneId, height);
+    if (user) {
+      user.setSwimlaneHeightToStorage(boardId, swimlaneId, height);
+    }
+    // For non-logged-in users, the client-side code will handle localStorage
   },
 
   applyListWidthToStorage(boardId, listId, width, constraint) {
@@ -1628,8 +1631,11 @@ Meteor.methods({
     check(width, Number);
     check(constraint, Number);
     const user = ReactiveCache.getCurrentUser();
-    user.setListWidthToStorage(boardId, listId, width);
-    user.setListConstraintToStorage(boardId, listId, constraint);
+    if (user) {
+      user.setListWidthToStorage(boardId, listId, width);
+      user.setListConstraintToStorage(boardId, listId, constraint);
+    }
+    // For non-logged-in users, the client-side code will handle localStorage
   },
   setZoomLevel(level) {
     check(level, Number);