From 5813352439b9b30708f347e7ba2b1c65d5037fda Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Tue, 14 Jun 2016 12:50:16 +0800 Subject: [PATCH 1/3] FEATURE: Add new API to add a toolbar popup menu button. --- .../discourse/controllers/composer.js.es6 | 39 +++++++++++++++++++ .../discourse/lib/plugin-api.js.es6 | 21 ++++++++++ .../discourse/templates/composer.hbs | 10 +++-- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6 index 5da1006830d..18784fa01e8 100644 --- a/app/assets/javascripts/discourse/controllers/composer.js.es6 +++ b/app/assets/javascripts/discourse/controllers/composer.js.es6 @@ -42,6 +42,12 @@ function loadDraft(store, opts) { } } +const _popupMenuOptionsCallbacks = []; + +export function addPopupMenuOptionsCallback(callback) { + _popupMenuOptionsCallbacks.push(callback); +} + export default Ember.Controller.extend({ needs: ['modal', 'topic', 'application'], replyAsNewTopicDraft: Em.computed.equal('model.draftKey', Composer.REPLY_AS_NEW_TOPIC_KEY), @@ -56,6 +62,20 @@ export default Ember.Controller.extend({ topic: null, linkLookup: null, + init() { + this._super(); + const self = this + + addPopupMenuOptionsCallback(function() { + return { + action: 'toggleWhisper', + icon: 'eye-slash', + label: 'composer.toggle_whisper', + condition: "canWhisper" + }; + }); + }, + showToolbar: Em.computed({ get(){ const keyValueStore = this.container.lookup('key-value-store:main'); @@ -92,6 +112,25 @@ export default Ember.Controller.extend({ return currentUser && currentUser.get('staff') && this.siteSettings.enable_whispers && action === Composer.REPLY; }, + @computed("model.composeState") + popupMenuOptions(composeState) { + const self = this; + + if (composeState === 'open') { + return _popupMenuOptionsCallbacks.map(callback => { + let option = callback(); + + if (option.condition) { + option.condition = self.get(option.condition); + } else { + option.condition = true; + } + + return option; + }); + } + }, + showWarning: function() { if (!Discourse.User.currentProp('staff')) { return false; } diff --git a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 index b7e3eb040ec..8665e446899 100644 --- a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 +++ b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 @@ -10,6 +10,7 @@ import { onPageChange } from 'discourse/lib/page-tracker'; import { preventCloak } from 'discourse/widgets/post-stream'; import { h } from 'virtual-dom'; import { addFlagProperty } from 'discourse/components/site-header'; +import { addPopupMenuOptionsCallback } from 'discourse/controllers/composer'; class PluginApi { constructor(version, container) { @@ -224,6 +225,26 @@ class PluginApi { addToolbarCallback(callback); } + /** + * Add a new button in the options popup menu. + * + * Example: + * + * ``` + * api.addToolbarPopupMenuOptionsCallback(function(controller) { + * return { + * action: 'toggleWhisper', + * icon: 'eye-slash', + * label: 'composer.toggle_whisper', + * condition: "canWhisper" + * }; + * }); + * ``` + **/ + addToolbarPopupMenuOptionsCallback(callback) { + addPopupMenuOptionsCallback(callback); + } + /** * A hook that is called when the post stream is removed from the DOM. * This advanced hook should be used if you end up wiring up any diff --git a/app/assets/javascripts/discourse/templates/composer.hbs b/app/assets/javascripts/discourse/templates/composer.hbs index 9bf668db795..2e3c6636b97 100644 --- a/app/assets/javascripts/discourse/templates/composer.hbs +++ b/app/assets/javascripts/discourse/templates/composer.hbs @@ -3,9 +3,13 @@ {{#if currentUser.staff}} {{#popup-menu visible=optionsVisible hide="hideOptions" title="composer.options"}} -
  • - {{d-button action="toggleWhisper" icon="eye-slash" label="composer.toggle_whisper"}} -
  • + {{#each popupMenuOptions as |option|}} + {{#if option.condition}} +
  • + {{d-button action=option.action icon=option.icon label=option.label}} +
  • + {{/if}} + {{/each}} {{/popup-menu}} {{/if}} From 8d46727d670801f61f3c8cca56497bdbf5006014 Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Mon, 13 Jun 2016 18:21:14 +0800 Subject: [PATCH 2/3] FEATURE: Poll UI Builder. --- .../components/composer-editor.js.es6 | 9 +- .../discourse/controllers/composer.js.es6 | 8 +- .../discourse/templates/composer.hbs | 3 +- .../controllers/poll-ui-builder.js.es6 | 158 ++++++++++++ .../templates/modals/poll-ui-builder.hbs | 57 +++++ .../initializers/add-poll-ui-builder.js.es6 | 30 +++ .../javascripts/views/poll-ui-builder.js.es6 | 8 + .../stylesheets/common/poll-ui-builder.scss | 18 ++ plugins/poll/config/locales/client.en.yml | 23 ++ plugins/poll/plugin.rb | 1 + .../controllers/poll-ui-builder-test.js.es6 | 225 ++++++++++++++++++ 11 files changed, 529 insertions(+), 11 deletions(-) create mode 100644 plugins/poll/assets/javascripts/controllers/poll-ui-builder.js.es6 create mode 100644 plugins/poll/assets/javascripts/discourse/templates/modals/poll-ui-builder.hbs create mode 100644 plugins/poll/assets/javascripts/initializers/add-poll-ui-builder.js.es6 create mode 100644 plugins/poll/assets/javascripts/views/poll-ui-builder.js.es6 create mode 100644 plugins/poll/assets/stylesheets/common/poll-ui-builder.scss create mode 100644 plugins/poll/test/javascripts/controllers/poll-ui-builder-test.js.es6 diff --git a/app/assets/javascripts/discourse/components/composer-editor.js.es6 b/app/assets/javascripts/discourse/components/composer-editor.js.es6 index 76d89193cbb..0b5d9c4e6f5 100644 --- a/app/assets/javascripts/discourse/components/composer-editor.js.es6 +++ b/app/assets/javascripts/discourse/components/composer-editor.js.es6 @@ -362,7 +362,7 @@ export default Ember.Component.extend({ this._resetUpload(true); }, - showOptions() { + showOptions(toolbarEvent) { // long term we want some smart positioning algorithm in popup-menu // the problem is that positioning in a fixed panel is a nightmare // cause offsetParent can end up returning a fixed element and then @@ -388,9 +388,8 @@ export default Ember.Component.extend({ left = replyWidth - popupWidth - 40; } - this.sendAction('showOptions', { position: "absolute", - left: left, - top: top }); + this.sendAction('showOptions', toolbarEvent, + { position: "absolute", left, top }); }, showUploadModal(toolbarEvent) { @@ -420,7 +419,7 @@ export default Ember.Component.extend({ sendAction: 'showUploadModal' }); - if (this.get('canWhisper')) { + if (this.get("popupMenuOptions").some(option => option.condition)) { toolbar.addButton({ id: 'options', group: 'extras', diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6 index 18784fa01e8..8f4b16701f6 100644 --- a/app/assets/javascripts/discourse/controllers/composer.js.es6 +++ b/app/assets/javascripts/discourse/controllers/composer.js.es6 @@ -64,7 +64,6 @@ export default Ember.Controller.extend({ init() { this._super(); - const self = this addPopupMenuOptionsCallback(function() { return { @@ -114,14 +113,12 @@ export default Ember.Controller.extend({ @computed("model.composeState") popupMenuOptions(composeState) { - const self = this; - if (composeState === 'open') { return _popupMenuOptionsCallbacks.map(callback => { let option = callback(); if (option.condition) { - option.condition = self.get(option.condition); + option.condition = this.get(option.condition); } else { option.condition = true; } @@ -193,7 +190,8 @@ export default Ember.Controller.extend({ this.toggleProperty('showToolbar'); }, - showOptions(loc) { + showOptions(toolbarEvent, loc) { + this.set('toolbarEvent', toolbarEvent); this.appEvents.trigger('popup-menu:open', loc); this.set('optionsVisible', true); }, diff --git a/app/assets/javascripts/discourse/templates/composer.hbs b/app/assets/javascripts/discourse/templates/composer.hbs index 2e3c6636b97..06f01ee8367 100644 --- a/app/assets/javascripts/discourse/templates/composer.hbs +++ b/app/assets/javascripts/discourse/templates/composer.hbs @@ -6,7 +6,7 @@ {{#each popupMenuOptions as |option|}} {{#if option.condition}}
  • - {{d-button action=option.action icon=option.icon label=option.label}} + {{d-button action=option.action icon=option.icon label=option.label}}
  • {{/if}} {{/each}} @@ -90,6 +90,7 @@ composer=model lastValidatedAt=lastValidatedAt canWhisper=canWhisper + popupMenuOptions=popupMenuOptions draftStatus=model.draftStatus isUploading=isUploading groupsMentioned="groupsMentioned" diff --git a/plugins/poll/assets/javascripts/controllers/poll-ui-builder.js.es6 b/plugins/poll/assets/javascripts/controllers/poll-ui-builder.js.es6 new file mode 100644 index 00000000000..6d10e459d4b --- /dev/null +++ b/plugins/poll/assets/javascripts/controllers/poll-ui-builder.js.es6 @@ -0,0 +1,158 @@ +import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; + +export default Ember.Controller.extend({ + needs: ['modal'], + + init() { + this._super(); + this._setupPoll(); + }, + + @computed + pollTypes() { + return [I18n.t("poll.ui_builder.poll_type.number"), I18n.t("poll.ui_builder.poll_type.multiple")].map(type => { + return { name: type, value: type }; + }); + }, + + @computed("pollType", "pollOptionsCount") + isMultiple(pollType, count) { + return (pollType === I18n.t("poll.ui_builder.poll_type.multiple")) && count > 0; + }, + + @computed("pollType") + isNumber(pollType) { + return pollType === I18n.t("poll.ui_builder.poll_type.number"); + }, + + @computed("isNumber", "isMultiple") + showMinMax(isNumber, isMultiple) { + return isNumber || isMultiple; + }, + + @computed("pollOptions") + pollOptionsCount(pollOptions) { + if (pollOptions.length === 0) return 0; + + let length = 0; + + pollOptions.split("\n").forEach(option => { + if (option.length !== 0) length += 1; + }); + + return length; + }, + + @observes("isMultiple", "isNumber", "pollOptionsCount") + _setPollMax() { + const isMultiple = this.get("isMultiple"); + const isNumber = this.get("isNumber"); + if (!isMultiple && !isNumber) return; + + if (isMultiple) { + this.set("pollMax", this.get("pollOptionsCount")); + } else if (isNumber) { + this.set("pollMax", this.siteSettings.poll_maximum_options); + } + }, + + @computed("isMultiple", "isNumber", "pollOptionsCount") + pollMinOptions(isMultiple, isNumber, count) { + if (!isMultiple && !isNumber) return; + + if (isMultiple) { + return this._comboboxOptions(1, count + 1); + } else if (isNumber) { + return this._comboboxOptions(1, this.siteSettings.poll_maximum_options + 1); + } + }, + + @computed("isMultiple", "isNumber", "pollOptionsCount", "pollMin", "pollStep") + pollMaxOptions(isMultiple, isNumber, count, pollMin, pollStep) { + if (!isMultiple && !isNumber) return; + var range = []; + const pollMinInt = parseInt(pollMin); + + if (isMultiple) { + return this._comboboxOptions(pollMinInt + 1, count + 1); + } else if (isNumber) { + const pollStepInt = parseInt(pollStep); + return this._comboboxOptions(pollMinInt + 1, pollMinInt + (this.siteSettings.poll_maximum_options * pollStepInt)); + } + }, + + @computed("isNumber", "pollMax") + pollStepOptions(isNumber, pollMax) { + if (!isNumber) return; + + return this._comboboxOptions(1, parseInt(pollMax) + 1); + }, + + @computed("isNumber", "showMinMax", "pollName", "pollType", "publicPoll", "pollOptions", "pollMin", "pollMax", "pollStep") + pollOutput(isNumber, showMinMax, pollName, pollType, publicPoll, pollOptions, pollMin, pollMax, pollStep) { + let pollHeader = '[poll'; + let output = ''; + + if (pollName) pollHeader += ` name=${pollName.replace(' ', '-')}`; + if (pollType) pollHeader += ` type=${pollType}`; + if (pollMin && showMinMax) pollHeader += ` min=${pollMin}`; + if (pollMax) pollHeader += ` max=${pollMax}`; + if (isNumber) pollHeader += ` step=${pollStep}`; + if (publicPoll) pollHeader += ' public=true'; + pollHeader += ']' + output += `${pollHeader}\n`; + + if (pollOptions.length > 0 && !isNumber) { + output += `${pollOptions.split("\n").map(option => `* ${option}`).join("\n")}\n`; + } + + output += '[/poll]'; + return output; + }, + + @computed("pollOptionsCount", "isNumber") + disableInsert(count, isNumber) { + if (isNumber) { + return false; + } else { + return count < 2; + } + }, + + @computed("disableInsert") + minNumOfOptionsValidation(disableInsert) { + let options = { ok: true }; + + if (disableInsert) { + options = { failed: true, reason: I18n.t("poll.ui_builder.help.options_count") }; + } + + return Discourse.InputValidation.create(options); + }, + + _comboboxOptions(start_index, end_index) { + return _.range(start_index, end_index).map(number => { + return { value: number, name: number } + }) + }, + + _setupPoll() { + this.setProperties({ + pollName: '', + pollNamePlaceholder: I18n.t("poll.ui_builder.poll_name.placeholder"), + pollType: null, + publicPoll: false, + pollOptions: '', + pollMin: 1, + pollMax: null, + pollStep: 1 + }); + }, + + actions: { + insertPoll() { + this.get("toolbarEvent").addText(this.get("pollOutput")); + this.send("closeModal"); + } + } +}); diff --git a/plugins/poll/assets/javascripts/discourse/templates/modals/poll-ui-builder.hbs b/plugins/poll/assets/javascripts/discourse/templates/modals/poll-ui-builder.hbs new file mode 100644 index 00000000000..c800db9aff9 --- /dev/null +++ b/plugins/poll/assets/javascripts/discourse/templates/modals/poll-ui-builder.hbs @@ -0,0 +1,57 @@ + + + diff --git a/plugins/poll/assets/javascripts/initializers/add-poll-ui-builder.js.es6 b/plugins/poll/assets/javascripts/initializers/add-poll-ui-builder.js.es6 new file mode 100644 index 00000000000..e1d88715ab0 --- /dev/null +++ b/plugins/poll/assets/javascripts/initializers/add-poll-ui-builder.js.es6 @@ -0,0 +1,30 @@ +import { withPluginApi } from 'discourse/lib/plugin-api'; +import showModal from 'discourse/lib/show-modal'; + +function initializePollUIBuilder(api) { + const ComposerController = api.container.lookup("controller:composer"); + + ComposerController.reopen({ + actions: { + showPollBuilder() { + showModal("poll-ui-builder").set("toolbarEvent", this.get("toolbarEvent")); + } + } + }); + + api.addToolbarPopupMenuOptionsCallback(function() { + return { + action: 'showPollBuilder', + icon: 'bar-chart-o', + label: 'poll.ui_builder.title' + }; + }); +} + +export default { + name: "add-poll-ui-builder", + + initialize() { + withPluginApi('0.1', initializePollUIBuilder); + } +}; diff --git a/plugins/poll/assets/javascripts/views/poll-ui-builder.js.es6 b/plugins/poll/assets/javascripts/views/poll-ui-builder.js.es6 new file mode 100644 index 00000000000..6ce0bf58203 --- /dev/null +++ b/plugins/poll/assets/javascripts/views/poll-ui-builder.js.es6 @@ -0,0 +1,8 @@ +import ModalBodyView from "discourse/views/modal-body"; + +export default ModalBodyView.extend({ + needs: ['modal'], + + templateName: 'modals/poll-ui-builder', + title: I18n.t("poll.ui_builder.title") +}); diff --git a/plugins/poll/assets/stylesheets/common/poll-ui-builder.scss b/plugins/poll/assets/stylesheets/common/poll-ui-builder.scss new file mode 100644 index 00000000000..a8467a3abbd --- /dev/null +++ b/plugins/poll/assets/stylesheets/common/poll-ui-builder.scss @@ -0,0 +1,18 @@ +.poll-ui-builder-form { + .input-group { + padding: 10px; + } + + label { + font-weight: bold; + display: inline; + } + + .combobox { + margin-right: 5px; + } + + .poll-options-min, .poll-options-max, .poll-options-step { + width: 70px !important; + } +} diff --git a/plugins/poll/config/locales/client.en.yml b/plugins/poll/config/locales/client.en.yml index 4344b85bd13..7113b022d74 100644 --- a/plugins/poll/config/locales/client.en.yml +++ b/plugins/poll/config/locales/client.en.yml @@ -68,3 +68,26 @@ en: error_while_toggling_status: "There was an error while toggling the status of this poll." error_while_casting_votes: "There was an error while casting your votes." error_while_fetching_voters: "There was an error while displaying the voters." + + ui_builder: + title: Poll Builder + insert: Insert Poll + reset: Reset Poll + help: + options_count: You must provide a minimum of 2 options. + poll_name: + label: Poll Name + placeholder: Enter Poll Name + poll_type: + label: Poll Type + regular: regular + multiple: multiple + number: number + poll_config: + max: Max + min: Min + step: Step + poll_public: + label: Make Public Poll + poll_options: + label: "Poll Choices: (one option per line)" diff --git a/plugins/poll/plugin.rb b/plugins/poll/plugin.rb index 075be098317..da979c275ba 100644 --- a/plugins/poll/plugin.rb +++ b/plugins/poll/plugin.rb @@ -7,6 +7,7 @@ enabled_site_setting :poll_enabled register_asset "stylesheets/common/poll.scss" +register_asset "stylesheets/common/poll-ui-builder.scss" register_asset "stylesheets/desktop/poll.scss", :desktop register_asset "stylesheets/mobile/poll.scss", :mobile diff --git a/plugins/poll/test/javascripts/controllers/poll-ui-builder-test.js.es6 b/plugins/poll/test/javascripts/controllers/poll-ui-builder-test.js.es6 new file mode 100644 index 00000000000..fb4941838e3 --- /dev/null +++ b/plugins/poll/test/javascripts/controllers/poll-ui-builder-test.js.es6 @@ -0,0 +1,225 @@ +moduleFor("controller:poll-ui-builder", "controller:poll-ui-builder", { + needs: ['controller:modal'] +}); + +test("isMultiple", function() { + const controller = this.subject(); + + controller.setProperties({ + pollType: I18n.t("poll.ui_builder.poll_type.multiple"), + pollOptionsCount: 1 + }); + + equal(controller.get("isMultiple"), true, "it should be true"); + + controller.set("pollOptionsCount", 0); + + equal(controller.get("isMultiple"), false, "it should be false"); + + controller.setProperties({ pollType: "random", pollOptionsCount: 1 }); + + equal(controller.get("isMultiple"), false, "it should be false"); +}); + +test("isNumber", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + + controller.set("pollType", "random"); + + equal(controller.get("isNumber"), false, "it should be false"); + + controller.set("pollType", I18n.t("poll.ui_builder.poll_type.number")); + + equal(controller.get("isNumber"), true, "it should be true"); +}); + +test("showMinMax", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + + controller.setProperties({ + isNumber: true, + isMultiple: false + }); + + equal(controller.get("showMinMax"), true, "it should be true"); + + controller.setProperties({ + isNumber: false, + isMultiple: true + }); + + equal(controller.get("showMinMax"), true, "it should be true"); +}); + +test("pollOptionsCount", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + + controller.set("pollOptions", "1\n2\n") + + equal(controller.get("pollOptionsCount"), 2, "it should equal 2"); + + controller.set("pollOptions", "") + + equal(controller.get("pollOptionsCount"), 0, "it should equal 0"); +}); + +test("pollMinOptions", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + + controller.setProperties({ + isMultiple: true, + pollOptionsCount: 1 + }); + + deepEqual(controller.get("pollMinOptions"), [{ name: 1, value: 1 }], "it should return the right options"); + + controller.set("pollOptionsCount", 2); + + deepEqual(controller.get("pollMinOptions"), [ + { name: 1, value: 1 }, { name: 2, value: 2 } + ], "it should return the right options"); + + controller.set("isNumber", true); + controller.siteSettings.poll_maximum_options = 2; + + deepEqual(controller.get("pollMinOptions"), [ + { name: 1, value: 1 }, { name: 2, value: 2 } + ], "it should return the right options"); +}); + +test("pollMaxOptions", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + + controller.setProperties({ isMultiple: true, pollOptionsCount: 1, pollMin: 1 }); + + deepEqual(controller.get("pollMaxOptions"), [], "it should return the right options"); + + controller.set("pollOptionsCount", 2); + + deepEqual(controller.get("pollMaxOptions"), [ + { name: 2, value: 2 } + ], "it should return the right options"); + + controller.siteSettings.poll_maximum_options = 3; + controller.setProperties({ isMultiple: false, isNumber: true, pollStep: 2, pollMin: 1 }); + + deepEqual(controller.get("pollMaxOptions"), [ + { name: 2, value: 2 }, + { name: 3, value: 3 }, + { name: 4, value: 4 }, + { name: 5, value: 5 }, + { name: 6, value: 6 } + ], "it should return the right options"); +}); + +test("pollStepOptions", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + controller.siteSettings.poll_maximum_options = 3; + + controller.set("isNumber", false); + + equal(controller.get("pollStepOptions"), null, "is should return null"); + + controller.setProperties({ isNumber: true }); + + deepEqual(controller.get("pollStepOptions"), [ + { name: 1, value: 1 }, + { name: 2, value: 2 }, + { name: 3, value: 3 } + ], "it should return the right options"); +}); + +test("disableInsert", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + + controller.setProperties({ isNumber: true }); + + equal(controller.get("disableInsert"), false, "it should be false"); + + controller.setProperties({ isNumber: false, pollOptionsCount: 3 }); + + equal(controller.get("disableInsert"), false, "it should be false"); + + controller.setProperties({ isNumber: false, pollOptionsCount: 1 }); + + equal(controller.get("disableInsert"), true, "it should be true"); +}); + +test("number pollOutput", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + controller.siteSettings.poll_maximum_options = 20; + + controller.setProperties({ + isNumber: true, + pollType: I18n.t("poll.ui_builder.poll_type.number"), + pollMin: 1 + }); + + equal(controller.get("pollOutput"), "[poll type=number min=1 max=20 step=1]\n[/poll]", "it should return the right output"); + + controller.set("pollName", 'test'); + + equal(controller.get("pollOutput"), "[poll name=test type=number min=1 max=20 step=1]\n[/poll]", "it should return the right output"); + + controller.set("pollName", 'test poll'); + + equal(controller.get("pollOutput"), "[poll name=test-poll type=number min=1 max=20 step=1]\n[/poll]", "it should return the right output"); + + controller.set("pollStep", 2); + + equal(controller.get("pollOutput"), "[poll name=test-poll type=number min=1 max=20 step=2]\n[/poll]", "it should return the right output"); + + controller.set("publicPoll", true); + + equal(controller.get("pollOutput"), "[poll name=test-poll type=number min=1 max=20 step=2 public=true]\n[/poll]", "it should return the right output"); +}); + +test("regular pollOutput", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + controller.siteSettings.poll_maximum_options = 20; + + controller.set("pollOptions", "1\n2"); + + equal(controller.get("pollOutput"), "[poll]\n* 1\n* 2\n[/poll]", "it should return the right output"); + + controller.set("pollName", "test"); + + equal(controller.get("pollOutput"), "[poll name=test]\n* 1\n* 2\n[/poll]", "it should return the right output"); + + controller.set("publicPoll", "true"); + + equal(controller.get("pollOutput"), "[poll name=test public=true]\n* 1\n* 2\n[/poll]", "it should return the right output"); +}); + + +test("multiple pollOutput", function() { + const controller = this.subject(); + controller.siteSettings = Discourse.SiteSettings; + controller.siteSettings.poll_maximum_options = 20; + + controller.setProperties({ + isMultiple: true, + pollType: I18n.t("poll.ui_builder.poll_type.multiple"), + pollMin: 1, + pollOptions: "1\n2" + }); + + equal(controller.get("pollOutput"), "[poll type=multiple min=1 max=2]\n* 1\n* 2\n[/poll]", "it should return the right output"); + + controller.set("pollName", "test"); + + equal(controller.get("pollOutput"), "[poll name=test type=multiple min=1 max=2]\n* 1\n* 2\n[/poll]", "it should return the right output"); + + controller.set("publicPoll", "true"); + + equal(controller.get("pollOutput"), "[poll name=test type=multiple min=1 max=2 public=true]\n* 1\n* 2\n[/poll]", "it should return the right output"); +}); From ae5a033469bce7d2a054ff9c9e5bc09221388b77 Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Tue, 14 Jun 2016 16:11:45 +0800 Subject: [PATCH 3/3] Start checking eslint in plugins. --- .travis.yml | 1 + .../components/poll-results-number-voters.js.es6 | 1 - .../components/poll-results-standard-voters.js.es6 | 1 - .../javascripts/controllers/poll-ui-builder.js.es6 | 14 ++++---------- .../assets/javascripts/controllers/poll.js.es6 | 1 - plugins/poll/assets/javascripts/views/poll.js.es6 | 2 -- 6 files changed, 5 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 43ef9e81663..6a2ca9143a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,7 @@ before_install: - eslint app/assets/javascripts - eslint --ext .es6 app/assets/javascripts - eslint --ext .es6 test/javascripts + - eslint --ext .es6 plugins/**/assets/javascripts - eslint test/javascripts before_script: diff --git a/plugins/poll/assets/javascripts/components/poll-results-number-voters.js.es6 b/plugins/poll/assets/javascripts/components/poll-results-number-voters.js.es6 index e75ad84cbbf..412cc8acd20 100644 --- a/plugins/poll/assets/javascripts/components/poll-results-number-voters.js.es6 +++ b/plugins/poll/assets/javascripts/components/poll-results-number-voters.js.es6 @@ -1,5 +1,4 @@ import computed from 'ember-addons/ember-computed-decorators'; -import User from 'discourse/models/user'; import PollVoters from 'discourse/plugins/poll/components/poll-voters'; export default PollVoters.extend({ diff --git a/plugins/poll/assets/javascripts/components/poll-results-standard-voters.js.es6 b/plugins/poll/assets/javascripts/components/poll-results-standard-voters.js.es6 index 80dc1ef8b3f..50332f4aeff 100644 --- a/plugins/poll/assets/javascripts/components/poll-results-standard-voters.js.es6 +++ b/plugins/poll/assets/javascripts/components/poll-results-standard-voters.js.es6 @@ -1,5 +1,4 @@ import computed from 'ember-addons/ember-computed-decorators'; -import User from 'discourse/models/user'; import PollVoters from 'discourse/plugins/poll/components/poll-voters'; export default PollVoters.extend({ diff --git a/plugins/poll/assets/javascripts/controllers/poll-ui-builder.js.es6 b/plugins/poll/assets/javascripts/controllers/poll-ui-builder.js.es6 index 6d10e459d4b..ce139cd4597 100644 --- a/plugins/poll/assets/javascripts/controllers/poll-ui-builder.js.es6 +++ b/plugins/poll/assets/javascripts/controllers/poll-ui-builder.js.es6 @@ -70,7 +70,6 @@ export default Ember.Controller.extend({ @computed("isMultiple", "isNumber", "pollOptionsCount", "pollMin", "pollStep") pollMaxOptions(isMultiple, isNumber, count, pollMin, pollStep) { if (!isMultiple && !isNumber) return; - var range = []; const pollMinInt = parseInt(pollMin); if (isMultiple) { @@ -84,7 +83,6 @@ export default Ember.Controller.extend({ @computed("isNumber", "pollMax") pollStepOptions(isNumber, pollMax) { if (!isNumber) return; - return this._comboboxOptions(1, parseInt(pollMax) + 1); }, @@ -99,7 +97,7 @@ export default Ember.Controller.extend({ if (pollMax) pollHeader += ` max=${pollMax}`; if (isNumber) pollHeader += ` step=${pollStep}`; if (publicPoll) pollHeader += ' public=true'; - pollHeader += ']' + pollHeader += ']'; output += `${pollHeader}\n`; if (pollOptions.length > 0 && !isNumber) { @@ -112,11 +110,7 @@ export default Ember.Controller.extend({ @computed("pollOptionsCount", "isNumber") disableInsert(count, isNumber) { - if (isNumber) { - return false; - } else { - return count < 2; - } + return isNumber ? false : (count < 2); }, @computed("disableInsert") @@ -132,8 +126,8 @@ export default Ember.Controller.extend({ _comboboxOptions(start_index, end_index) { return _.range(start_index, end_index).map(number => { - return { value: number, name: number } - }) + return { value: number, name: number }; + }); }, _setupPoll() { diff --git a/plugins/poll/assets/javascripts/controllers/poll.js.es6 b/plugins/poll/assets/javascripts/controllers/poll.js.es6 index 841a3beb8ab..acf63314c4f 100644 --- a/plugins/poll/assets/javascripts/controllers/poll.js.es6 +++ b/plugins/poll/assets/javascripts/controllers/poll.js.es6 @@ -147,7 +147,6 @@ export default Ember.Controller.extend({ }).then(results => { const poll = results.poll; const votes = results.vote; - const currentUser = this.currentUser; this.setProperties({ vote: votes, showResults: true }); this.set("model", Em.Object.create(poll)); diff --git a/plugins/poll/assets/javascripts/views/poll.js.es6 b/plugins/poll/assets/javascripts/views/poll.js.es6 index ac739b3f429..c9d6e632e34 100644 --- a/plugins/poll/assets/javascripts/views/poll.js.es6 +++ b/plugins/poll/assets/javascripts/views/poll.js.es6 @@ -1,5 +1,3 @@ -import { on } from "ember-addons/ember-computed-decorators"; - export default Em.View.extend({ templateName: "poll", classNames: ["poll"],