Allow providers to be disabled, and tidy up translations

This commit is contained in:
David Taylor 2017-07-03 15:53:26 +01:00
parent 984211e9ce
commit 1c416d5a81
15 changed files with 149 additions and 66 deletions

View File

@ -4,9 +4,9 @@ import computed from "ember-addons/ember-computed-decorators";
export default RestModel.extend({ export default RestModel.extend({
available_filters: [ available_filters: [
{ id: 'watch', name: I18n.t('chat.filter.watch'), icon: 'exclamation-circle' }, { id: 'watch', name: I18n.t('chat_integration.filter.watch'), icon: 'exclamation-circle' },
{ id: 'follow', name: I18n.t('chat.filter.follow'), icon: 'circle'}, { id: 'follow', name: I18n.t('chat_integration.filter.follow'), icon: 'circle'},
{ id: 'mute', name: I18n.t('chat.filter.mute'), icon: 'times-circle' } { id: 'mute', name: I18n.t('chat_integration.filter.mute'), icon: 'times-circle' }
], ],
category_id: null, category_id: null,
@ -26,7 +26,7 @@ export default RestModel.extend({
@computed('filter') @computed('filter')
filterName(filter) { filterName(filter) {
return I18n.t(`slack.present.${filter}`); return I18n.t(`chat_integration.filter.${filter}`);
}, },
updateProperties() { updateProperties() {

View File

@ -1,7 +1,10 @@
import AdminPluginsChatProvider from 'discourse/plugins/discourse-chat-integration/admin/routes/admin-plugins-chat-provider' import AdminPluginsChatProvider from 'discourse/plugins/discourse-chat-integration/admin/routes/admin-plugins-chat-provider'
export default Discourse.Route.extend({ export default Discourse.Route.extend({
afterModel(model, transition) { afterModel(model, transition) {
this.transitionTo('adminPlugins.chat.provider', model.get('firstObject').name);
if(model.totalRows > 0){
this.transitionTo('adminPlugins.chat.provider', model.get('firstObject').name);
}
} }
}); });

View File

@ -3,5 +3,13 @@ import AdminPluginsChatProvider from 'discourse/plugins/discourse-chat-integrati
export default Discourse.Route.extend({ export default Discourse.Route.extend({
model(params, transition) { model(params, transition) {
return this.store.findAll('provider'); return this.store.findAll('provider');
} },
actions: {
showSettings: function(){
this.transitionTo('adminSiteSettingsCategory', 'plugins', {
queryParams: { filter: 'chat_integration'}
});
}
}
}); });

View File

@ -1,12 +1,12 @@
{{#d-modal-body title="chat.edit_rule_modal_title"}} {{#d-modal-body title="chat_integration.edit_rule_modal.title"}}
<form class="form-horizontal"> <form class="form-horizontal">
<div> <div>
Rule for provider {{model.provider}} {{i18n 'chat_integration.edit_rule_modal.provider'}}: {{i18n (concat 'chat_integration.provider.' model.provider '.title')}}
</div> </div>
<div> <div>
<label for="category">{{i18n "chat.category"}}</label> <label for="category">{{i18n "chat_integration.edit_rule_modal.category"}}</label>
{{category-chooser {{category-chooser
name="category" name="category"
value=model.category_id value=model.category_id
@ -18,22 +18,22 @@
{{#if siteSettings.tagging_enabled}} {{#if siteSettings.tagging_enabled}}
<div> <div>
<label for="tags">{{i18n "chat.tags"}}</label> <label for="tags">{{i18n "chat_integration.edit_rule_modal.tags"}}</label>
{{tag-chooser name="tags" tags=model.tags placeholderKey="slack.choose.tags"}} {{tag-chooser name="tags" tags=model.tags placeholderKey="chat_integration.edit_rule_modal.placeholders.tags"}}
</div> </div>
{{/if}} {{/if}}
<div> <div>
<label for="channel">{{i18n "chat.channel"}}</label> <label for="channel">{{i18n "chat_integration.edit_rule_modal.channel"}}</label>
{{text-field {{text-field
name="channel" name="channel"
value=model.channel value=model.channel
placeholderKey="slack.choose.channel" placeholderKey="chat_integration.edit_rule_modal.placeholders.channel"
class="channel"}} class="channel"}}
</div> </div>
<div> <div>
<label for="filter">{{i18n "chat.filter"}}</label> <label for="filter">{{i18n "chat_integration.edit_rule_modal.filter"}}</label>
{{combo-box name="filter" content=model.available_filters value=model.filter}} {{combo-box name="filter" content=model.available_filters value=model.filter}}
</div> </div>
@ -42,6 +42,8 @@
{{/d-modal-body}} {{/d-modal-body}}
<div class="modal-footer"> <div class="modal-footer">
<button class='btn btn-primary' {{action "save"}} disabled={{submitDisabled}}>{{i18n 'chat.save'}}</button> {{d-button class='btn-primary' action="save" title="chat_integration.edit_rule_modal.save" label="chat_integration.edit_rule_modal.save"}}
<a {{action "cancel"}}>{{i18n 'chat.cancel'}}</a>
{{d-button action="cancel" title="chat_integration.edit_rule_modal.cancel" label="chat_integration.edit_rule_modal.cancel"}}
</div> </div>

View File

@ -1,15 +1,14 @@
<table> <table>
<tr> <tr>
<th>{{i18n "chat.channel"}}</th> <th>{{i18n "chat_integration.rule_table.channel"}}</th>
<th>{{i18n "chat.filter"}}</th> <th>{{i18n "chat_integration.rule_table.filter"}}</th>
<th>{{i18n "chat.category"}}</th> <th>{{i18n "chat_integration.rule_table.category"}}</th>
{{#if siteSettings.tagging_enabled}} {{#if siteSettings.tagging_enabled}}
<th>{{i18n "chat.tags"}}</th> <th>{{i18n "chat_integration.rule_table.tags"}}</th>
{{/if}} {{/if}}
@ -27,7 +26,7 @@
{{#if rule.category}} {{#if rule.category}}
{{category-link rule.category allowUncategorized="true" link="false"}} {{category-link rule.category allowUncategorized="true" link="false"}}
{{else}} {{else}}
{{i18n "slack.choose.all_categories"}} {{i18n "chat_integration.all_categories"}}
{{/if}} {{/if}}
</td> </td>
@ -38,27 +37,16 @@
<td> <td>
{{d-button action="edit" actionParam=rule icon="pencil" class="edit" title="chat.edit"}} {{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 btn-danger" title="chat.delete"}} {{d-button action="delete" actionParam=rule icon="trash-o" class="delete btn-danger" title="chat_integration.rule_table.delete_rule"}}
</td> </td>
</tr> </tr>
{{/each}} {{/each}}
</table> </table>
<hr/> <div>
{{d-button action="testNotification" <div class="pull-right">
icon="rocket" {{d-button action="create" actionParam=model.provider icon="plus" title="chat_integration.create_rule" label="chat_integration.create_rule"}}
disabled=testingNotification </div>
title="chat.test_notification" </div>
label="chat.test_notification"}}
{{#d-button
action="resetSettings"
icon="trash"
title="chat.reset_settings"
label="chat.reset_settings"}}
{{/d-button}}
<div class="pull-right">
{{d-button action="create" actionParam=model.provider icon="plus" title="chat.create_rule" label="chat.create_rule"}}
</div>

View File

@ -1,14 +1,27 @@
<div id="admin-plugin-slack"> <div id="admin-plugin-chat">
<div class="admin-controls"> <div class="admin-controls">
<div class="span15"> <div class="span15">
<ul class="nav nav-pills"> <ul class="nav nav-pills">
{{#each model as |provider|}} {{#each model as |provider|}}
{{nav-item route='adminPlugins.chat.provider' routeParam=provider.name label=(concat 'chat.integration.' provider.name '.title')}} {{nav-item route='adminPlugins.chat.provider' routeParam=provider.name label=(concat 'chat_integration.provider.' provider.name '.title')}}
{{/each}} {{/each}}
</ul> </ul>
</div> </div>
<div class="pull-right">
{{#d-button
action="showSettings"
icon="gear"
title="chat_integration.settings"
label="chat_integration.settings"}}
{{/d-button}}
</div>
</div> </div>
{{#if model.totalRows}}
{{else}}
{{i18n "chat_integration.no_providers"}}
{{/if}}
{{outlet}} {{outlet}}
</div> </div>

View File

@ -1,17 +1,35 @@
en: en:
js: js:
chat: chat_integration:
menu_title: "Chat Integrations" menu_title: "Chat Integrations"
channel: "Channel" settings: "Settings"
filter: "Filter" no_providers: "You need to enable some providers in the plugin settings"
category: "Category" all_categories: "All Categories"
tags: "Tags" create_rule: "Create Rule"
edit: "Edit" rule_table:
delete: "Delete" channel: "Channel"
test_notification: "Test Notification" filter: "Filter"
reset_settings: "Reset Settings" category: "Category"
edit_rule_modal_title: "Edit Rule" tags: "Tags"
integration: edit: "Edit"
delete: "Delete"
filter:
watch: "Watch"
follow: "Follow"
mute: "Mute"
edit_rule_modal:
title: "Edit Rule"
save: "Save Rule"
cancel: "Cancel"
provider: "Provider"
category: "Category"
tags: "Tags"
channel: "Channel"
filter: "Filter"
placeholders:
tags: "Choose tags"
channel: "#channel, @user or Channel ID"
provider:
telegram: telegram:
title: "Telegram" title: "Telegram"
slack: slack:

View File

@ -1,3 +1,20 @@
en: en:
site_settings: site_settings:
discourse_chat_enabled: 'Enable the discourse-chat plugin' chat_integration_enabled: 'Enable the discourse-chat-integration plugin'
chat_integration_discourse_username: 'Username of user to act as when fetching content.'
chat_integration_delay_seconds: 'Number of seconds to wait after post creation before sending chat notitifications'
#######################################
########## SLACK SETTINGS #############
#######################################
chat_integration_slack_enabled: 'Enable the slack chat-integration provider'
chat_integration_slack_outbound_webhook_url: 'URL for outbound slack requests'
chat_integration_slack_excerpt_length: 'Post excerpt length'
chat_integration_slack_icon_url: 'Icon to post to slack with (defaults to forum logo)'
chat_integration_slack_access_token: 'Token if you are using the Web API instead of webhooks'
#######################################
######### TELEGRAM SETTINGS ###########
#######################################
chat_integration_telegram_enabled: "Enable the telegram chat-integration provider"

View File

@ -3,6 +3,7 @@ plugins:
default: false default: false
chat_integration_discourse_username: chat_integration_discourse_username:
default: system default: system
type: username
chat_integration_delay_seconds: chat_integration_delay_seconds:
default: 20 default: 20
@ -13,7 +14,7 @@ plugins:
default: false default: false
chat_integration_slack_outbound_webhook_url: chat_integration_slack_outbound_webhook_url:
default: '' default: ''
chat_integration_slack_discourse_excerpt_length: chat_integration_slack_excerpt_length:
default: 400 default: 400
chat_integration_slack_icon_url: chat_integration_slack_icon_url:
default: '' default: ''

View File

@ -63,10 +63,12 @@ module DiscourseChat
matching_rules.each do |rule| matching_rules.each do |rule|
Rails.logger.info("Sending notification to provider #{rule.provider}, channel #{rule.channel}") Rails.logger.info("Sending notification to provider #{rule.provider}, channel #{rule.channel}")
provider = ::DiscourseChat::Provider.get_by_name(rule.provider) provider = ::DiscourseChat::Provider.get_by_name(rule.provider)
if provider is_enabled = ::DiscourseChat::Provider.is_enabled(provider)
if provider and is_enabled
provider.trigger_notification(post, rule.channel) provider.trigger_notification(post, rule.channel)
elsif provider
# Provider is disabled, don't do anything
else else
puts "Can't find provider"
# TODO: Handle when the provider does not exist # TODO: Handle when the provider does not exist
end end
end end

View File

@ -6,10 +6,24 @@ module DiscourseChat
end.map(&method(:const_get)) end.map(&method(:const_get))
end end
def self.enabled_providers
self.providers.select do |provider|
self.is_enabled(provider)
end
end
def self.get_by_name(name) def self.get_by_name(name)
self.providers.find{|p| p::PROVIDER_NAME == name} self.providers.find{|p| p::PROVIDER_NAME == name}
end end
def self.is_enabled(provider)
if defined? provider::PROVIDER_ENABLED_SETTING
SiteSetting.send(provider::PROVIDER_ENABLED_SETTING)
else
false
end
end
end end
end end

View File

@ -3,7 +3,9 @@ require_relative "slack_message_formatter.rb"
module DiscourseChat::Provider::SlackProvider module DiscourseChat::Provider::SlackProvider
PROVIDER_NAME = "slack".freeze PROVIDER_NAME = "slack".freeze
def self.excerpt(post, max_length = SiteSetting.chat_integration_slack_discourse_excerpt_length) PROVIDER_ENABLED_SETTING = :chat_integration_slack_enabled
def self.excerpt(post, max_length = SiteSetting.chat_integration_slack_excerpt_length)
doc = Nokogiri::HTML.fragment(post.excerpt(max_length, doc = Nokogiri::HTML.fragment(post.excerpt(max_length,
remap_emoji: true, remap_emoji: true,
keep_onebox_source: true keep_onebox_source: true

View File

@ -1,7 +1,10 @@
module DiscourseChat module DiscourseChat
module Provider module Provider
module TelegramProvider module TelegramProvider
include Provider
PROVIDER_NAME = "telegram".freeze PROVIDER_NAME = "telegram".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_telegram_enabled
end end
end end
end end

View File

@ -65,18 +65,16 @@ after_initialize do
end end
def list_providers def list_providers
providers = ::DiscourseChat::Provider.providers.map {|x| {name: x::PROVIDER_NAME, id: x::PROVIDER_NAME}} providers = ::DiscourseChat::Provider.enabled_providers.map {|x| {name: x::PROVIDER_NAME, id: x::PROVIDER_NAME}}
render json:providers, root: 'providers' render json:providers, root: 'providers'
end end
def list_rules def list_rules
providers = ::DiscourseChat::Provider.providers.map {|x| x::PROVIDER_NAME} providers = ::DiscourseChat::Provider.enabled_providers.map {|x| x::PROVIDER_NAME}
requested_provider = params[:provider] requested_provider = params[:provider]
if requested_provider.nil? if providers.include? requested_provider
rules = DiscourseChat::Rule.all
elsif providers.include? requested_provider
rules = DiscourseChat::Rule.all_for_provider(requested_provider) rules = DiscourseChat::Rule.all_for_provider(requested_provider)
else else
raise Discourse::NotFound raise Discourse::NotFound
@ -119,7 +117,7 @@ after_initialize do
require_dependency 'admin_constraint' require_dependency 'admin_constraint'
add_admin_route 'chat.menu_title', 'chat' add_admin_route 'chat_integration.menu_title', 'chat'
DiscourseChat::Engine.routes.draw do DiscourseChat::Engine.routes.draw do
get "" => "chat#respond" get "" => "chat#respond"

View File

@ -10,9 +10,14 @@ RSpec.describe DiscourseChat::Manager do
let(:second_post) {Fabricate(:post, topic: topic, post_number:2)} let(:second_post) {Fabricate(:post, topic: topic, post_number:2)}
describe '.trigger_notifications' do describe '.trigger_notifications' do
before do
SiteSetting.chat_integration_enabled = true
end
before(:each) do before(:each) do
module ::DiscourseChat::Provider::DummyProvider module ::DiscourseChat::Provider::DummyProvider
PROVIDER_NAME = "dummy".freeze PROVIDER_NAME = "dummy".freeze
PROVIDER_ENABLED_SETTING = :chat_integration_enabled # Tie to main plugin enabled setting
@@sent_messages = [] @@sent_messages = []
def self.trigger_notification(post, channel) def self.trigger_notification(post, channel)
@ -35,6 +40,15 @@ RSpec.describe DiscourseChat::Manager do
DiscourseChat::Rule.new({provider: provider, channel: channel, filter:filter, category_id:category_id, tags:tags}).save DiscourseChat::Rule.new({provider: provider, channel: channel, filter:filter, category_id:category_id, tags:tags}).save
end end
it "should only send notifications when provider is enabled" do
SiteSetting.chat_integration_enabled = false
create_rule('dummy', 'chan1', 'watch', category.id, nil)
manager.trigger_notifications(first_post.id)
expect(provider.sent_messages.map{|x| x[:channel]}).to contain_exactly()
end
it "should send a notification to watched and following channels for new topic" do it "should send a notification to watched and following channels for new topic" do
create_rule('dummy', 'chan1', 'watch', category.id, nil) create_rule('dummy', 'chan1', 'watch', category.id, nil)