Jelajahi Sumber

Merge branch 'jrsupplee-master'

Lauri Ojansivu 4 tahun lalu
induk
melakukan
f88c3755e0

+ 7 - 7
client/components/boards/boardsList.jade

@@ -60,10 +60,10 @@ template(name="boardList")
 
 
 template(name="boardListHeaderBar")
 template(name="boardListHeaderBar")
   h1 {{_ title }}
   h1 {{_ title }}
-  .board-header-btns.right
-    a.board-header-btn.js-open-archived-board
-      i.fa.fa-archive
-      span {{_ 'archives'}}
-    a.board-header-btn(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
-      i.fa.fa-clone
-      span {{_ 'templates'}}
+  //.board-header-btns.right
+  //  a.board-header-btn.js-open-archived-board
+  //    i.fa.fa-archive
+  //    span {{_ 'archives'}}
+  //  a.board-header-btn(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
+  //    i.fa.fa-clone
+  //    span {{_ 'templates'}}

+ 4 - 4
client/components/main/header.jade

@@ -38,10 +38,10 @@ template(name="header")
               span.fa.fa-home
               span.fa.fa-home
               | {{_ 'all-boards'}}
               | {{_ 'all-boards'}}
           li.separator -
           li.separator -
-          li
-            a(href="{{pathFor 'public'}}")
-              span.fa.fa-globe
-              | {{_ 'public'}}
+          //li
+          //  a(href="{{pathFor 'public'}}")
+          //    span.fa.fa-globe
+          //    | {{_ 'public'}}
           each currentUser.starredBoards
           each currentUser.starredBoards
             li.separator -
             li.separator -
             li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")
             li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")

+ 28 - 0
client/components/main/myCards.jade

@@ -0,0 +1,28 @@
+template(name="myCardsHeaderBar")
+  h1
+    a.back-btn(href="{{pathFor 'home'}}")
+      i.fa.fa-chevron-left
+    | {{_ 'my-cards'}}
+
+template(name="myCardsModalTitle")
+  h2
+    i.fa.fa-keyboard-o
+    | {{_ 'my-cards'}}
+
+template(name="myCards")
+  .wrapper
+    each board in cardsFind
+      .board-title
+        | {{_ 'board' }}:
+        = board.title
+      each swimlane in board.swimlanes
+        .swimlane-title
+          | {{_ 'swimlane' }}:
+          = swimlane.title
+        each list in swimlane.lists
+          .list-title
+            | {{_ 'list' }}:
+            = list.title
+          each card in list.cards
+            a.minicard-wrapper.card-title(href="{{pathFor 'card' boardId=board.id slug=board.slug cardId=card._id }}")
+              +minicard(card)

+ 154 - 0
client/components/main/myCards.js

@@ -0,0 +1,154 @@
+const subManager = new SubsManager();
+Meteor.subscribe('myCards');
+Meteor.subscribe('mySwimlanes');
+Meteor.subscribe('myLists');
+
+Template.myCardsHeaderBar.events({
+  'click .js-open-archived-board'() {
+    Modal.open('archivedBoards');
+  },
+});
+
+Template.myCardsHeaderBar.helpers({
+  title() {
+    return FlowRouter.getRouteName() === 'home' ? 'my-boards' : 'public';
+  },
+  templatesUser() {
+    return Meteor.user();
+  },
+});
+
+Template.myCards.helpers({
+  userId() {
+    return Meteor.userId();
+  },
+});
+
+BlazeComponent.extendComponent({
+  onCreated() {
+    Meteor.subscribe('setting');
+    // subManager.subscribe('myCards');
+  },
+
+  cardsFind() {
+    const userId = Meteor.userId();
+    const boards = [];
+    let board = null;
+    let swimlane = null;
+    let list = null;
+
+    const cursor = Cards.find(
+      {
+        archived: false,
+        $or: [{ members: userId }, { assignees: userId }],
+      },
+      {
+        sort: {
+          boardId: 1,
+          swimlaneId: 1,
+          listId: 1,
+          sort: 1,
+        },
+      },
+    );
+    // eslint-disable-next-line no-console
+    // console.log('cursor:', cursor);
+
+    let newBoard = false;
+    let newSwimlane = false;
+    let newList = false;
+
+    cursor.forEach(card => {
+      // eslint-disable-next-line no-console
+      // console.log('card:', card.title);
+      if (list === null || list.id !== card.listId) {
+        // eslint-disable-next-line no-console
+        // console.log('new list');
+        let l = Lists.findOne(card.listId);
+        if (!l) {
+          l = {
+            _id: card.listId,
+            title: 'undefined list',
+          };
+        }
+        // eslint-disable-next-line no-console
+        // console.log('list:', l);
+        list = {
+          id: l._id,
+          title: l.title,
+          cards: [card],
+        };
+        newList = true;
+      }
+      if (swimlane === null || card.swimlaneId !== swimlane.id) {
+        // eslint-disable-next-line no-console
+        // console.log('new swimlane');
+        let s = Swimlanes.findOne(card.swimlaneId);
+        if (!s) {
+          s = {
+            _id: card.swimlaneId,
+            title: 'undefined swimlane',
+          };
+        }
+        // eslint-disable-next-line no-console
+        // console.log('swimlane:', s);
+        swimlane = {
+          id: s._id,
+          title: s.title,
+          lists: [list],
+        };
+        newSwimlane = true;
+      }
+      if (board === null || card.boardId !== board.id) {
+        // eslint-disable-next-line no-console
+        // console.log('new board');
+        const b = Boards.findOne(card.boardId);
+        // eslint-disable-next-line no-console
+        // console.log('board:', b, b._id, b.title);
+        board = {
+          id: b._id,
+          title: b.title,
+          slug: b.slug,
+          swimlanes: [swimlane],
+        };
+        newBoard = true;
+      }
+
+      if (newBoard) {
+        boards.push(board);
+      } else if (newSwimlane) {
+        board.swimlanes.push(swimlane);
+      } else if (newList) {
+        swimlane.lists.push(list);
+      } else {
+        list.cards.push(card);
+      }
+
+      newBoard = false;
+      newSwimlane = false;
+      newList = false;
+    });
+
+    // eslint-disable-next-line no-console
+    // console.log('boards:', boards);
+    return boards;
+  },
+
+  events() {
+    return [
+      {
+        'click .js-my-card'(evt) {
+          const card = this.currentData().card;
+          // eslint-disable-next-line no-console
+          console.log('currentData():', this.currentData());
+          // eslint-disable-next-line no-console
+          console.log('card:', card);
+          if (card) {
+            Utils.goCardId(card._id);
+          }
+          evt.preventDefault();
+        },
+      },
+    ];
+  },
+}).register('myCards');

+ 40 - 0
client/components/main/myCards.styl

@@ -0,0 +1,40 @@
+.my-cards-list
+  .my-cards-list-item
+    border-bottom: 1px solid darken(white, 25%)
+    padding: 10px 5px
+
+    &:last-child
+      border-bottom: none
+
+    .my-cards-list-item-keys
+      margin-top: 5px
+      float: right
+
+      kbd
+        padding: 5px 8px
+        margin: 5px
+        font-size: 18px
+
+    .my-cards-list-item-action
+      font-size: 1.4em
+      margin: 5px
+
+.board-title
+  font-size: 1.4rem
+  font-weight: bold
+
+.swimlane-title
+  font-size: 1.2rem
+  font-weight: bold
+  margin-left: 1em
+  margin-top: 10px
+
+.list-title
+  margin-top: 5px
+  font-weight: bold
+  margin-left: 1.6rem
+
+.card-title
+  margin-top: 5px
+  margin-left: 1.8rem
+  max-width: 350px;

+ 5 - 4
client/components/swimlanes/swimlaneHeader.jade

@@ -17,11 +17,12 @@ template(name="swimlaneFixedHeader")
     unless currentUser.isCommentOnly
     unless currentUser.isCommentOnly
       if currentUser.isBoardAdmin
       if currentUser.isBoardAdmin
         a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon
         a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon
-        a.fa.fa-navicon.js-open-swimlane-menu.swimlane-header-menu-icon
-      if isMiniScreenOrShowDesktopDragHandles
+        a.fa.fa-navicon.js-open-swimlane-menu
+      unless isMiniScreen
+        if showDesktopDragHandles
+          a.swimlane-header-handle.handle.fa.fa-arrows.js-swimlane-header-handle
+      if isMiniScreen
         a.swimlane-header-miniscreen-handle.handle.fa.fa-arrows.js-swimlane-header-handle
         a.swimlane-header-miniscreen-handle.handle.fa.fa-arrows.js-swimlane-header-handle
-      else
-        a.swimlane-header-handle.handle.fa.fa-arrows.js-swimlane-header-handle
 
 
 template(name="editSwimlaneTitleForm")
 template(name="editSwimlaneTitleForm")
   .list-composer
   .list-composer

+ 1 - 0
client/components/swimlanes/swimlanes.styl

@@ -85,6 +85,7 @@
     .swimlane-header-menu
     .swimlane-header-menu
       position: absolute
       position: absolute
       padding: 5px 5px
       padding: 5px 5px
+      font-size: 22px
 
 
     .swimlane-header-plus-icon
     .swimlane-header-plus-icon
       margin-left: 5px
       margin-left: 5px

+ 28 - 12
client/components/users/userHeader.jade

@@ -12,7 +12,35 @@ template(name="headerUserBar")
 
 
 template(name="memberMenuPopup")
 template(name="memberMenuPopup")
   ul.pop-over-list
   ul.pop-over-list
+    if currentUser.isAdmin
+      li
+        a.js-go-setting(href="{{pathFor 'setting'}}")
+          i.fa.fa-lock
+          | {{_ 'admin-panel'}}
     with currentUser
     with currentUser
+      li
+        a(href="{{pathFor 'home'}}")
+          span.fa.fa-home
+          | {{_ 'all-boards'}}
+      li
+        a.js-my-cards(href="{{pathFor 'my-cards'}}")
+          i.fa.fa-list
+          | {{_ 'my-cards'}}
+      li
+        a(href="{{pathFor 'public'}}")
+          span.fa.fa-globe
+          | {{_ 'public'}}
+      li
+        a.board-header-btn.js-open-archived-board
+          i.fa.fa-archive
+          span {{_ 'archives'}}
+      unless currentUser.isWorker
+        ul.pop-over-list
+          li
+            a(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
+              i.fa.fa-clone
+              | {{_ 'templates'}}
+      hr
       li
       li
         a.js-edit-profile
         a.js-edit-profile
           i.fa.fa-user
           i.fa.fa-user
@@ -34,18 +62,6 @@ template(name="memberMenuPopup")
           a.js-change-language
           a.js-change-language
             i.fa.fa-flag
             i.fa.fa-flag
             | {{_ 'changeLanguagePopup-title'}}
             | {{_ 'changeLanguagePopup-title'}}
-    if currentUser.isAdmin
-      li
-        a.js-go-setting(href="{{pathFor 'setting'}}")
-          i.fa.fa-lock
-          | {{_ 'admin-panel'}}
-  unless currentUser.isWorker
-    hr
-    ul.pop-over-list
-      li
-        a(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
-          i.fa.fa-clone
-          | {{_ 'templates'}}
   unless isSandstorm
   unless isSandstorm
     hr
     hr
     ul.pop-over-list
     ul.pop-over-list

+ 6 - 0
client/components/users/userHeader.js

@@ -25,6 +25,12 @@ Template.memberMenuPopup.helpers({
 });
 });
 
 
 Template.memberMenuPopup.events({
 Template.memberMenuPopup.events({
+  'click .js-my-cards'() {
+    Popup.close();
+  },
+  'click .js-open-archived-board'() {
+    Modal.open('archivedBoards');
+  },
   'click .js-edit-profile': Popup.open('editProfile'),
   'click .js-edit-profile': Popup.open('editProfile'),
   'click .js-change-settings': Popup.open('changeSettings'),
   'click .js-change-settings': Popup.open('changeSettings'),
   'click .js-change-avatar': Popup.open('changeAvatar'),
   'click .js-change-avatar': Popup.open('changeAvatar'),

+ 26 - 0
config/router.js

@@ -113,6 +113,32 @@ FlowRouter.route('/shortcuts', {
   },
   },
 });
 });
 
 
+FlowRouter.route('/my-cards', {
+  name: 'my-cards',
+  action() {
+    const myCardsTemplate = 'myCards';
+
+    Filter.reset();
+    // EscapeActions.executeAll();
+    EscapeActions.executeUpTo('popup-close');
+
+    Utils.manageCustomUI();
+    Utils.manageMatomo();
+
+    // if (previousPath) {
+    //   Modal.open(myCardsTemplate, {
+    //     header: 'myCardsModalTitle',
+    //     onCloseGoTo: previousPath,
+    //   });
+    // } else {
+    BlazeLayout.render('defaultLayout', {
+      headerBar: 'myCardsHeaderBar',
+      content: myCardsTemplate,
+    });
+    // }
+  },
+});
+
 FlowRouter.route('/import/:source', {
 FlowRouter.route('/import/:source', {
   name: 'import',
   name: 'import',
   triggersEnter: [AccountsTemplates.ensureSignedIn],
   triggersEnter: [AccountsTemplates.ensureSignedIn],

+ 6 - 2
i18n/ar.i18n.json

@@ -137,6 +137,7 @@
   "boardChangeWatchPopup-title": "تغيير المتابعة",
   "boardChangeWatchPopup-title": "تغيير المتابعة",
   "boardMenuPopup-title": "Board Settings",
   "boardMenuPopup-title": "Board Settings",
   "boardChangeViewPopup-title": "عرض اللوحات",
   "boardChangeViewPopup-title": "عرض اللوحات",
+  "board": "لوحة",
   "boards": "لوحات",
   "boards": "لوحات",
   "board-view": "عرض اللوحات",
   "board-view": "عرض اللوحات",
   "board-view-cal": "التقويم",
   "board-view-cal": "التقويم",
@@ -148,6 +149,7 @@
   "cancel": "إلغاء",
   "cancel": "إلغاء",
   "card-archived": "البطاقة منقولة الى الارشيف",
   "card-archived": "البطاقة منقولة الى الارشيف",
   "board-archived": "اللوحات منقولة الى الارشيف",
   "board-archived": "اللوحات منقولة الى الارشيف",
+  "card": "نطاقة",
   "card-comments-title": "%s تعليقات لهذه البطاقة",
   "card-comments-title": "%s تعليقات لهذه البطاقة",
   "card-delete-notice": "هذا حذف أبديّ . سوف تفقد كل الإجراءات المنوطة بهذه البطاقة",
   "card-delete-notice": "هذا حذف أبديّ . سوف تفقد كل الإجراءات المنوطة بهذه البطاقة",
   "card-delete-pop": "سيتم إزالة جميع الإجراءات من تبعات النشاط، وأنك لن تكون قادرا على إعادة فتح البطاقة. لا يوجد التراجع.",
   "card-delete-pop": "سيتم إزالة جميع الإجراءات من تبعات النشاط، وأنك لن تكون قادرا على إعادة فتح البطاقة. لا يوجد التراجع.",
@@ -403,6 +405,7 @@
   "leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
   "leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
   "leaveBoardPopup-title": "مغادرة اللوحة ؟",
   "leaveBoardPopup-title": "مغادرة اللوحة ؟",
   "link-card": "ربط هذه البطاقة",
   "link-card": "ربط هذه البطاقة",
+  "list": "قائمة",
   "list-archive-cards": "Move all cards in this list to Archive",
   "list-archive-cards": "Move all cards in this list to Archive",
   "list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Archive and bring them back to the board, click “Menu” > “Archive”.",
   "list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Archive and bring them back to the board, click “Menu” > “Archive”.",
   "list-move-cards": "نقل بطاقات هذه القائمة",
   "list-move-cards": "نقل بطاقات هذه القائمة",
@@ -831,7 +834,7 @@
   "saturday": "Saturday",
   "saturday": "Saturday",
   "sunday": "Sunday",
   "sunday": "Sunday",
   "status": "Status",
   "status": "Status",
-  "swimlane": "Swimlane",
+  "swimlane": "خط السباحة",
   "owner": "Owner",
   "owner": "Owner",
   "last-modified-at": "Last modified at",
   "last-modified-at": "Last modified at",
   "last-activity": "Last activity",
   "last-activity": "Last activity",
@@ -848,5 +851,6 @@
   "displayName": "Display Name",
   "displayName": "Display Name",
   "shortName": "Short Name",
   "shortName": "Short Name",
   "website": "Website",
   "website": "Website",
-  "person": "Person"
+  "person": "Person",
+  "my-cards": "بطاقاتي"
 }
 }

+ 5 - 1
i18n/en.i18n.json

@@ -848,5 +848,9 @@
   "displayName": "Display Name",
   "displayName": "Display Name",
   "shortName": "Short Name",
   "shortName": "Short Name",
   "website": "Website",
   "website": "Website",
-  "person": "Person"
+  "person": "Person",
+  "my-cards": "My Cards",
+  "card": "Card",
+  "list": "List",
+  "board": "Board"
 }
 }

+ 60 - 0
server/publications/boards.js

@@ -42,6 +42,66 @@ Meteor.publish('boards', function() {
   );
   );
 });
 });
 
 
