FEATURE: Improve channel error visibility in the admin panel, stop adding chat integration errors to logs
This commit is contained in:
parent
c44ac56d32
commit
fc721a1768
|
@ -1,6 +1,6 @@
|
||||||
class DiscourseChat::Channel < DiscourseChat::PluginModel
|
class DiscourseChat::Channel < DiscourseChat::PluginModel
|
||||||
# Setup ActiveRecord::Store to use the JSON field to read/write these values
|
# Setup ActiveRecord::Store to use the JSON field to read/write these values
|
||||||
store :value, accessors: [ :provider, :error_key, :data ], coder: JSON
|
store :value, accessors: [ :provider, :error_key, :error_info, :data ], coder: JSON
|
||||||
|
|
||||||
scope :with_provider, ->(provider) { where("value::json->>'provider'=?", provider) }
|
scope :with_provider, ->(provider) { where("value::json->>'provider'=?", provider) }
|
||||||
scope :with_data_value, ->(key, value) { where("(value::json->>'data')::json->>?=?", key.to_s, value.to_s) }
|
scope :with_data_value, ->(key, value) { where("(value::json->>'data')::json->>?=?", key.to_s, value.to_s) }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
require_relative './rule_serializer'
|
require_relative './rule_serializer'
|
||||||
|
|
||||||
class DiscourseChat::ChannelSerializer < ApplicationSerializer
|
class DiscourseChat::ChannelSerializer < ApplicationSerializer
|
||||||
attributes :id, :provider, :error_key, :data, :rules
|
attributes :id, :provider, :error_key, :error_info, :data, :rules
|
||||||
|
|
||||||
def rules
|
def rules
|
||||||
object.rules.order_by_precedence.map do |rule|
|
object.rules.order_by_precedence.map do |rule|
|
||||||
|
|
|
@ -86,15 +86,16 @@ module DiscourseChat
|
||||||
else
|
else
|
||||||
channel.update_attribute('error_key', 'chat_integration.channel_exception')
|
channel.update_attribute('error_key', 'chat_integration.channel_exception')
|
||||||
end
|
end
|
||||||
|
channel.update_attribute('error_info', JSON.pretty_generate(e.try(:info)))
|
||||||
|
|
||||||
# Log the error
|
# Log the error
|
||||||
Discourse.handle_job_exception(e,
|
# Discourse.handle_job_exception(e,
|
||||||
message: "Triggering notifications failed",
|
# message: "Triggering notifications failed",
|
||||||
extra: { provider_name: provider::PROVIDER_NAME,
|
# extra: { provider_name: provider::PROVIDER_NAME,
|
||||||
channel: rule.channel,
|
# channel: rule.channel,
|
||||||
post_id: post.id,
|
# post_id: post.id,
|
||||||
error_info: e.class == DiscourseChat::ProviderError ? e.info : nil }
|
# error_info: e.class == DiscourseChat::ProviderError ? e.info : nil }
|
||||||
)
|
# )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,41 +1,48 @@
|
||||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
classNames: ['channel-details'],
|
classNames: ["channel-details"],
|
||||||
actions: {
|
actions: {
|
||||||
refresh: function(){
|
refresh: function() {
|
||||||
this.sendAction('refresh');
|
this.sendAction("refresh");
|
||||||
},
|
},
|
||||||
|
|
||||||
delete(channel){
|
delete(channel) {
|
||||||
bootbox.confirm(I18n.t("chat_integration.channel_delete_confirm"), I18n.t("no_value"), I18n.t("yes_value"), result => {
|
bootbox.confirm(
|
||||||
if (result) {
|
I18n.t("chat_integration.channel_delete_confirm"),
|
||||||
channel.destroyRecord().then(() => {
|
I18n.t("no_value"),
|
||||||
this.send('refresh');
|
I18n.t("yes_value"),
|
||||||
}).catch(popupAjaxError);
|
result => {
|
||||||
|
if (result) {
|
||||||
|
channel
|
||||||
|
.destroyRecord()
|
||||||
|
.then(() => {
|
||||||
|
this.send("refresh");
|
||||||
|
})
|
||||||
|
.catch(popupAjaxError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
edit(channel){
|
edit(channel) {
|
||||||
this.sendAction('edit', channel);
|
this.sendAction("edit", channel);
|
||||||
},
|
},
|
||||||
|
|
||||||
test(channel){
|
test(channel) {
|
||||||
this.sendAction('test', channel);
|
this.sendAction("test", channel);
|
||||||
},
|
},
|
||||||
|
|
||||||
createRule(channel){
|
createRule(channel) {
|
||||||
this.sendAction('createRule', channel);
|
this.sendAction("createRule", channel);
|
||||||
},
|
},
|
||||||
|
|
||||||
editRule(rule){
|
editRule(rule) {
|
||||||
this.sendAction('editRule', rule, this.get('channel'));
|
this.sendAction("editRule", rule, this.get("channel"));
|
||||||
},
|
|
||||||
|
|
||||||
showError(errorKey){
|
|
||||||
bootbox.alert(I18n.t(errorKey));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showError(channel) {
|
||||||
|
this.sendAction("showError", channel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import showModal from 'discourse/lib/show-modal';
|
import showModal from "discourse/lib/show-modal";
|
||||||
import computed from "ember-addons/ember-computed-decorators";
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
modalShowing: false,
|
modalShowing: false,
|
||||||
|
|
||||||
@computed('model.channels')
|
@computed("model.channels")
|
||||||
anyErrors(channels) {
|
anyErrors(channels) {
|
||||||
let anyErrors = false;
|
let anyErrors = false;
|
||||||
|
|
||||||
channels.forEach((channel) => {
|
channels.forEach(channel => {
|
||||||
if (channel.error_key) {
|
if (channel.error_key) {
|
||||||
anyErrors = true;
|
anyErrors = true;
|
||||||
}
|
}
|
||||||
|
@ -17,57 +17,78 @@ export default Ember.Controller.extend({
|
||||||
return anyErrors;
|
return anyErrors;
|
||||||
},
|
},
|
||||||
|
|
||||||
actions:{
|
actions: {
|
||||||
createChannel() {
|
createChannel() {
|
||||||
this.set('modalShowing', true);
|
this.set("modalShowing", true);
|
||||||
|
|
||||||
const model = {
|
const model = {
|
||||||
channel: this.store.createRecord('channel', { provider: this.get('model.provider.id'), data:{} }),
|
channel: this.store.createRecord("channel", {
|
||||||
provider: this.get('model.provider')
|
provider: this.get("model.provider.id"),
|
||||||
|
data: {}
|
||||||
|
}),
|
||||||
|
provider: this.get("model.provider")
|
||||||
};
|
};
|
||||||
|
|
||||||
showModal('admin-plugins-chat-edit-channel', { model: model, admin: true });
|
showModal("admin-plugins-chat-edit-channel", {
|
||||||
|
model: model,
|
||||||
|
admin: true
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
editChannel(channel) {
|
editChannel(channel) {
|
||||||
this.set('modalShowing', true);
|
this.set("modalShowing", true);
|
||||||
|
|
||||||
const model = {
|
const model = {
|
||||||
channel: channel,
|
channel: channel,
|
||||||
provider: this.get('model.provider')
|
provider: this.get("model.provider")
|
||||||
};
|
};
|
||||||
|
|
||||||
showModal('admin-plugins-chat-edit-channel', { model: model, admin: true });
|
showModal("admin-plugins-chat-edit-channel", {
|
||||||
|
model: model,
|
||||||
|
admin: true
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
testChannel(channel) {
|
testChannel(channel) {
|
||||||
this.set('modalShowing', true);
|
this.set("modalShowing", true);
|
||||||
showModal('admin-plugins-chat-test', { model: { channel: channel }, admin: true });
|
showModal("admin-plugins-chat-test", {
|
||||||
|
model: { channel: channel },
|
||||||
|
admin: true
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
createRule(channel){
|
createRule(channel) {
|
||||||
this.set('modalShowing', true);
|
this.set("modalShowing", true);
|
||||||
|
|
||||||
const model = {
|
const model = {
|
||||||
rule: this.store.createRecord('rule', { channel_id: channel.id }),
|
rule: this.store.createRecord("rule", { channel_id: channel.id }),
|
||||||
channel: channel,
|
channel: channel,
|
||||||
provider: this.get('model.provider'),
|
provider: this.get("model.provider"),
|
||||||
groups: this.get('model.groups')
|
groups: this.get("model.groups")
|
||||||
};
|
};
|
||||||
|
|
||||||
showModal('admin-plugins-chat-edit-rule', { model: model, admin: true });
|
showModal("admin-plugins-chat-edit-rule", { model: model, admin: true });
|
||||||
},
|
},
|
||||||
editRule(rule, channel){
|
editRule(rule, channel) {
|
||||||
this.set('modalShowing', true);
|
this.set("modalShowing", true);
|
||||||
|
|
||||||
const model = {
|
const model = {
|
||||||
rule: rule,
|
rule: rule,
|
||||||
channel: channel,
|
channel: channel,
|
||||||
provider: this.get('model.provider'),
|
provider: this.get("model.provider"),
|
||||||
groups: this.get('model.groups')
|
groups: this.get("model.groups")
|
||||||
};
|
};
|
||||||
|
|
||||||
showModal('admin-plugins-chat-edit-rule', { model: model, admin: true });
|
showModal("admin-plugins-chat-edit-rule", { model: model, admin: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showError(channel) {
|
||||||
|
this.set("modalShowing", true);
|
||||||
|
|
||||||
|
showModal("admin-plugins-chat-channel-error", {
|
||||||
|
model: channel,
|
||||||
|
admin: true
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{{#d-modal-body id="chat_integration_error_modal"}}
|
||||||
|
<h4>{{i18n model.error_key}}</h4>
|
||||||
|
<pre>{{model.error_info}}</pre>
|
||||||
|
{{/d-modal-body}}
|
|
@ -14,7 +14,8 @@
|
||||||
edit='editChannel'
|
edit='editChannel'
|
||||||
test='testChannel'
|
test='testChannel'
|
||||||
createRule='createRule'
|
createRule='createRule'
|
||||||
editRule='editRule'}}
|
editRule='editRule'
|
||||||
|
showError='showError'}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
<div class="table-footer">
|
<div class="table-footer">
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<span class='channel-title'>
|
<span class='channel-title'>
|
||||||
{{#if channel.error_key}}
|
{{#if channel.error_key}}
|
||||||
{{d-button action="showError" actionParam=channel.error_key class="delete btn-danger" icon="exclamation-triangle"}}
|
{{d-button action="showError" actionParam=channel class="delete btn-danger" icon="exclamation-triangle"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{channel-data provider=provider channel=channel}}
|
{{channel-data provider=provider channel=channel}}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#admin-plugin-chat {
|
#admin-plugin-chat {
|
||||||
|
|
||||||
table {
|
table {
|
||||||
margin-top:0;
|
margin-top: 0;
|
||||||
|
|
||||||
td:last-child {
|
td:last-child {
|
||||||
white-space:nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
td:not(:last-child) {
|
td:not(:last-child) {
|
||||||
|
@ -18,7 +17,7 @@
|
||||||
|
|
||||||
div.error {
|
div.error {
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
font-weight:bold;
|
font-weight: bold;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
@ -33,7 +32,7 @@
|
||||||
div.channel-header {
|
div.channel-header {
|
||||||
background: $primary-low;
|
background: $primary-low;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
overflow:auto;
|
overflow: auto;
|
||||||
|
|
||||||
.channel-title {
|
.channel-title {
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
|
@ -45,7 +44,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
div.channel-footer {
|
div.channel-footer {
|
||||||
overflow:auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +53,7 @@
|
||||||
#chat_integration_test_modal,
|
#chat_integration_test_modal,
|
||||||
#chat-integration-edit-rule_modal {
|
#chat-integration-edit-rule_modal {
|
||||||
table {
|
table {
|
||||||
width:100%;
|
width: 100%;
|
||||||
|
|
||||||
tr.input td {
|
tr.input td {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
|
@ -83,7 +82,7 @@
|
||||||
.tag-chooser {
|
.tag-chooser {
|
||||||
ul.select2-choices {
|
ul.select2-choices {
|
||||||
border: none;
|
border: none;
|
||||||
background:none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
|
@ -94,3 +93,12 @@
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#chat_integration_error_modal {
|
||||||
|
pre {
|
||||||
|
max-width: 500px;
|
||||||
|
max-height: 800px;
|
||||||
|
overflow: scroll;
|
||||||
|
background: $primary-low;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ en:
|
||||||
settings: "Settings"
|
settings: "Settings"
|
||||||
no_providers: "You need to enable some providers in the plugin settings"
|
no_providers: "You need to enable some providers in the plugin settings"
|
||||||
channels_with_errors: "Some channels for this provider failed last time messages were sent. Click the error icon(s) to learn more."
|
channels_with_errors: "Some channels for this provider failed last time messages were sent. Click the error icon(s) to learn more."
|
||||||
channel_exception: "An unknown error occured when a message was last sent to this channel. Check the site logs for more information."
|
channel_exception: "An unknown error occured when a message was last sent to this channel."
|
||||||
group_mention_template: "Mentions of: @{{name}}"
|
group_mention_template: "Mentions of: @{{name}}"
|
||||||
group_message_template: "Messages to: @{{name}}"
|
group_message_template: "Messages to: @{{name}}"
|
||||||
choose_group: "(choose a group)"
|
choose_group: "(choose a group)"
|
||||||
|
|
|
@ -4,7 +4,6 @@ en:
|
||||||
chat_integration_discourse_username: 'Username of user to act as when fetching content.'
|
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'
|
chat_integration_delay_seconds: 'Number of seconds to wait after post creation before sending chat notitifications'
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
########## SLACK SETTINGS #############
|
########## SLACK SETTINGS #############
|
||||||
#######################################
|
#######################################
|
||||||
|
@ -93,6 +92,8 @@ en:
|
||||||
group_mention_template: "mentions of: @%{name}"
|
group_mention_template: "mentions of: @%{name}"
|
||||||
group_message_template: "messages to: @%{name}"
|
group_message_template: "messages to: @%{name}"
|
||||||
|
|
||||||
|
admin_error: "Some chat integration channels have errors. Visit <a href='/admin/plugins/chat'>the chat integration section</a> to find out more."
|
||||||
|
|
||||||
provider:
|
provider:
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|
|
@ -22,5 +22,13 @@ after_initialize do
|
||||||
|
|
||||||
add_admin_route 'chat_integration.menu_title', 'chat'
|
add_admin_route 'chat_integration.menu_title', 'chat'
|
||||||
|
|
||||||
|
AdminDashboardData.add_problem_check do
|
||||||
|
error = false;
|
||||||
|
DiscourseChat::Channel.find_each do |channel|
|
||||||
|
error = true unless channel.error_key.blank?
|
||||||
|
end
|
||||||
|
I18n.t("chat_integration.admin_error") if error
|
||||||
|
end
|
||||||
|
|
||||||
DiscourseChat::Provider.mount_engines
|
DiscourseChat::Provider.mount_engines
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue