Explorar el Código

New Broken Cards page

John R. Supplee hace 4 años
padre
commit
4679db6ec4

+ 41 - 0
client/components/main/brokenCards.jade

@@ -0,0 +1,41 @@
+template(name="brokenCardsHeaderBar")
+  h1
+    | Broken Cards
+
+template(name="brokenCards")
+  .wrapper
+    .broken-cards-dueat-list-wrapper
+      each card in brokenCardsList
+        .broken-cards-card-wrapper
+          a.minicard-wrapper.card-title(href=card.absoluteUrl)
+            +minicard(card)
+          ul.broken-cards-context-list
+            li.broken-cards-context(title="{{_ 'board'}}")
+              if card.boardId
+                +viewer
+                  = card.getBoard.title
+              else
+                .broken-cards-null
+                  | NULL
+            li.broken-cards-context.broken-cards-context-separator
+              = ' '
+              | {{_ 'context-separator'}}
+              = ' '
+            li.broken-cards-context(title="{{_ 'swimlane'}}")
+              if card.swimlaneId
+                +viewer
+                  = card.getSwimlane.title
+              else
+                .broken-cards-null
+                  | NULL
+            li.broken-cards-context
+              = ' '
+              | {{_ 'context-separator'}}
+              = ' '
+            li.broken-cards-context(title="{{_ 'list'}}")
+              if card.listId
+                +viewer
+                  = card.getList.title
+              else
+                .broken-cards-null
+                  | NULL

+ 58 - 0
client/components/main/brokenCards.js

@@ -0,0 +1,58 @@
+BlazeComponent.extendComponent({}).register('brokenCardsHeaderBar');
+
+Template.brokenCards.helpers({
+  userId() {
+    return Meteor.userId();
+  },
+});
+
+BlazeComponent.extendComponent({
+  onCreated() {
+    Meteor.subscribe('setting');
+    Meteor.subscribe('brokenCards');
+  },
+
+  brokenCardsList() {
+    const user = Meteor.user();
+
+    const permiitedBoards = [null];
+    let selector = {};
+    // if user is not an admin allow her to see cards only from boards where
+    // she is a member
+    if (!user.isAdmin) {
+      selector.$or = [
+        { permission: 'public' },
+        { members: { $elemMatch: { userId: user._id, isActive: true } } },
+      ];
+    }
+    Boards.find(selector).forEach(board => {
+      permiitedBoards.push(board._id);
+    });
+
+    selector = {
+      boardId: { $in: permiitedBoards },
+      $or: [{ boardId: null }, { swimlaneId: null }, { listId: null }],
+    };
+
+    const cards = Cards.find(selector, {
+      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,
+      },
+    });
+
+    // eslint-disable-next-line no-console
+    // console.log('cards:', cards);
+    return cards;
+  },
+}).register('brokenCards');

+ 73 - 0
client/components/main/brokenCards.styl

@@ -0,0 +1,73 @@
+.broken-cards-board-wrapper
+  border-radius: 8px
+  //padding: 0.5rem
+  min-width: 400px
+  border-width: 8px
+  border-color: grey
+  border-style: solid
+  margin-bottom: 2rem
+  margin-right: auto
+  margin-left: auto
+
+.broken-cards-board-title
+  font-size: 1.4rem
+  font-weight: bold
+  padding: 0.5rem
+  background-color: grey
+  color: white
+
+.broken-cards-swimlane-title
+  font-size: 1.1rem
+  font-weight: bold
+  padding: 0.5rem
+  padding-bottom: 0.4rem
+  margin-top: 0
+  margin-bottom: 0.5rem
+  //border-top: black 1px solid
+  //border-bottom: black 1px solid
+  text-align: center
+
+.swimlane-default-color
+  background-color: lightgrey
+
+.broken-cards-list-title
+  font-weight: bold
+  font-size: 1.1rem
+  //padding-bottom: 0
+  //margin-bottom: 0
+  text-align: center
+  margin-bottom: 0.7rem
+
+.broken-cards-list-wrapper
+  margin: 1rem
+  border-radius: 5px
+  padding: 1.5rem
+  padding-top: 0.75rem
+  display: inline-block
+  min-width: 250px
+  max-width: 350px
+
+.broken-cards-card-wrapper
+  margin-top: 0
+  margin-bottom: 10px
+
+.broken-cards-dueat-list-wrapper
+  max-width: 500px
+  margin-right: auto
+  margin-left: auto
+
+.broken-cards-field-name
+  font-weight: bold
+
+.broken-cards-context
+  display: inline-block
+
+.broken-cards-context-separator
+  font-weight: bold
+
+.broken-cards-context-list
+  margin-bottom: 0.7rem
+
+.broken-cards-null
+  //font-weight: bold
+  font-style: italic

+ 20 - 0
config/router.js

@@ -165,6 +165,26 @@ FlowRouter.route('/due-cards', {
   },
 });
 
+FlowRouter.route('/broken-cards', {
+  name: 'broken-cards',
+  action() {
+    const brokenCardsTemplate = 'brokenCards';
+
+    Filter.reset();
+    // EscapeActions.executeAll();
+    EscapeActions.executeUpTo('popup-close');
+
+    Utils.manageCustomUI();
+    Utils.manageMatomo();
+
+    BlazeLayout.render('defaultLayout', {
+      headerBar: 'brokenCardsHeaderBar',
+      content: brokenCardsTemplate,
+    });
+    // }
+  },
+});
+
 FlowRouter.route('/import/:source', {
   name: 'import',
   triggersEnter: [AccountsTemplates.ensureSignedIn],

+ 57 - 0
server/publications/cards.js

@@ -119,3 +119,60 @@ Meteor.publish('dueCards', function(allUsers = false) {
     Lists.find({ _id: { $in: lists } }),
   ];
 });
+
+Meteor.publish('brokenCards', function() {
+  const user = Users.findOne(this.userId);
+
+  const permiitedBoards = [null];
+  let selector = {};
+  // if user is not an admin allow her to see cards only from boards where
+  // she is a member
+  if (!user.isAdmin) {
+    selector.$or = [
+      { permission: 'public' },
+      { members: { $elemMatch: { userId: user._id, isActive: true } } },
+    ];
+  }
+  Boards.find(selector).forEach(board => {
+    permiitedBoards.push(board._id);
+  });
+
+  selector = {
+    boardId: { $in: permiitedBoards },
+    $or: [{ boardId: null }, { swimlaneId: null }, { listId: null }],
+  };
+
+  const cards = Cards.find(selector, {
+    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,
+    },
+  });
+
+  const boards = [];
+  const swimlanes = [];
+  const lists = [];
+
+  cards.forEach(card => {
+    if (card.boardId) boards.push(card.boardId);
+    if (card.swimlaneId) swimlanes.push(card.swimlaneId);
+    if (card.listId) lists.push(card.listId);
+  });
+
+  return [
+    cards,
+    Boards.find({ _id: { $in: boards } }),
+    Swimlanes.find({ _id: { $in: swimlanes } }),
+    Lists.find({ _id: { $in: lists } }),
+  ];
+});