+Meteor.publish('mySwimlanes', function() {
+  const userId = this.userId;
+  const swimlanes = [];
+
+  Cards.find({
+    archived: false,
+    $or: [{ members: userId }, { assignees: userId }],
+  }).forEach(card => {
+    swimlanes.push(card.swimlaneId);
+  });
+
+  return Swimlanes.find(
+    {
+      archived: false,
+      _id: { $in: swimlanes },
+    },
+    {
+      fields: {
+        _id: 1,
+        title: 1,
+        type: 1,
+        sort: 1,
+      },
+      // sort: {
+      //   sort: ['boardId', 'listId', 'sort'],
+      // },
+    },
+  );
+});
+
+Meteor.publish('myLists', function() {
+  const userId = this.userId;
+  const lists = [];
+
+  Cards.find({
+    archived: false,
+    $or: [{ members: userId }, { assignees: userId }],
+  }).forEach(card => {
+    lists.push(card.listId);
+  });
+
+  return Lists.find(
+    {
+      archived: false,
+      _id: { $in: lists },
+    },
+    {
+      fields: {
+        _id: 1,
+        title: 1,
+        type: 1,
+        sort: 1,
+      },
+      // sort: {
+      //   sort: ['boardId', 'listId', 'sort'],
+      // },
+    },
+  );
+});
+
 Meteor.publish('archivedBoards', function() {
 Meteor.publish('archivedBoards', function() {
   const userId = this.userId;
   const userId = this.userId;
   if (!Match.test(userId, String)) return [];
   if (!Match.test(userId, String)) return [];

+ 30 - 0
server/publications/cards.js

@@ -2,3 +2,33 @@ Meteor.publish('card', cardId => {
   check(cardId, String);
   check(cardId, String);
   return Cards.find({ _id: cardId });
   return Cards.find({ _id: cardId });
 });
 });
+
+Meteor.publish('myCards', function() {
+  const userId = this.userId;
+
+  return Cards.find(
+    {
+      archived: false,
+      $or: [{ members: userId }, { assignees: userId }],
+    },
+    {
+      fields: {
+        _id: 1,
+        archived: 1,
+        boardId: 1,
+        swimlaneId: 1,
+        listId: 1,
+        title: 1,
+        type: 1,
+        sort: 1,
+        members: 1,
+        assignees: 1,
+        colors: 1,
+        dueAt: 1,
+      },
+      // sort: {
+      //   sort: ['boardId', 'listId', 'sort'],
+      // },
+    },
+  );
+});