From b670a1ab36fcf514751e4b356487a96088dbbd24 Mon Sep 17 00:00:00 2001 From: Xavier Priour Date: Wed, 14 Oct 2015 22:09:32 +0200 Subject: Import single card: proper error handling --- client/components/lists/listHeader.jade | 2 ++ client/components/lists/listHeader.js | 62 +++++++++++++++++++++------------ i18n/en.i18n.json | 4 +++ models/import.js | 48 +++++++++++++------------ 4 files changed, 71 insertions(+), 45 deletions(-) diff --git a/client/components/lists/listHeader.jade b/client/components/lists/listHeader.jade index 922ac27b..e7b16912 100644 --- a/client/components/lists/listHeader.jade +++ b/client/components/lists/listHeader.jade @@ -32,6 +32,8 @@ template(name="listMoveCardsPopup") +boardLists template(name="listImportCardPopup") + if error.get + .warning {{_ error.get}} form label | {{_ 'card-json'}} diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js index 9aa26194..7db93618 100644 --- a/client/components/lists/listHeader.js +++ b/client/components/lists/listHeader.js @@ -49,30 +49,46 @@ Template.listActionPopup.events({ }, }); -Template.listImportCardPopup.events({ - submit(evt) { - // 1. get the json data out of the form and parse it - evt.preventDefault(); - const jsonData = $(evt.currentTarget).find('textarea').val(); - const firstCardDom = $(`#js-list-${this._id} .js-minicard:first`).get(0); - const sortIndex = Utils.calculateIndex(null, firstCardDom).base; - try { - const trelloCard = JSON.parse(jsonData); - const cardId = Meteor.call('importTrelloCard', trelloCard, this._id, sortIndex); - // In case the filter is active we need to add the newly inserted card in - // the list of exceptions -- cards that are not filtered. Otherwise the - // card will disappear instantly. - // See https://github.com/wekan/wekan/issues/80 - Filter.addException(cardId); - Popup.close(); - } catch(e) { - // XXX handle error - // this.error.set('avatar-too-big'); - console.log('Invalid JSON'); - return; - } + +BlazeComponent.extendComponent({ + events() { + return [{ + 'submit': (evt) => { + evt.preventDefault(); + const jsonData = $(evt.currentTarget).find('textarea').val(); + const firstCardDom = $(`#js-list-${this.currentData()._id} .js-minicard:first`).get(0); + const sortIndex = Utils.calculateIndex(null, firstCardDom).base; + let trelloCard; + try { + trelloCard = JSON.parse(jsonData); + } catch (e) { + console.log(e); + this.setError('error-json-malformed'); + return; + } + Meteor.call('importTrelloCard', trelloCard, this.currentData()._id, sortIndex, + (error, response) => { + if (error) { + console.log(error); + this.setError(error.error); + } else { + Filter.addException(response); + Popup.close(); + } + } + ); + } + },]; }, -}); + + onCreated() { + this.error = new ReactiveVar(''); + }, + + setError(error) { + this.error.set(error); + }, +}).register('listImportCardPopup'); Template.listMoveCardsPopup.events({ 'click .js-select-list'() { diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 40e21e53..9f383ae4 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -112,6 +112,10 @@ "editLabelPopup-title": "Change Label", "editProfilePopup-title": "Edit Profile", "email": "Email", + "error-board-notAMember": "You need to be a member of this board to do that", + "error-json-malformed": "Your text is not valid JSON", + "error-json-schema": "Your JSON data does not include the proper information in the correct format", + "error-list-doesNotExist": "This list does not exist", "filter": "Filter", "filter-cards": "Filter Cards", "filter-clear": "Clear filter", diff --git a/models/import.js b/models/import.js index a76bbc5f..51206ea3 100644 --- a/models/import.js +++ b/models/import.js @@ -1,40 +1,44 @@ Meteor.methods({ - /** - * - */ importTrelloCard(trelloCard, listId, sortIndex) { // 1. check parameters are ok from a syntax point of view DateString = Match.Where(function (dateAsString) { check(dateAsString, String); return moment(dateAsString, moment.ISO_8601).isValid(); }); - check(trelloCard, Match.ObjectIncluding({ - name: String, - desc: String, - closed: Boolean, - dateLastActivity: DateString, - labels: [Match.ObjectIncluding({ + try { + check(trelloCard, Match.ObjectIncluding({ name: String, - color: String, - })], - actions: [Match.ObjectIncluding({ - type: String, - date: DateString, - data: Object, - })], - members: [Object], - })); - check(listId, String); - check(sortIndex, Number); + desc: String, + closed: Boolean, + dateLastActivity: DateString, + labels: [Match.ObjectIncluding({ + name: String, + color: String, + })], + actions: [Match.ObjectIncluding({ + type: String, + date: DateString, + data: Object, + })], + members: [Object], + })); + check(listId, String); + check(sortIndex, Number); + } catch(e) { + if(Meteor.isServer) { + console.log(e); + } + throw new Meteor.Error('error-json-schema'); + } // 2. check parameters are ok from a business point of view (exist & authorized) const list = Lists.findOne(listId); if(!list) { - throw 'exception-list-doesNotExist'; + throw new Meteor.Error('error-list-doesNotExist'); } if(Meteor.isServer) { if (!allowIsBoardMember(Meteor.userId(), Boards.findOne(list.boardId))) { - throw 'exception-board-notAMember'; + throw new Meteor.Error('error-board-notAMember'); } } -- cgit v1.2.3-1-g7c22