Browse Source

Implement board archive and restoration

Maxime Quandalle 9 years ago
parent
commit
48ac8b026f

+ 1 - 1
History.md

@@ -28,7 +28,7 @@ This release continues the implementation of basic features of a “kanban”
 software, especially:
 software, especially:
 
 
 * Basic card attachments. If the attached file is an image we generate and
 * Basic card attachments. If the attached file is an image we generate and
-  displayed a thumbnail that can be used as a card “cover” (visible in the board
+  display a thumbnail that can be used as a card “cover” (visible in the board
   general view);
   general view);
 * User names mentions and auto-completion in card description and comments
 * User names mentions and auto-completion in card description and comments
   (though we don’t have any notification system for now, making this feature a
   (though we don’t have any notification system for now, making this feature a

+ 12 - 0
client/components/boards/boardArchive.jade

@@ -0,0 +1,12 @@
+template(name="archivedBoards")
+  h2 Archived boards
+
+  ul.archived-lists
+    each archivedBoards
+      li.archived-lists-item
+        button.js-restore-board
+          i.fa.fa-undo
+          | Restore board
+        = title
+    else
+      li.no-items-message No archived board.

+ 35 - 0
client/components/boards/boardArchive.js

@@ -0,0 +1,35 @@
+Template.headerTitle.events({
+  'click .js-open-archived-board': function() {
+    Modal.open('archivedBoards')
+  }
+})
+
+BlazeComponent.extendComponent({
+  template() {
+    return 'archivedBoards';
+  },
+
+  onCreated() {
+    this.subscribe('archivedBoards')
+  },
+
+  archivedBoards() {
+    return Boards.find({ archived: true }, {
+      sort: ['title']
+    })
+  },
+
+  events() {
+    return [{
+      'click .js-restore-board': function() {
+        let boardId = this.currentData()._id
+        Boards.update(boardId, {
+          $set: {
+            archived: false
+          }
+        })
+        Utils.goBoardId(boardId)
+      }
+    }]
+  },
+}).register('archivedBoards')

+ 1 - 0
client/components/boards/boardBody.jade

@@ -3,6 +3,7 @@ template(name="board")
     if currentBoard
     if currentBoard
       +boardBody
       +boardBody
     else
     else
+      //- XXX We need a better error message in case the board has been archived
       +message(label="board-no-found")
       +message(label="board-no-found")
   else
   else
     +spinner
     +spinner

+ 2 - 2
client/components/boards/boardHeader.jade

@@ -60,7 +60,7 @@ template(name="boardMenuPopup")
     if currentUser.isBoardAdmin
     if currentUser.isBoardAdmin
       hr
       hr
       ul.pop-over-list
       ul.pop-over-list
-        li: a Close Board…
+        li: a.js-archive-board Archive Board…
 
 
 template(name="boardVisibilityList")
 template(name="boardVisibilityList")
   ul.pop-over-list
   ul.pop-over-list
@@ -120,6 +120,6 @@ template(name="boardChangeTitlePopup")
       input.js-board-name(type="text" value="{{title}}" autofocus)
       input.js-board-name(type="text" value="{{title}}" autofocus)
     input.primary.wide(type="submit" value="{{_ 'rename'}}")
     input.primary.wide(type="submit" value="{{_ 'rename'}}")
 
 
-template(name="closeBoardPopup")
+template(name="archiveBoardPopup")
   p {{_ 'close-board-pop'}}
   p {{_ 'close-board-pop'}}
   button.js-confirm.negate.full(type="submit") {{_ 'close'}}
   button.js-confirm.negate.full(type="submit") {{_ 'close'}}

+ 8 - 1
client/components/boards/boardHeader.js

@@ -5,7 +5,14 @@ Template.boardMenuPopup.events({
     Popup.close();
     Popup.close();
   },
   },
   'click .js-change-board-color': Popup.open('boardChangeColor'),
   'click .js-change-board-color': Popup.open('boardChangeColor'),
-  'click .js-change-language': Popup.open('setLanguage')
+  'click .js-change-language': Popup.open('setLanguage'),
+  'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
+    var boardId = Session.get('currentBoard');
+    Boards.update(boardId, { $set: { archived: true }});
+    // XXX We should have some kind of notification on top of the page to
+    // confirm that the board was successfully archived.
+    FlowRouter.go('home');
+  })
 });
 });
 
 
 Template.boardChangeTitlePopup.events({
 Template.boardChangeTitlePopup.events({

+ 15 - 14
client/components/boards/boardList.jade

@@ -1,15 +1,16 @@
 template(name="boardList")
 template(name="boardList")
-  if boards.count
-    ul.board-list.clearfix
-      each boards
-        li(class="{{#if isStarred}}starred{{/if}}" class=colorClass)
-          a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}")
-            span.details
-              span.board-list-item-name= title
-              i.fa.js-star-board(
-                class="fa-star{{#if isStarred}} is-star-active{{else}}-o{{/if}}"
-                title="{{_ 'star-board-title'}}")
-  else
-    ul.board-list.clearfix
-      li.js-add-board
-        a.label {{_ 'add-board'}}
+  .wrapper
+    if boards.count
+      ul.board-list.clearfix
+        each boards
+          li(class="{{#if isStarred}}starred{{/if}}" class=colorClass)
+            a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}")
+              span.details
+                span.board-list-item-name= title
+                i.fa.js-star-board(
+                  class="fa-star{{#if isStarred}} is-star-active{{else}}-o{{/if}}"
+                  title="{{_ 'star-board-title'}}")
+    else
+      ul.board-list.clearfix
+        li.js-add-board
+          a.label {{_ 'add-board'}}

+ 1 - 1
client/components/boards/boardList.js

@@ -4,7 +4,7 @@ BlazeComponent.extendComponent({
   },
   },
 
 
   boards: function() {
   boards: function() {
-    return Boards.find({}, {
+    return Boards.find({ archived: false }, {
       sort: ['title']
       sort: ['title']
     });
     });
   },
   },

+ 4 - 3
client/components/boards/boardList.styl

@@ -1,6 +1,7 @@
+$spaceBetweenTiles = 16px
+
 .board-list
 .board-list
-  margin: 25px auto
-  width: 1200px
+  margin: $spaceBetweenTiles ($spaceBetweenTiles/-2) 0
 
 
   li
   li
     float: left
     float: left
@@ -24,7 +25,7 @@
     font-weight: 700
     font-weight: 700
     min-height: 18px
     min-height: 18px
     padding: 8px 12px 8px 12px
     padding: 8px 12px 8px 12px
-    margin: 0 16px 16px 0
+    margin: 0 ($spaceBetweenTiles/2) $spaceBetweenTiles
     position: relative
     position: relative
     text-decoration: none
     text-decoration: none
 
 

+ 5 - 1
client/components/main/header.jade

@@ -31,7 +31,7 @@ template(name="header")
       The main bar is a colorful bar that provide all the meta-data for the
       The main bar is a colorful bar that provide all the meta-data for the
       current page. This bar is contextual based.
       current page. This bar is contextual based.
       If the user is not connected we display "sign in" and "log in" buttons.
       If the user is not connected we display "sign in" and "log in" buttons.
-    #header-main-bar
+    #header-main-bar(class="{{#if wrappedHeader}}wrapper{{/if}}")
       if $.Session.get 'currentBoard'
       if $.Session.get 'currentBoard'
         +headerBoard
         +headerBoard
       else
       else
@@ -39,3 +39,7 @@ template(name="header")
 
 
 template(name="headerTitle")
 template(name="headerTitle")
   h1 LibreBoard
   h1 LibreBoard
+  .board-header-btns.right
+    a.board-header-btn.js-open-archived-board
+      i.fa.fa-archive
+      span Archives

+ 6 - 0
client/components/main/header.js

@@ -2,6 +2,12 @@ Template.header.helpers({
   // Reactively set the color of the page from the color of the current board.
   // Reactively set the color of the page from the color of the current board.
   headerTemplate: function() {
   headerTemplate: function() {
     return 'headerBoard';
     return 'headerBoard';
+  },
+
+  wrappedHeader: function() {
+    var unwrapedRoutes = ['board', 'card'];
+    var currentRouteName = FlowRouter.getRouteName();
+    return unwrapedRoutes.indexOf(currentRouteName) === -1;
   }
   }
 });
 });
 
 

