diff options
-rw-r--r-- | .meteor/packages | 7 | ||||
-rw-r--r-- | .meteor/versions | 16 | ||||
-rw-r--r-- | client/components/boards/boardBody.jade | 44 | ||||
-rw-r--r-- | client/components/boards/boardBody.js | 15 | ||||
-rw-r--r-- | client/components/boards/boardHeader.jade | 12 | ||||
-rw-r--r-- | client/components/boards/boardList.jade | 9 | ||||
-rw-r--r-- | client/components/boards/router.js | 58 | ||||
-rw-r--r-- | client/components/lists/main.js | 2 | ||||
-rw-r--r-- | client/components/main/header.jade | 4 | ||||
-rw-r--r-- | client/components/main/layouts.jade | 6 | ||||
-rw-r--r-- | client/components/main/layouts.js | 5 | ||||
-rw-r--r-- | client/components/main/router.js | 5 | ||||
-rw-r--r-- | client/components/sidebar/sidebar.js | 2 | ||||
-rw-r--r-- | client/components/sidebar/sidebarArchives.jade | 2 | ||||
-rw-r--r-- | client/components/users/router.js | 15 | ||||
-rw-r--r-- | client/config/accounts.js | 13 | ||||
-rw-r--r-- | client/config/router.js | 97 | ||||
-rw-r--r-- | client/lib/utils.js | 6 | ||||
-rw-r--r-- | collections/boards.js | 2 | ||||
-rw-r--r-- | collections/cards.js | 2 | ||||
-rw-r--r-- | sandstorm.js | 12 | ||||
-rw-r--r-- | server/publications/boards.js | 4 |
22 files changed, 139 insertions, 199 deletions
diff --git a/.meteor/packages b/.meteor/packages index 5547ede0..11594a83 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -14,7 +14,7 @@ kenton:accounts-sandstorm service-configuration useraccounts:core useraccounts:unstyled -useraccounts:iron-routing +useraccounts:flow-routing # Compilers mquandalle:jade @@ -32,8 +32,11 @@ reywood:publish-composite # Utilities alethes:pages +arillo:flow-router-helpers audit-argument-checks -iron:router +kadira:blaze-layout +kadira:flow-router +meteorhacks:picker meteorhacks:subs-manager mquandalle:autofocus mquandalle:bower diff --git a/.meteor/versions b/.meteor/versions index c60462d2..e9be382b 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -3,6 +3,7 @@ accounts-password@1.1.1 aldeed:collection2@2.3.3 aldeed:simple-schema@1.3.3 alethes:pages@1.8.4 +arillo:flow-router-helpers@0.4.3 audit-argument-checks@1.0.3 autoupdate@1.2.1 base64@1.0.3 @@ -30,6 +31,7 @@ cfs:upload-http@0.0.20 cfs:worker@0.1.4 check@1.0.5 coffeescript@1.0.6 +cosmos:browserify@0.5.0 dburles:collection-helpers@1.0.3 ddp@1.1.0 deps@1.0.7 @@ -43,16 +45,10 @@ htmljs@1.0.4 http@1.1.0 id-map@1.0.3 idmontie:migrations@1.0.0 -iron:controller@1.0.8 -iron:core@1.0.8 -iron:dynamic-template@1.0.8 -iron:layout@1.0.8 -iron:location@1.0.9 -iron:middleware-stack@1.0.9 -iron:router@1.0.9 -iron:url@1.0.9 jquery@1.11.3_2 json@1.0.3 +kadira:blaze-layout@2.0.0 +kadira:flow-router@2.3.0 kenton:accounts-sandstorm@0.1.4 launch-screen@1.0.2 less@1.0.14 @@ -65,6 +61,7 @@ meteor@1.1.6 meteor-platform@1.2.2 meteorhacks:aggregate@1.2.1 meteorhacks:collection-utils@1.2.0 +meteorhacks:picker@1.0.3 meteorhacks:subs-manager@1.5.2 meteorspark:util@0.2.0 minifiers@1.1.5 @@ -115,7 +112,8 @@ ui@1.0.6 underscore@1.0.3 url@1.0.4 useraccounts:core@1.12.2 -useraccounts:iron-routing@1.12.2 +useraccounts:flow-routing@1.12.2 useraccounts:unstyled@1.12.2 webapp@1.2.0 webapp-hashing@1.0.3 +zimme:active-route@2.3.1 diff --git a/client/components/boards/boardBody.jade b/client/components/boards/boardBody.jade index 12fc0e36..3d6667ae 100644 --- a/client/components/boards/boardBody.jade +++ b/client/components/boards/boardBody.jade @@ -1,29 +1,25 @@ -//- - XXX This template can't be transformed into a component because it is - included by iron-router. That's a bug. - See https://github.com/peerlibrary/meteor-blaze-components/issues/44 template(name="board") - +boardComponent - -template(name="boardComponent") - if this - .board-wrapper(class=colorClass) - .board-canvas( - class=sidebarSize - class="{{#if MultiSelection.isActive}}is-multiselection-active{{/if}}" - class="{{#if draggingActive.get}}is-dragging-active{{/if}}") - if showOverlay.get - .board-overlay - .lists.js-lists - each lists - +list(this) - if currentCardIsInThisList - +cardDetails(currentCard) - if currentUser.isBoardMember - +addListForm - +sidebar + if Template.subscriptionsReady + if currentBoard + .board-wrapper(class=currentBoard.colorClass) + .board-canvas( + class=currentBoard.sidebarSize + class="{{#if MultiSelection.isActive}}is-multiselection-active{{/if}}" + class="{{#if draggingActive.get}}is-dragging-active{{/if}}") + if showOverlay.get + .board-overlay + .lists.js-lists + each currentBoard.lists + +list(this) + if currentCardIsInThisList + +cardDetails(currentCard) + if currentUser.isBoardMember + +addListForm + +sidebar + else + +message(label="board-no-found") else - +message(label="board-no-found") + +spinner template(name="addListForm") .list.js-list.list-composer.js-list-composer diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index 876f2cd0..3757eff9 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -1,11 +1,17 @@ +var boardSubsManager = new SubsManager(); + BlazeComponent.extendComponent({ template: function() { - return 'boardComponent'; + return 'board'; }, onCreated: function() { this.draggingActive = new ReactiveVar(false); this.showOverlay = new ReactiveVar(false); + + // XXX The boardId should be readed from some sort the component "props", + // unfortunatly, Blaze doesn't have this notion. + boardSubsManager.subscribe('board', Session.get('currentBoard')); }, openNewListForm: function() { @@ -67,7 +73,7 @@ BlazeComponent.extendComponent({ } }; - if (! Meteor.userId() || ! Meteor.user().isBoardMember()) + if (! Meteor.user() || ! Meteor.user().isBoardMember()) return; self.$(lists).sortable({ @@ -101,7 +107,8 @@ BlazeComponent.extendComponent({ // If there is no data in the board (ie, no lists) we autofocus the list // creation form by clicking on the corresponding element. - if (self.data().lists().count() === 0) { + var currentBoard = Boards.findOne(Session.get('currentBoard')); + if (currentBoard.lists().count() === 0) { this.openNewListForm(); } }, @@ -121,7 +128,7 @@ BlazeComponent.extendComponent({ } }]; } -}).register('boardComponent'); +}).register('board'); BlazeComponent.extendComponent({ template: function() { diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index 3847cd93..9ec79227 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -1,20 +1,20 @@ template(name="headerBoard") h1.header-board-menu a(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}") - = title + = currentBoard.title .board-header-btns.left unless isSandstorm if currentUser a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}" - title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") - i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") + title="{{#if currentBoard.isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") + i.fa(class="fa-star{{#unless currentBoard.isStarred}}-o{{/unless}}") if showStarCounter - span {{_ 'board-nb-stars' stars}} + span {{_ 'board-nb-stars' currentBoard.stars}} a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}") - i.fa(class="{{#if isPublic}}fa-globe{{else}}fa-lock{{/if}}") - span {{_ permission}} + i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") + span {{_ currentBoard.permission}} .board-header-btns.right a.board-header-btn.js-open-filter-view( diff --git a/client/components/boards/boardList.jade b/client/components/boards/boardList.jade index e92cad2d..f0dc808f 100644 --- a/client/components/boards/boardList.jade +++ b/client/components/boards/boardList.jade @@ -1,16 +1,9 @@ -//- - XXX This template can't be transformed into a component because it is - included by iron-router. That's a bug. - See https://github.com/peerlibrary/meteor-blaze-components/issues/44 -template(name="boards") - +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 route='Board' boardId=_id }}") + a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") span.details span.board-list-item-name= title i.fa.fa-star-o.js-star-board( diff --git a/client/components/boards/router.js b/client/components/boards/router.js deleted file mode 100644 index 1c485225..00000000 --- a/client/components/boards/router.js +++ /dev/null @@ -1,58 +0,0 @@ -Meteor.subscribe('boards'); - -var boardSubsManager = new SubsManager(); - -Router.route('/boards', { - name: 'Boards', - template: 'boards', - authenticated: true, - onBeforeAction: function() { - Session.set('currentBoard', ''); - Filter.reset(); - this.next(); - } -}); - -Router.route('/boards/:_id/:slug', { - name: 'Board', - template: 'board', - onAfterAction: function() { - // XXX We probably shouldn't rely on Session - Session.set('sidebarIsOpen', true); - Session.set('menuWidgetIsOpen', false); - }, - waitOn: function() { - var params = this.params; - Session.set('currentBoard', params._id); - Session.set('currentCard', null); - - return boardSubsManager.subscribe('board', params._id, params.slug); - }, - data: function() { - return Boards.findOne(this.params._id); - } -}); - -Router.route('/boards/:boardId/:slug/:cardId', { - name: 'Card', - template: 'board', - noEscapeActions: true, - onAfterAction: function() { - Tracker.nonreactive(function() { - if (! Session.get('currentCard') && Sidebar) { - Sidebar.hide(); - } - }); - EscapeActions.executeUpTo('popup'); - var params = this.params; - Session.set('currentBoard', params.boardId); - Session.set('currentCard', params.cardId); - }, - waitOn: function() { - var params = this.params; - return boardSubsManager.subscribe('board', params.boardId, params.slug); - }, - data: function() { - return Boards.findOne(this.params.boardId); - } -}); diff --git a/client/components/lists/main.js b/client/components/lists/main.js index c4e38c46..e6491f0a 100644 --- a/client/components/lists/main.js +++ b/client/components/lists/main.js @@ -21,7 +21,7 @@ BlazeComponent.extendComponent({ // comment below provides further details. onRendered: function() { var self = this; - if (! Meteor.userId() || ! Meteor.user().isBoardMember()) + if (! Meteor.user() || ! Meteor.user().isBoardMember()) return; var boardComponent = self.componentParent(); diff --git a/client/components/main/header.jade b/client/components/main/header.jade index 510ef484..1185da85 100644 --- a/client/components/main/header.jade +++ b/client/components/main/header.jade @@ -10,13 +10,13 @@ template(name="header") #header-quick-access ul li - +linkTo(route="Boards") + a(href="{{pathFor 'home'}}") span.fa.fa-home | All boards each currentUser.starredBoards li.separator - li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}") - +linkTo(route="Board" data=this) + a(href="{{pathFor 'board' id=_id slug=slug}}") = title else li.current Star a board to add a shortcut in this bar. diff --git a/client/components/main/layouts.jade b/client/components/main/layouts.jade index 8e6ae941..2dd3b2f2 100644 --- a/client/components/main/layouts.jade +++ b/client/components/main/layouts.jade @@ -8,15 +8,15 @@ template(name="userFormsLayout") section.auth-layout h1.at-form-landing-logo img(src="/logo.png" title="LibreBoard") - +yield + +Template.dynamic(template=content) template(name="defaultLayout") #surface +header #content - +yield + +Template.dynamic(template=content) -template(name="notfound") +template(name="notFound") +message(label='page-not-found') template(name="message") diff --git a/client/components/main/layouts.js b/client/components/main/layouts.js new file mode 100644 index 00000000..5dbd8c91 --- /dev/null +++ b/client/components/main/layouts.js @@ -0,0 +1,5 @@ +Meteor.subscribe('boards'); + +Template.userFormsLayout.onRendered(function() { + EscapeActions.executeAll(); +}); diff --git a/client/components/main/router.js b/client/components/main/router.js deleted file mode 100644 index bae832e8..00000000 --- a/client/components/main/router.js +++ /dev/null @@ -1,5 +0,0 @@ -Router.route('/', { - name: 'Home', - redirectLoggedInUsers: true, - authenticated: true -}); diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index e4937bec..701e176b 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -162,7 +162,7 @@ Template.labelsWidget.events({ // fields of the current board document. var draggableMembersLabelsWidgets = function() { var self = this; - if (! Meteor.userId() || ! Meteor.user().isBoardMember()) + if (! Meteor.user() || ! Meteor.user().isBoardMember()) return; self.autorun(function() { diff --git a/client/components/sidebar/sidebarArchives.jade b/client/components/sidebar/sidebarArchives.jade index d2bd5d7b..2e42de6a 100644 --- a/client/components/sidebar/sidebarArchives.jade +++ b/client/components/sidebar/sidebarArchives.jade @@ -10,7 +10,7 @@ template(name="archivesSidebar") | - a.js-delete-card Delete if cardIsInArchivedList - p.quiet.small (warning: this card is in an archived list) <br> + p.quiet.small (warning: this card is in an archived list) else p.no-items-message No archived cards. diff --git a/client/components/users/router.js b/client/components/users/router.js deleted file mode 100644 index 955f0494..00000000 --- a/client/components/users/router.js +++ /dev/null @@ -1,15 +0,0 @@ -Router.route('/profile/:username', { - name: 'Profile', - template: 'profile', - waitOn: function() { - return Meteor.subscribe('profile', this.params.username); - }, - data: function() { - var params = this.params; - return { - profile: function() { - return Users.findOne({ username: params.username }); - } - }; - } -}); diff --git a/client/config/accounts.js b/client/config/accounts.js index e12dd8bc..3852e580 100644 --- a/client/config/accounts.js +++ b/client/config/accounts.js @@ -9,20 +9,25 @@ AccountsTemplates.addFields([{ }, emailField, passwordField]); AccountsTemplates.configure({ + defaultLayout: 'userFormsLayout', + defaultContentRegion: 'content', confirmPassword: false, enablePasswordChange: true, sendVerificationEmail: true, showForgotPasswordLink: true, onLogoutHook: function() { - Router.go('Home'); + var homePage = 'home'; + if (FlowRouter.getRouteName() === homePage) { + FlowRouter.reload(); + } else { + FlowRouter.go(homePage); + } } }); _.each(['signIn', 'signUp', 'resetPwd', 'forgotPwd', 'enrollAccount'], function(routeName) { - AccountsTemplates.configureRoute(routeName, { - layoutTemplate: 'userFormsLayout' - }); + AccountsTemplates.configureRoute(routeName); }); // We display the form to change the password in a popup window that already diff --git a/client/config/router.js b/client/config/router.js index 97871e23..e251aea0 100644 --- a/client/config/router.js +++ b/client/config/router.js @@ -1,44 +1,57 @@ -// XXX Switch to Flow-Router? -var previousRoute; - -Router.configure({ - loadingTemplate: 'spinner', - notFoundTemplate: 'notfound', - layoutTemplate: 'defaultLayout', - - onBeforeAction: function() { - var options = this.route.options; - - var loggedIn = Tracker.nonreactive(function() { - return !! Meteor.userId(); - }); - - // Redirect logged in users to Boards view when they try to open Login or - // signup views. - if (loggedIn && options.redirectLoggedInUsers) { - return this.redirect('Boards'); - } - - // Authenticated - if (! loggedIn && options.authenticated) { - return this.redirect('atSignIn'); - } - - // We want to execute our EscapeActions.executeUpTo method any time the - // route is changed, but not if the stays the same but only the parameters - // change (eg when a user is navigation from a card A to a card B). Iron- - // Router onBeforeAction is a reactive context (which is a bad desig choice - // as explained in - // https://github.com/meteorhacks/flow-router#routercurrent-is-evil) so we - // need to use Tracker.nonreactive - Tracker.nonreactive(function() { - if (! options.noEscapeActions && - ! (previousRoute && previousRoute.options.noEscapeActions)) - EscapeActions.executeAll(); - }); - - previousRoute = this.route; - - this.next(); +FlowRouter.route('/', { + name: 'home', + triggersEnter: [AccountsTemplates.ensureSignedIn], + action: function() { + EscapeActions.executeAll(); + Filter.reset(); + + Session.set('currentBoard', ''); + + BlazeLayout.render('defaultLayout', { content: 'boardList' }); + } +}); + +FlowRouter.route('/b/:id/:slug', { + name: 'board', + action: function(params) { + EscapeActions.executeAll(); + + Session.set('currentBoard', params.id); + Session.set('currentCard', null); + + BlazeLayout.render('defaultLayout', { content: 'board' }); + } +}); + +FlowRouter.route('/b/:boardId/:slug/:cardId', { + name: 'card', + action: function(params) { + Session.set('currentBoard', params.boardId); + Session.set('currentCard', params.cardId); + EscapeActions.executeUpTo('popup'); + + BlazeLayout.render('defaultLayout', { content: 'board' }); + } +}); + +FlowRouter.notFound = { + action: function() { + BlazeLayout.render('defaultLayout', { content: 'notFound' }); } +} + +// We maintain a list of redirections to ensure that we don't break old URLs +// when we change our routing scheme. +var redirections = { + '/boards': '/', + '/boards/:id/:slug': '/b/:id/:slug', + '/boards/:id/:slug/:cardId': '/b/:id/:slug/:cardId' +}; + +_.each(redirections, function(newPath, oldPath) { + FlowRouter.route(oldPath, { + triggersEnter: [function(context, redirect) { + redirect(FlowRouter.path(newPath, context.params)); + }] + }); }); diff --git a/client/lib/utils.js b/client/lib/utils.js index 121b3c2b..c6a9adc5 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -2,8 +2,8 @@ Utils = { // XXX We should remove these two methods goBoardId: function(_id) { var board = Boards.findOne(_id); - return board && Router.go('Board', { - _id: board._id, + return board && FlowRouter.go('board', { + id: board._id, slug: board.slug }); }, @@ -11,7 +11,7 @@ Utils = { goCardId: function(_id) { var card = Cards.findOne(_id); var board = Boards.findOne(card.boardId); - return board && Router.go('Card', { + return board && FlowRouter.go('card', { cardId: card._id, boardId: board._id, slug: board.slug diff --git a/collections/boards.js b/collections/boards.js index d0507dc4..ade70466 100644 --- a/collections/boards.js +++ b/collections/boards.js @@ -131,7 +131,7 @@ Boards.helpers({ return Activities.find({ boardId: this._id }, { sort: { createdAt: -1 }}); }, absoluteUrl: function() { - return Router.path('Board', { boardId: this._id, slug: this.slug }); + return FlowRouter.path('board', { id: this._id, slug: this.slug }); }, colorClass: function() { return 'board-color-' + this.color; diff --git a/collections/cards.js b/collections/cards.js index 92a3f618..d9f1bf6e 100644 --- a/collections/cards.js +++ b/collections/cards.js @@ -143,7 +143,7 @@ Cards.helpers({ }, absoluteUrl: function() { var board = this.board(); - return Router.path('Card', { + return FlowRouter.path('card', { boardId: board._id, slug: board.slug, cardId: this._id diff --git a/sandstorm.js b/sandstorm.js index b2b4d88b..d565df62 100644 --- a/sandstorm.js +++ b/sandstorm.js @@ -30,23 +30,23 @@ if (isSandstorm && Meteor.isServer) { // Redirect the user to the hard-coded board. On the first launch the user // will be redirected to the board before its creation. But that’s not a // problem thanks to the reactive board publication. We used to do this - // redirection on the client side but that was sometime visible on loading, + // redirection on the client side but that was sometimes visible on loading, // and the home page was accessible by pressing the back button of the // browser, a server-side redirection solves both of these issues. // // XXX Maybe sandstorm manifest could provide some kind of "home url"? - Router.route('/', function() { - var base = this.request.headers['x-sandstorm-base-path']; + Picker.route('/', function(params, request, response) { + var base = request.headers['x-sandstorm-base-path']; // XXX If this routing scheme changes, this will break. We should generation // the location url using the router, but at the time of writting, the // router is only accessible on the client. var path = '/boards/' + sandstormBoard._id + '/' + sandstormBoard.slug; - this.response.writeHead(301, { + response.writeHead(301, { Location: base + path }); - this.response.end(); - }, { where: 'server' }); + response.end(); + }); // On the first launch of the instance a user is automatically created thanks // to the `accounts-sandstorm` package. After its creation we insert the diff --git a/server/publications/boards.js b/server/publications/boards.js index 103e9080..15825952 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -30,14 +30,12 @@ Meteor.publish('boards', function() { }); }); -Meteor.publishComposite('board', function(boardId, slug) { +Meteor.publishComposite('board', function(boardId) { check(boardId, String); - check(slug, String); return { find: function() { return Boards.find({ _id: boardId, - slug: slug, archived: false, // If the board is not public the user has to be a member of it to see // it. |