From bdb81191d77560dbab7ccdedbd06200defdadb37 Mon Sep 17 00:00:00 2001 From: David Taylor Date: Tue, 18 Jul 2017 16:17:03 +0100 Subject: [PATCH] New admin interface for improved channel definitions --- app/controllers/chat_controller.rb | 96 +++++++++++++++---- app/models/rule.rb | 2 +- app/routes/discourse_chat.rb | 9 +- app/serializers/channel_serializer.rb | 11 +++ app/serializers/rule_serializer.rb | 4 +- .../javascripts/admin/adapters/channel.js.es6 | 7 ++ .../admin/components/channel-details.js.es6 | 36 +++++++ .../admin/components/rule-row.js.es6 | 38 ++++++++ .../admin-plugins-chat-provider.js.es6 | 38 ++++---- .../admin-plugins-chat-edit-channel.js.es6 | 94 ++++++++++++++++++ .../admin-plugins-chat-edit-rule.js.es6 | 61 ------------ .../modals/admin-plugins-chat-test.js.es6 | 7 +- .../javascripts/admin/models/channel.js.es6 | 14 +++ assets/javascripts/admin/models/rule.js.es6 | 10 +- .../routes/admin-plugins-chat-provider.js.es6 | 12 ++- .../modal/admin-plugins-chat-edit-channel.hbs | 49 ++++++++++ .../modal/admin-plugins-chat-edit-rule.hbs | 87 ----------------- .../modal/admin-plugins-chat-test.hbs | 29 +----- .../templates/admin/plugins-chat-provider.hbs | 67 +------------ .../templates/components/channel-details.hbs | 40 ++++++++ .../templates/components/rule-row.hbs | 53 ++++++++++ .../stylesheets/chat-integration-admin.scss | 28 +++++- config/locales/client.en.yml | 29 +++--- plugin.rb | 1 + 24 files changed, 514 insertions(+), 308 deletions(-) create mode 100644 app/serializers/channel_serializer.rb create mode 100644 assets/javascripts/admin/adapters/channel.js.es6 create mode 100644 assets/javascripts/admin/components/channel-details.js.es6 create mode 100644 assets/javascripts/admin/components/rule-row.js.es6 create mode 100644 assets/javascripts/admin/controllers/modals/admin-plugins-chat-edit-channel.js.es6 delete mode 100644 assets/javascripts/admin/controllers/modals/admin-plugins-chat-edit-rule.js.es6 create mode 100644 assets/javascripts/admin/models/channel.js.es6 create mode 100644 assets/javascripts/admin/templates/modal/admin-plugins-chat-edit-channel.hbs delete mode 100644 assets/javascripts/admin/templates/modal/admin-plugins-chat-edit-rule.hbs create mode 100644 assets/javascripts/discourse/templates/components/channel-details.hbs create mode 100644 assets/javascripts/discourse/templates/components/rule-row.hbs diff --git a/app/controllers/chat_controller.rb b/app/controllers/chat_controller.rb index a692a30..43fbace 100644 --- a/app/controllers/chat_controller.rb +++ b/app/controllers/chat_controller.rb @@ -15,23 +15,19 @@ class DiscourseChat::ChatController < ApplicationController render json:providers, root: 'providers' end - def test_provider + def test begin - requested_provider = params[:provider] - channel = params[:channel] - topic_id = params[:topic_id] + channel_id = params[:channel_id].to_i + topic_id = params[:topic_id].to_i - provider = ::DiscourseChat::Provider.get_by_name(requested_provider) + channel = DiscourseChat::Channel.find(channel_id) - if provider.nil? or not ::DiscourseChat::Provider.is_enabled(provider) + provider = ::DiscourseChat::Provider.get_by_name(channel.provider) + + if not ::DiscourseChat::Provider.is_enabled(provider) raise Discourse::NotFound end - if defined? provider::PROVIDER_CHANNEL_REGEX - channel_regex = Regexp.new provider::PROVIDER_CHANNEL_REGEX - raise Discourse::InvalidParameters, 'Channel is not valid' if not channel_regex.match?(channel) - end - post = Topic.find(topic_id.to_i).posts.first provider.trigger_notification(post, channel) @@ -48,23 +44,91 @@ class DiscourseChat::ChatController < ApplicationController end end + def list_channels + providers = ::DiscourseChat::Provider.enabled_providers.map {|x| x::PROVIDER_NAME} + + requested_provider = params[:provider] + + if not providers.include? requested_provider + raise Discourse::NotFound + end + + channels = DiscourseChat::Channel.with_provider(requested_provider) + + render_serialized channels, DiscourseChat::ChannelSerializer, root: 'channels' + end + + def create_channel + begin + providers = ::DiscourseChat::Provider.enabled_providers.map {|x| x::PROVIDER_NAME} + + requested_provider = params[:channel][:provider] + + if not providers.include? requested_provider + raise Discourse::InvalidParameters, 'Provider is not valid' + end + + allowed_keys = DiscourseChat::Provider.get_by_name(requested_provider)::CHANNEL_PARAMETERS.map{|p| p[:key].to_sym} + + hash = params.require(:channel).permit(:provider, data:allowed_keys) + + channel = DiscourseChat::Channel.new(hash) + + if not channel.save(hash) + raise Discourse::InvalidParameters, 'Channel is not valid' + end + + render_serialized channel, DiscourseChat::ChannelSerializer, root: 'channel' + rescue Discourse::InvalidParameters => e + render json: {errors: [e.message]}, status: 422 + end + end + + def update_channel + begin + channel = DiscourseChat::Channel.find(params[:id].to_i) + # rule.error_key = nil # Reset any error on the rule + + allowed_keys = DiscourseChat::Provider.get_by_name(channel.provider)::CHANNEL_PARAMETERS.map{|p| p[:key].to_sym} + + hash = params.require(:channel).permit(data:allowed_keys) + + if not channel.update(hash) + raise Discourse::InvalidParameters, 'Channel is not valid' + end + + render_serialized channel, DiscourseChat::ChannelSerializer, root: 'channel' + rescue Discourse::InvalidParameters => e + render json: {errors: [e.message]}, status: 422 + end + end + + def destroy_channel + rule = DiscourseChat::Channel.find(params[:id].to_i) + + rule.destroy + + render json: success_json + end + + def list_rules providers = ::DiscourseChat::Provider.enabled_providers.map {|x| x::PROVIDER_NAME} requested_provider = params[:provider] - if providers.include? requested_provider - rules = DiscourseChat::Rule.with_provider(requested_provider) - else + if not providers.include? requested_provider raise Discourse::NotFound end + rules = DiscourseChat::Rule.with_provider(requested_provider) + render_serialized rules, DiscourseChat::RuleSerializer, root: 'rules' end def create_rule begin - hash = params.require(:rule).permit(:provider, :channel, :filter, :category_id, tags:[]) + hash = params.require(:rule).permit(:channel_id, :filter, :category_id, tags:[]) rule = DiscourseChat::Rule.new(hash) @@ -82,7 +146,7 @@ class DiscourseChat::ChatController < ApplicationController begin rule = DiscourseChat::Rule.find(params[:id].to_i) rule.error_key = nil # Reset any error on the rule - hash = params.require(:rule).permit(:provider, :channel, :filter, :category_id, tags:[]) + hash = params.require(:rule).permit(:filter, :category_id, tags:[]) if not rule.update(hash) raise Discourse::InvalidParameters, 'Rule is not valid' diff --git a/app/models/rule.rb b/app/models/rule.rb index 20623d9..3300c4e 100644 --- a/app/models/rule.rb +++ b/app/models/rule.rb @@ -17,7 +17,7 @@ class DiscourseChat::Rule < DiscourseChat::PluginModel def channel_valid? # Validate category - if not (channel_id.nil? or DiscourseChat::Channel.where(id: channel_id).exists?) + if not (DiscourseChat::Channel.where(id: channel_id).exists?) errors.add(:channel_id, "#{channel_id} is not a valid channel id") end end diff --git a/app/routes/discourse_chat.rb b/app/routes/discourse_chat.rb index 207b4e1..cf137e6 100644 --- a/app/routes/discourse_chat.rb +++ b/app/routes/discourse_chat.rb @@ -4,10 +4,15 @@ module DiscourseChat AdminEngine.routes.draw do get "" => "chat#respond" get '/providers' => "chat#list_providers" - post '/test' => "chat#test_provider" + post '/test' => "chat#test" + get '/channels' => "chat#list_channels" + post '/channels' => "chat#create_channel" + put '/channels/:id' => "chat#update_channel" + delete '/channels/:id' => "chat#destroy_channel" + get '/rules' => "chat#list_rules" - put '/rules' => "chat#create_rule" + post '/rules' => "chat#create_rule" put '/rules/:id' => "chat#update_rule" delete '/rules/:id' => "chat#destroy_rule" diff --git a/app/serializers/channel_serializer.rb b/app/serializers/channel_serializer.rb new file mode 100644 index 0000000..4022976 --- /dev/null +++ b/app/serializers/channel_serializer.rb @@ -0,0 +1,11 @@ +require_relative './rule_serializer' + +class DiscourseChat::ChannelSerializer < ApplicationSerializer + attributes :id, :provider, :data, :rules + + def rules + object.rules.map do |rule| + DiscourseChat::RuleSerializer.new(rule, root:false) + end + end +end \ No newline at end of file diff --git a/app/serializers/rule_serializer.rb b/app/serializers/rule_serializer.rb index 7ff023b..d8b3f77 100644 --- a/app/serializers/rule_serializer.rb +++ b/app/serializers/rule_serializer.rb @@ -1,3 +1,3 @@ -class DiscourseChat::RuleSerializer < ActiveModel::Serializer - attributes :id, :provider, :channel, :category_id, :tags, :filter, :error_key +class DiscourseChat::RuleSerializer < ApplicationSerializer + attributes :id, :channel_id, :category_id, :tags, :filter, :error_key end \ No newline at end of file diff --git a/assets/javascripts/admin/adapters/channel.js.es6 b/assets/javascripts/admin/adapters/channel.js.es6 new file mode 100644 index 0000000..8287b75 --- /dev/null +++ b/assets/javascripts/admin/adapters/channel.js.es6 @@ -0,0 +1,7 @@ +import buildPluginAdapter from 'admin/adapters/build-plugin'; +import Rule from 'discourse/plugins/discourse-chat-integration/admin/models/rule' + +export default buildPluginAdapter('chat').extend({ + + +}); \ No newline at end of file diff --git a/assets/javascripts/admin/components/channel-details.js.es6 b/assets/javascripts/admin/components/channel-details.js.es6 new file mode 100644 index 0000000..6e3be76 --- /dev/null +++ b/assets/javascripts/admin/components/channel-details.js.es6 @@ -0,0 +1,36 @@ +import { popupAjaxError } from 'discourse/lib/ajax-error'; + +export default Ember.Component.extend({ + classNames: ['channel-details'], + actions: { + refresh: function(){ + this.sendAction('refresh'); + }, + + delete(channel){ + bootbox.confirm(I18n.t("chat_integration.channel_delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), result => { + if (result) { + channel.destroyRecord().then(() => { + this.send('refresh'); + }).catch(popupAjaxError) + } + }); + }, + + edit(channel){ + this.sendAction('edit', channel) + }, + + test(channel){ + this.sendAction('test', channel) + }, + + createRule(channel){ + var newRule = this.get('store').createRecord('rule',{channel_id: channel.id}); + channel.rules.pushObject(newRule) + } + + + + } +}); \ No newline at end of file diff --git a/assets/javascripts/admin/components/rule-row.js.es6 b/assets/javascripts/admin/components/rule-row.js.es6 new file mode 100644 index 0000000..7622fa1 --- /dev/null +++ b/assets/javascripts/admin/components/rule-row.js.es6 @@ -0,0 +1,38 @@ +import { popupAjaxError } from 'discourse/lib/ajax-error'; + +export default Ember.Component.extend({ + tagName: 'tr', + editing: false, + + autoEdit: function(){ + if(!this.get('rule').id){ + this.set('editing', true); + } + }.on('init'), + + actions: { + edit: function(){ + this.set('editing', true); + }, + + cancel: function(){ + this.send('refresh'); + }, + + save: function(){ + this.get('rule').save().then(result => { + this.send('refresh'); + }).catch(popupAjaxError); + }, + + delete(rule){ + rule.destroyRecord().then(() => { + this.send('refresh'); + }).catch(popupAjaxError) + }, + + refresh: function(){ + this.sendAction('refresh'); + } + } +}); \ No newline at end of file diff --git a/assets/javascripts/admin/controllers/admin-plugins-chat-provider.js.es6 b/assets/javascripts/admin/controllers/admin-plugins-chat-provider.js.es6 index 5fd9341..335d400 100644 --- a/assets/javascripts/admin/controllers/admin-plugins-chat-provider.js.es6 +++ b/assets/javascripts/admin/controllers/admin-plugins-chat-provider.js.es6 @@ -7,42 +7,38 @@ import { popupAjaxError } from 'discourse/lib/ajax-error'; export default Ember.Controller.extend({ modalShowing: false, - + anyErrors: function(){ var anyErrors = false; - this.get('model.rules').forEach(function(rule){ - if(rule.error_key){ + this.get('model.channels').forEach(function(channel){ + if(channel.error_key){ anyErrors = true; } }); return anyErrors; - }.property('model.rules'), + }.property('model.channels'), actions:{ - create(){ + createChannel(){ this.set('modalShowing', true); - var model = {rule: this.store.createRecord('rule',{provider: this.get('model.provider').id}), provider:this.get('model.provider')}; - showModal('admin-plugins-chat-edit-rule', { model: model, admin: true }); + var model = {channel: this.store.createRecord('channel',{provider: this.get('model.provider').id, data:{}},), provider:this.get('model.provider')}; + showModal('admin-plugins-chat-edit-channel', { model: model, admin: true }); }, - edit(rule){ + editChannel(channel){ this.set('modalShowing', true); - var model = {rule: rule, provider:this.get('model.provider')}; - showModal('admin-plugins-chat-edit-rule', { model: model, admin: true }); - }, - delete(rule){ - const self = this; - rule.destroyRecord().then(function() { - self.send('refresh'); - }).catch(popupAjaxError) + var model = {channel: channel, provider: this.get('model.provider')}; + showModal('admin-plugins-chat-edit-channel', { model: model, admin: true }); }, + testChannel(channel){ + this.set('modalShowing', true); + var model = {channel:channel} + showModal('admin-plugins-chat-test', { model: model, admin: true }); + }, showError(error_key){ bootbox.alert(I18n.t(error_key)); }, - test(){ - this.set('modalShowing', true); - var model = {provider:this.get('model.provider'), channel:''} - showModal('admin-plugins-chat-test', { model: model, admin: true }); - } + + } diff --git a/assets/javascripts/admin/controllers/modals/admin-plugins-chat-edit-channel.js.es6 b/assets/javascripts/admin/controllers/modals/admin-plugins-chat-edit-channel.js.es6 new file mode 100644 index 0000000..b215fba --- /dev/null +++ b/assets/javascripts/admin/controllers/modals/admin-plugins-chat-edit-channel.js.es6 @@ -0,0 +1,94 @@ +import Rule from 'discourse/plugins/discourse-chat-integration/admin/models/rule' +import ModalFunctionality from 'discourse/mixins/modal-functionality'; +import { ajax } from 'discourse/lib/ajax'; +import { extractError } from 'discourse/lib/ajax-error'; +import InputValidation from 'discourse/models/input-validation'; + +export default Ember.Controller.extend(ModalFunctionality, { + + initThing: function(){ + console.log("Initialising controller"); + console.log(this.get('model.data')); + }.on('init'), + + // The validation property must be defined at runtime since the possible parameters vary by provider + setupValidations: function(){ + if(this.get('model.provider')){ + var theKeys = this.get('model.provider.channel_parameters').map( ( param ) => param['key'] ); + Ember.defineProperty(this,'paramValidation',Ember.computed('model.channel.data.{' + theKeys.join(',') + '}',this._paramValidation)); + } + }.observes('model'), + + validate(parameter){ + var regString = parameter.regex; + var regex = new RegExp(regString); + var val = this.get('model.channel.data.'+parameter.key); + + if(val == ""){ // Fail silently if field blank + return InputValidation.create({ + failed: true, + }); + }else if(!regString){ // Pass silently if no regex available for provider + return InputValidation.create({ + ok: true, + }); + }else if(regex.test(val)){ // Test against regex + return InputValidation.create({ + ok: true, + reason: I18n.t('chat_integration.edit_channel_modal.channel_validation.ok') + }); + }else{ // Failed regex + return InputValidation.create({ + failed: true, + reason: I18n.t('chat_integration.edit_channel_modal.channel_validation.fail') + }); + } + + }, + + _paramValidation: function(){ + var response = {} + var parameters = this.get('model.provider.channel_parameters'); + parameters.forEach(parameter => { + response[parameter.key] = this.validate(parameter); + }); + return response; + }, + + saveDisabled: function(){ + var validations = this.get('paramValidation'); + + if(!validations){ return true } + + var invalid = false; + + Object.keys(validations).forEach(key =>{ + if(!validations[key]){ + invalid = true; + } + if(!validations[key]['ok']){ + invalid = true; + } + }); + + return invalid; + }.property('paramValidation'), + + actions: { + cancel: function(){ + this.send('closeModal'); + }, + + save: function(){ + + const self = this; + + this.get('model.channel').save().then(function(result) { + self.send('closeModal'); + }).catch(function(error) { + self.flash(extractError(error), 'error'); + }); + + } + } +}); \ No newline at end of file diff --git a/assets/javascripts/admin/controllers/modals/admin-plugins-chat-edit-rule.js.es6 b/assets/javascripts/admin/controllers/modals/admin-plugins-chat-edit-rule.js.es6 deleted file mode 100644 index 2093a03..0000000 --- a/assets/javascripts/admin/controllers/modals/admin-plugins-chat-edit-rule.js.es6 +++ /dev/null @@ -1,61 +0,0 @@ -import Rule from 'discourse/plugins/discourse-chat-integration/admin/models/rule' -import ModalFunctionality from 'discourse/mixins/modal-functionality'; -import { ajax } from 'discourse/lib/ajax'; -import { extractError } from 'discourse/lib/ajax-error'; -import InputValidation from 'discourse/models/input-validation'; - -export default Ember.Controller.extend(ModalFunctionality, { - - model: Rule.create({}), - - channelValidation: function(){ - - var regString = this.get('model.provider.channel_regex'); - var regex = new RegExp(regString); - var val = this.get('model.rule.channel'); - - if(val == ""){ // Fail silently if field blank - return InputValidation.create({ - failed: true, - }); - }else if(!regString){ // Pass silently if no regex available for provider - return InputValidation.create({ - ok: true, - }); - }else if(regex.test(val)){ // Test against regex - return InputValidation.create({ - ok: true, - reason: I18n.t('chat_integration.edit_rule_modal.channel_validation.ok') - }); - }else{ // Failed regex - return InputValidation.create({ - failed: true, - reason: I18n.t('chat_integration.edit_rule_modal.channel_validation.fail') - }); - } - }.property('model.rule.channel'), - - saveDisabled: function(){ - if(this.get('channelValidation.failed')){ return true } - - return false; - }.property('channelValidation.failed'), - - actions: { - cancel: function(){ - this.send('closeModal'); - }, - - save: function(){ - - const self = this; - - this.get('model.rule').update().then(function(result) { - self.send('closeModal'); - }).catch(function(error) { - self.flash(extractError(error), 'error'); - }); - - } - } -}); \ No newline at end of file diff --git a/assets/javascripts/admin/controllers/modals/admin-plugins-chat-test.js.es6 b/assets/javascripts/admin/controllers/modals/admin-plugins-chat-test.js.es6 index 1eacb71..b6a5ba5 100644 --- a/assets/javascripts/admin/controllers/modals/admin-plugins-chat-test.js.es6 +++ b/assets/javascripts/admin/controllers/modals/admin-plugins-chat-test.js.es6 @@ -3,11 +3,11 @@ import { ajax } from 'discourse/lib/ajax'; export default Ember.Controller.extend(ModalFunctionality, { sendDisabled: function(){ - if(this.get('model').topic_id && this.get('model').channel){ + if(this.get('model').topic_id){ return false } return true - }.property('model.topic_id', 'model.channel'), + }.property('model.topic_id'), actions: { @@ -15,8 +15,7 @@ export default Ember.Controller.extend(ModalFunctionality, { self = this; this.set('loading', true); ajax("/admin/plugins/chat/test", { - data: { provider: this.get('model.provider.name'), - channel: this.get('model.channel'), + data: { channel_id: this.get('model.channel.id'), topic_id: this.get('model.topic_id') }, type: 'POST' diff --git a/assets/javascripts/admin/models/channel.js.es6 b/assets/javascripts/admin/models/channel.js.es6 new file mode 100644 index 0000000..b21399c --- /dev/null +++ b/assets/javascripts/admin/models/channel.js.es6 @@ -0,0 +1,14 @@ +import RestModel from 'discourse/models/rest'; + +export default RestModel.extend({ + + updateProperties() { + var prop_names = ['data']; + return this.getProperties(prop_names); + }, + + createProperties() { + var prop_names = ['provider','data']; + return this.getProperties(prop_names); + } +}); diff --git a/assets/javascripts/admin/models/rule.js.es6 b/assets/javascripts/admin/models/rule.js.es6 index 2ee1523..44fe2c8 100644 --- a/assets/javascripts/admin/models/rule.js.es6 +++ b/assets/javascripts/admin/models/rule.js.es6 @@ -11,9 +11,8 @@ export default RestModel.extend({ category_id: null, tags: null, - provider: '', - channel: '', - filter: null, + channel_id: null, + filter: 'watch', error_key: null, @computed('category_id') @@ -31,12 +30,13 @@ export default RestModel.extend({ }, updateProperties() { - var prop_names = ['category_id','provider','channel', 'tags','filter']; + var prop_names = ['category_id','tags','filter']; return this.getProperties(prop_names); }, createProperties() { - return this.updateProperties(); + var prop_names = ['channel_id', 'category_id','tags','filter']; + return this.getProperties(prop_names); } }); diff --git a/assets/javascripts/admin/routes/admin-plugins-chat-provider.js.es6 b/assets/javascripts/admin/routes/admin-plugins-chat-provider.js.es6 index 07b7b0a..7889816 100644 --- a/assets/javascripts/admin/routes/admin-plugins-chat-provider.js.es6 +++ b/assets/javascripts/admin/routes/admin-plugins-chat-provider.js.es6 @@ -1,12 +1,20 @@ -import Rule from 'discourse/plugins/discourse-chat-integration/admin/models/rule' import { ajax } from 'discourse/lib/ajax'; export default Discourse.Route.extend({ model(params, transition) { return Ember.RSVP.hash({ - rules: this.store.find('rule', {provider: params.provider}), + channels: this.store.findAll('channel', {provider: params.provider}), provider: this.modelFor("admin-plugins-chat").findBy('id',params.provider) + }).then(value => { + value.channels.forEach(channel => { + channel.set('rules', channel.rules.map(rule => { + rule = this.store.createRecord('rule', rule); + rule.channel = channel; + return rule; + })); + }); + return value; }); }, diff --git a/assets/javascripts/admin/templates/modal/admin-plugins-chat-edit-channel.hbs b/assets/javascripts/admin/templates/modal/admin-plugins-chat-edit-channel.hbs new file mode 100644 index 0000000..9c3399d --- /dev/null +++ b/assets/javascripts/admin/templates/modal/admin-plugins-chat-edit-channel.hbs @@ -0,0 +1,49 @@ +{{#d-modal-body id="chat_integration_edit_channel_modal" title="chat_integration.edit_channel_modal.title"}} +
+
+ + + + + + + + + + + + {{# each model.provider.channel_parameters as |param|}} + + + + + + + + + {{/each}} +
+ {{i18n (concat 'chat_integration.provider.' model.channel.provider '.title')}} +
+ {{text-field + name=(concat 'param-' param.key) + value=(mut (get model.channel.data param.key)) + }} + +   + {{#if (get model.channel.data param.key)}} + {{input-tip validation=(get paramValidation param.key)}} + {{/if}} +
+ +
+
+{{/d-modal-body}} + + \ No newline at end of file diff --git a/assets/javascripts/admin/templates/modal/admin-plugins-chat-edit-rule.hbs b/assets/javascripts/admin/templates/modal/admin-plugins-chat-edit-rule.hbs deleted file mode 100644 index a428578..0000000 --- a/assets/javascripts/admin/templates/modal/admin-plugins-chat-edit-rule.hbs +++ /dev/null @@ -1,87 +0,0 @@ -{{#d-modal-body id="chat_integration_edit_rule_modal" title="chat_integration.edit_rule_modal.title"}} -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{#if siteSettings.tagging_enabled}} - - - - - - - - - {{/if}} - -
- {{i18n (concat 'chat_integration.provider.' model.rule.provider '.title')}} -
- {{text-field - name="channel" - value=model.rule.channel - autofocus="autofocus" - id="channel-field"}} - -  {{input-tip validation=channelValidation}} -
- {{combo-box name="filter" content=model.rule.available_filters value=model.rule.filter}} -
- {{category-chooser - name="category" - value=model.rule.category_id - rootNoneLabel="chat_integration.all_categories" - rootNone=true - overrideWidths=false - }} -
- {{tag-chooser placeholderKey="chat_integration.all_tags" name="tags" tags=model.rule.tags}} -
- -
-
-{{/d-modal-body}} - - \ No newline at end of file diff --git a/assets/javascripts/admin/templates/modal/admin-plugins-chat-test.hbs b/assets/javascripts/admin/templates/modal/admin-plugins-chat-test.hbs index ef6b755..c4bc8e6 100644 --- a/assets/javascripts/admin/templates/modal/admin-plugins-chat-test.hbs +++ b/assets/javascripts/admin/templates/modal/admin-plugins-chat-test.hbs @@ -3,34 +3,7 @@
- - - - - - - - - - - - - - - - - - + + + + + + +{{#if siteSettings.tagging_enabled}} + +{{/if}} + + + diff --git a/assets/stylesheets/chat-integration-admin.scss b/assets/stylesheets/chat-integration-admin.scss index a048ce9..c9b7a71 100644 --- a/assets/stylesheets/chat-integration-admin.scss +++ b/assets/stylesheets/chat-integration-admin.scss @@ -1,6 +1,7 @@ #admin-plugin-chat{ table{ + margin-top:0; td:last-child{ white-space:nowrap; } @@ -25,10 +26,33 @@ } + div.channel-details{ + margin: 20px 10px; + + border: 1px solid dark-light-diff($primary, $secondary, 90%, -75%); + + div.channel-header{ + background: dark-light-diff($primary, $secondary, 90%, -75%); + padding: 10px; + overflow:auto; + + .channel-title{ + font-weight: bold; + font-size: 1.3em; + } + + + } + + div.channel-footer{ + overflow:auto; + } + } + } -#chat_integration_edit_rule_modal, #chat_integration_test_modal{ +#chat_integration_edit_channel_modal, #chat_integration_test_modal{ table{ width:100%; @@ -66,4 +90,4 @@ } - } \ No newline at end of file + } diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index a8224a7..8afedca 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -9,7 +9,11 @@ en: all_categories: "(all categories)" all_tags: "(all tags)" create_rule: "Create Rule" - test_provider: "Test Provider" + create_channel: "Create Channel" + delete_channel: "Delete" + test_channel: "Test" + edit_channel: "Edit" + channel_delete_confirm: "Are you sure you want to delete this channel? All associated rules will be deleted." test_modal: title: "Send a test message" provider: "Provider" @@ -30,23 +34,15 @@ en: tags: "Tags" edit_rule: "Edit" delete_rule: "Delete" - edit_rule_modal: - title: "Edit Rule" - save: "Save Rule" + edit_channel_modal: + title: "Edit Channel" + save: "Save Channel" cancel: "Cancel" provider: "Provider" - category: "Category" - tags: "Tags" - channel: "Channel" - filter: "Filter" channel_validation: ok: "Valid" - fail: "Invalid channel format" - instructions: - filter: "Notification level. Mute overrides other matching rules." - category: "This rule will only apply to topics in the specified category." - tags: "If specified, this rule will only apply to topics which have at least one of these tags." - + fail: "Invalid format" + provider: ####################################### @@ -54,7 +50,10 @@ en: ####################################### slack: title: "Slack" - channel_instructions: "e.g. #channel, @username." + param: + identifier: + title: Channel + help: "e.g. #channel, @username." errors: action_prohibited: "The bot does not have permission to post to that channel" channel_not_found: "The specified channel does not exist on slack" diff --git a/plugin.rb b/plugin.rb index 19f6225..f9580fd 100644 --- a/plugin.rb +++ b/plugin.rb @@ -19,6 +19,7 @@ after_initialize do require_relative "app/models/rule" require_relative "app/models/channel" + require_relative "app/serializers/channel_serializer" require_relative "app/serializers/rule_serializer" require_relative "app/controllers/chat_controller"
- {{i18n (concat 'chat_integration.provider.' model.provider.id '.title')}} -
- {{text-field - name="channel" - value=model.channel - autofocus="autofocus" - id="channel-field"}} - - {{!--  {{input-tip validation=channelValidation}} --}} -
diff --git a/assets/javascripts/discourse/templates/admin/plugins-chat-provider.hbs b/assets/javascripts/discourse/templates/admin/plugins-chat-provider.hbs index 399e99a..86d57c4 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-chat-provider.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-chat-provider.hbs @@ -6,70 +6,13 @@ {{/if}} - - - - - - - - {{#if siteSettings.tagging_enabled}} - - {{/if}} - - - - - - - - {{#each model.rules as |rule|}} - - - - - - - - - {{#if siteSettings.tagging_enabled}} - - {{/if}} - - - - - {{/each}} - -
{{i18n "chat_integration.rule_table.channel"}}{{i18n "chat_integration.rule_table.filter"}}{{i18n "chat_integration.rule_table.category"}}{{i18n "chat_integration.rule_table.tags"}}
- {{#if rule.error_key}} - - {{d-button action="showError" actionParam=rule.error_key class="delete btn-danger" icon="exclamation-triangle"}} - - {{/if}} - - {{rule.channel}} - {{rule.filterName}} - {{#if rule.category}} - {{category-link rule.category allowUncategorized="true" link="false"}} - {{else}} - {{i18n "chat_integration.all_categories"}} - {{/if}} - - {{#if rule.tags}} - {{rule.tags}} - {{else}} - {{i18n "chat_integration.all_tags"}} - {{/if}} - - {{d-button action="edit" actionParam=rule icon="pencil" class="edit" title="chat_integration.rule_table.edit_rule"}} - {{d-button action="delete" actionParam=rule icon="trash-o" class="delete" title="chat_integration.rule_table.delete_rule"}} -
+ {{# each model.channels as |channel|}} + {{channel-details channel=channel provider=provider store=store refresh='refresh' edit='editChannel' test='testChannel'}} + + {{/each}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/channel-details.hbs b/assets/javascripts/discourse/templates/components/channel-details.hbs new file mode 100644 index 0000000..ed9a5d1 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/channel-details.hbs @@ -0,0 +1,40 @@ +
+ {{channel.data.identifier}} +
+ {{d-button action="edit" actionParam=channel icon="pencil" title="chat_integration.edit_channel" label="chat_integration.edit_channel"}} + + {{d-button action="test" actionParam=channel icon="rocket" title="chat_integration.test_channel" label="chat_integration.test_channel"}} + + {{d-button class='cancel' action="delete" actionParam=channel icon="trash" title="chat_integration.delete_channel" label="chat_integration.delete_channel"}} +
+
+
+ + + {{!-- --}} + + + + + {{#if siteSettings.tagging_enabled}} + + {{/if}} + + + + + + + + {{#each channel.rules as |rule|}} + {{rule-row rule=rule refresh=refresh}} + + {{/each}} + +
{{i18n "chat_integration.rule_table.filter"}}{{i18n "chat_integration.rule_table.category"}}{{i18n "chat_integration.rule_table.tags"}}
+
+ \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/rule-row.hbs b/assets/javascripts/discourse/templates/components/rule-row.hbs new file mode 100644 index 0000000..9af5d24 --- /dev/null +++ b/assets/javascripts/discourse/templates/components/rule-row.hbs @@ -0,0 +1,53 @@ + +
+ {{#if editing}} + {{combo-box name="filter" content=rule.available_filters value=rule.filter}} + {{else}} + {{rule.filterName}} + {{/if}} + + {{#if editing}} + {{category-chooser + name="category" + value=rule.category_id + rootNoneLabel="chat_integration.all_categories" + rootNone=true + overrideWidths=false + }} + {{else}} + {{#if rule.category}} + {{category-link rule.category allowUncategorized="true" link="false"}} + {{else}} + {{i18n "chat_integration.all_categories"}} + {{/if}} + {{/if}} + + {{#if editing}} + {{tag-chooser placeholderKey="chat_integration.all_tags" name="tags" tags=rule.tags}} + {{else}} + {{#if rule.tags}} + {{rule.tags}} + {{else}} + {{i18n "chat_integration.all_tags"}} + {{/if}} + {{/if}} + + {{#if editing}} + {{d-button action="save" actionParam=rule icon="check" class="ok" title="chat_integration.rule_table.save_rule"}} + {{d-button action="cancel" actionParam=rule icon="times" class="cancel" title="chat_integration.rule_table.cancel_edit"}} + {{else}} + {{d-button action="edit" actionParam=rule icon="pencil" class="edit" title="chat_integration.rule_table.edit_rule"}} + {{d-button action="delete" actionParam=rule icon="trash-o" class="delete" title="chat_integration.rule_table.delete_rule"}} + {{/if}} +