+ 2 - 0
client/components/main/header.styl

@@ -106,6 +106,8 @@
         margin: 0 10px
         margin: 0 10px
 
 
         + span
         + span
+          display: inline-block
+          margin-top: 1px
           margin-right: 10px
           margin-right: 10px
 
 
       .board-header-btn-close
       .board-header-btn-close

+ 5 - 1
client/components/main/layouts.styl

@@ -42,6 +42,7 @@ body
     width: 660px
     width: 660px
     min-height: 160px
     min-height: 160px
     margin: 42px auto
     margin: 42px auto
+    padding: 12px
     border-radius: 4px
     border-radius: 4px
     background: darken(white, 13%)
     background: darken(white, 13%)
     z-index: 110
     z-index: 110
@@ -49,7 +50,6 @@ body
     .modal-close-btn
     .modal-close-btn
       display: block
       display: block
       float: right
       float: right
-      margin: 12px
       font-size: 24px
       font-size: 24px
 
 
 h1
 h1
@@ -206,6 +206,10 @@ dd
   margin-bottom: 0
   margin-bottom: 0
   padding-bottom: 0
   padding-bottom: 0
 
 
+.wrapper
+  max-width: 1200px
+  margin: 0 auto
+
 .relative
 .relative
   position: relative
   position: relative
 
 

+ 1 - 1
client/lib/modal.js

@@ -1,6 +1,6 @@
 const closedValue = null
 const closedValue = null
 
 
-Modal = new class {
+window.Modal = new class {
   constructor() {
   constructor() {
     this._currentModal = new ReactiveVar(closedValue)
     this._currentModal = new ReactiveVar(closedValue)
   }
   }

+ 1 - 1
collections/users.js

@@ -14,7 +14,7 @@ Users.helpers({
   },
   },
   starredBoards: function() {
   starredBoards: function() {
     var starredBoardIds = this.profile.starredBoards || [];
     var starredBoardIds = this.profile.starredBoards || [];
-    return Boards.find({_id: {$in: starredBoardIds}});
+    return Boards.find({archived: false, _id: {$in: starredBoardIds}});
   },
   },
   hasStarred: function(boardId) {
   hasStarred: function(boardId) {
     var starredBoardIds = this.profile.starredBoards || [];
     var starredBoardIds = this.profile.starredBoards || [];

+ 1 - 1
i18n/ar.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "addMemberPopup-title": "Members",
     "addMemberPopup-title": "Members",
-    "closeBoardPopup-title": "Close Board?",
+    "archiveBoardPopup-title": "Close Board?",
     "removeMemberPopup-title": "Remove Member?",
     "removeMemberPopup-title": "Remove Member?",
     "createBoardPopup-title": "Create Board",
     "createBoardPopup-title": "Create Board",
     "listActionPopup-title": "List Actions",
     "listActionPopup-title": "List Actions",

+ 1 - 1
i18n/br.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Renomear Quadro",
     "boardChangeTitlePopup-title": "Renomear Quadro",
     "boardChangeVisibilityPopup-title": "Alterar Visibilidade",
     "boardChangeVisibilityPopup-title": "Alterar Visibilidade",
     "addMemberPopup-title": "Membros",
     "addMemberPopup-title": "Membros",
-    "closeBoardPopup-title": "Fechar Quadro?",
+    "archiveBoardPopup-title": "Fechar Quadro?",
     "removeMemberPopup-title": "Remover Membro?",
     "removeMemberPopup-title": "Remover Membro?",
     "createBoardPopup-title": "Criar Quadro",
     "createBoardPopup-title": "Criar Quadro",
     "listActionPopup-title": "Listar Ações",
     "listActionPopup-title": "Listar Ações",

+ 1 - 1
i18n/cm.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "addMemberPopup-title": "Members",
     "addMemberPopup-title": "Members",
-    "closeBoardPopup-title": "Close Board?",
+    "archiveBoardPopup-title": "Close Board?",
     "removeMemberPopup-title": "Remove Member?",
     "removeMemberPopup-title": "Remove Member?",
     "createBoardPopup-title": "Create Board",
     "createBoardPopup-title": "Create Board",
     "listActionPopup-title": "List Actions",
     "listActionPopup-title": "List Actions",

+ 1 - 1
i18n/cn.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "重命名看板",
     "boardChangeTitlePopup-title": "重命名看板",
     "boardChangeVisibilityPopup-title": "更改可视级别",
     "boardChangeVisibilityPopup-title": "更改可视级别",
     "addMemberPopup-title": "成员",
     "addMemberPopup-title": "成员",
-    "closeBoardPopup-title": "关闭看板?",
+    "archiveBoardPopup-title": "关闭看板?",
     "removeMemberPopup-title": "删除成员?",
     "removeMemberPopup-title": "删除成员?",
     "createBoardPopup-title": "创建看板",
     "createBoardPopup-title": "创建看板",
     "listActionPopup-title": "列出动作",
     "listActionPopup-title": "列出动作",

+ 1 - 1
i18n/cs.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "addMemberPopup-title": "Members",
     "addMemberPopup-title": "Members",
-    "closeBoardPopup-title": "Close Board?",
+    "archiveBoardPopup-title": "Close Board?",
     "removeMemberPopup-title": "Remove Member?",
     "removeMemberPopup-title": "Remove Member?",
     "createBoardPopup-title": "Create Board",
     "createBoardPopup-title": "Create Board",
     "listActionPopup-title": "List Actions",
     "listActionPopup-title": "List Actions",

+ 1 - 1
i18n/de.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Bord umbenennen",
     "boardChangeTitlePopup-title": "Bord umbenennen",
     "boardChangeVisibilityPopup-title": "Ändere Sichbarkeit",
     "boardChangeVisibilityPopup-title": "Ändere Sichbarkeit",
     "addMemberPopup-title": "Nutzer",
     "addMemberPopup-title": "Nutzer",
-    "closeBoardPopup-title": "Schliese Bord?",
+    "archiveBoardPopup-title": "Schliese Bord?",
     "removeMemberPopup-title": "Entferne Nutzer?",
     "removeMemberPopup-title": "Entferne Nutzer?",
     "createBoardPopup-title": "Erstelle ein Bord",
     "createBoardPopup-title": "Erstelle ein Bord",
     "listActionPopup-title": "Liste von Aktionen",
     "listActionPopup-title": "Liste von Aktionen",

+ 1 - 1
i18n/en.i18n.json

@@ -171,7 +171,7 @@
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "addMemberPopup-title": "Members",
     "addMemberPopup-title": "Members",
-    "closeBoardPopup-title": "Close Board?",
+    "archiveBoardPopup-title": "Close Board?",
     "removeMemberPopup-title": "Remove Member?",
     "removeMemberPopup-title": "Remove Member?",
     "createBoardPopup-title": "Create Board",
     "createBoardPopup-title": "Create Board",
     "listActionPopup-title": "List Actions",
     "listActionPopup-title": "List Actions",

+ 1 - 1
i18n/es.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Renombrar tablero",
     "boardChangeTitlePopup-title": "Renombrar tablero",
     "boardChangeVisibilityPopup-title": "Cambiar visibilidad",
     "boardChangeVisibilityPopup-title": "Cambiar visibilidad",
     "addMemberPopup-title": "Miembros",
     "addMemberPopup-title": "Miembros",
-    "closeBoardPopup-title": "Cerrar el tablero",
+    "archiveBoardPopup-title": "Cerrar el tablero",
     "removeMemberPopup-title": "¿Eliminar miembro?",
     "removeMemberPopup-title": "¿Eliminar miembro?",
     "createBoardPopup-title": "Crear tablero",
     "createBoardPopup-title": "Crear tablero",
     "listActionPopup-title": "Acciones de la lista",
     "listActionPopup-title": "Acciones de la lista",

+ 1 - 1
i18n/fi.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Nimeä taulu uudelleen",
     "boardChangeTitlePopup-title": "Nimeä taulu uudelleen",
     "boardChangeVisibilityPopup-title": "Vaihda näkyvyyttä",
     "boardChangeVisibilityPopup-title": "Vaihda näkyvyyttä",
     "addMemberPopup-title": "Jäsenet",
     "addMemberPopup-title": "Jäsenet",
-    "closeBoardPopup-title": "Sulje taulu?",
+    "archiveBoardPopup-title": "Sulje taulu?",
     "removeMemberPopup-title": "Poista jäsen?",
     "removeMemberPopup-title": "Poista jäsen?",
     "createBoardPopup-title": "Luo taulu",
     "createBoardPopup-title": "Luo taulu",
     "listActionPopup-title": "Listaa toimet",
     "listActionPopup-title": "Listaa toimet",

+ 1 - 1
i18n/fr.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Renommer le tableau",
     "boardChangeTitlePopup-title": "Renommer le tableau",
     "boardChangeVisibilityPopup-title": "Changer la visibilité",
     "boardChangeVisibilityPopup-title": "Changer la visibilité",
     "addMemberPopup-title": "Membres",
     "addMemberPopup-title": "Membres",
-    "closeBoardPopup-title": "Fermer le tableau ?",
+    "archiveBoardPopup-title": "Fermer le tableau ?",
     "removeMemberPopup-title": "Supprimer le membre ?",
     "removeMemberPopup-title": "Supprimer le membre ?",
     "createBoardPopup-title": "Créer un tableau",
     "createBoardPopup-title": "Créer un tableau",
     "listActionPopup-title": "Liste des actions",
     "listActionPopup-title": "Liste des actions",

+ 1 - 1
i18n/hk.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "addMemberPopup-title": "Members",
     "addMemberPopup-title": "Members",
-    "closeBoardPopup-title": "Close Board?",
+    "archiveBoardPopup-title": "Close Board?",
     "removeMemberPopup-title": "Remove Member?",
     "removeMemberPopup-title": "Remove Member?",
     "createBoardPopup-title": "Create Board",
     "createBoardPopup-title": "Create Board",
     "listActionPopup-title": "List Actions",
     "listActionPopup-title": "List Actions",

+ 1 - 1
i18n/id.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeTitlePopup-title": "Rename Board",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "boardChangeVisibilityPopup-title": "Change Visibility",
     "addMemberPopup-title": "Members",
     "addMemberPopup-title": "Members",
-    "closeBoardPopup-title": "Close Board?",
+    "archiveBoardPopup-title": "Close Board?",
     "removeMemberPopup-title": "Remove Member?",
     "removeMemberPopup-title": "Remove Member?",
     "createBoardPopup-title": "Create Board",
     "createBoardPopup-title": "Create Board",
     "listActionPopup-title": "List Actions",
     "listActionPopup-title": "List Actions",

+ 1 - 1
i18n/ja.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "ボード名の変更",
     "boardChangeTitlePopup-title": "ボード名の変更",
     "boardChangeVisibilityPopup-title": "公開範囲の変更",
     "boardChangeVisibilityPopup-title": "公開範囲の変更",
     "addMemberPopup-title": "メンバー",
     "addMemberPopup-title": "メンバー",
-    "closeBoardPopup-title": "ボードを閉じますか?",
+    "archiveBoardPopup-title": "ボードを閉じますか?",
     "removeMemberPopup-title": "メンバーを外しますか?",
     "removeMemberPopup-title": "メンバーを外しますか?",
     "createBoardPopup-title": "ボードの作成",
     "createBoardPopup-title": "ボードの作成",
     "listActionPopup-title": "操作一覧",
     "listActionPopup-title": "操作一覧",

+ 1 - 1
i18n/ko.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "보드 이름 바꾸기",
     "boardChangeTitlePopup-title": "보드 이름 바꾸기",
     "boardChangeVisibilityPopup-title": "표시 여부 변경",
     "boardChangeVisibilityPopup-title": "표시 여부 변경",
     "addMemberPopup-title": "멤버",
     "addMemberPopup-title": "멤버",
-    "closeBoardPopup-title": "보드를 닫습니까?",
+    "archiveBoardPopup-title": "보드를 닫습니까?",
     "removeMemberPopup-title": "멤버를 제거합니까?",
     "removeMemberPopup-title": "멤버를 제거합니까?",
     "createBoardPopup-title": "보드 생성",
     "createBoardPopup-title": "보드 생성",
     "listActionPopup-title": "동작 목록",
     "listActionPopup-title": "동작 목록",

+ 1 - 1
i18n/ru.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Переименовать доску",
     "boardChangeTitlePopup-title": "Переименовать доску",
     "boardChangeVisibilityPopup-title": "Изменить настройки видимости",
     "boardChangeVisibilityPopup-title": "Изменить настройки видимости",
     "addMemberPopup-title": "Участники",
     "addMemberPopup-title": "Участники",
-    "closeBoardPopup-title": "Закрыть доску?",
+    "archiveBoardPopup-title": "Закрыть доску?",
     "removeMemberPopup-title": "Удалить участника?",
     "removeMemberPopup-title": "Удалить участника?",
     "createBoardPopup-title": "Создать доску",
     "createBoardPopup-title": "Создать доску",
     "listActionPopup-title": "Список действий",
     "listActionPopup-title": "Список действий",

+ 1 - 1
i18n/tr.i18n.json

@@ -159,7 +159,7 @@
     "boardChangeTitlePopup-title": "Pano Adı Değiştirme",
     "boardChangeTitlePopup-title": "Pano Adı Değiştirme",
     "boardChangeVisibilityPopup-title": "Görünebilirliği Değiştir",
     "boardChangeVisibilityPopup-title": "Görünebilirliği Değiştir",
     "addMemberPopup-title": "Üyeler",
     "addMemberPopup-title": "Üyeler",
-    "closeBoardPopup-title": "Pano Kapatılsın mı?",
+    "archiveBoardPopup-title": "Pano Kapatılsın mı?",
     "removeMemberPopup-title": "Üyeyi Çıkarmak mı?",
     "removeMemberPopup-title": "Üyeyi Çıkarmak mı?",
     "createBoardPopup-title": "Pano Oluşturma",
     "createBoardPopup-title": "Pano Oluşturma",
     "listActionPopup-title": "Liste İşlemleri",
     "listActionPopup-title": "Liste İşlemleri",

+ 23 - 0
server/publications/boards.js

@@ -22,6 +22,7 @@ Meteor.publish('boards', function() {
   }, {
   }, {
     fields: {
     fields: {
       _id: 1,
       _id: 1,
+      archived: 1,
       slug: 1,
       slug: 1,
       title: 1,
       title: 1,
       color: 1,
       color: 1,
@@ -30,6 +31,28 @@ Meteor.publish('boards', function() {
   });
   });
 });
 });
 
 
+Meteor.publish('archivedBoards', function() {
+  if (! Match.test(this.userId, String))
+    return [];
+
+  return Boards.find({
+    archived: true,
+    members: {
+      $elemMatch: {
+        userId: this.userId,
+        isAdmin: true
+      }
+    }
+  }, {
+    fields: {
+      _id: 1,
+      archived: 1,
+      slug: 1,
+      title: 1
+    }
+  })
+});
+
 Meteor.publishComposite('board', function(boardId) {
 Meteor.publishComposite('board', function(boardId) {
   check(boardId, String);
   check(boardId, String);
   return {
   return {