simplify Webhooks' structure

This commit is contained in:
Evgeny Anatskiy
2018-02-01 12:18:01 -05:00
committed by Dannon Baker
parent 6b0542f7c2
commit 6070bf07e1
31 changed files with 175 additions and 220 deletions
+4 -4
View File
@@ -105,11 +105,11 @@ var Collection = Backbone.Collection.extend({
//
// Webhooks
//
Webhooks.add({
url: "api/webhooks/masthead/all",
callback: function(webhooks) {
Webhooks.load({
type: "masthead",
callback: function (webhooks) {
$(document).ready(() => {
$.each(webhooks.models, (index, model) => {
webhooks.each((model) => {
var webhook = model.toJSON();
if (webhook.activate) {
var obj = {
@@ -175,13 +175,13 @@ var menu = [
];
// Webhooks
Webhooks.add({
url: "api/webhooks/history-menu/all",
async: false, // (hypothetically) slows down the performance
Webhooks.load({
type: "history-menu",
async: false, // (hypothetically) slows down the performance
callback: function(webhooks) {
var webhooks_menu = [];
$.each(webhooks.models, (index, model) => {
webhooks.each((model) => {
var webhook = model.toJSON();
if (webhook.activate) {
webhooks_menu.push({
@@ -6,6 +6,7 @@ import Utils from "utils/utils";
import Deferred from "utils/deferred";
import Ui from "mvc/ui/ui-misc";
import FormBase from "mvc/form/form-view";
import Webhooks from "mvc/webhooks";
import Citations from "components/Citations.vue";
import Vue from "vue";
export default FormBase.extend({
@@ -200,19 +201,23 @@ export default FormBase.extend({
}
// add tool menu webhooks
$.getJSON("/api/webhooks/tool-menu/all", webhooks => {
_.each(webhooks, webhook => {
if (webhook.activate && webhook.config.function) {
menu_button.addMenu({
icon: webhook.config.icon,
title: webhook.config.title,
onclick: function() {
var func = new Function("options", webhook.config.function);
func(options);
}
});
}
});
Webhooks.load({
type: "tool-menu",
callback: function(webhooks) {
webhooks.each((model) => {
var webhook = model.toJSON();
if (webhook.activate && webhook.config.function) {
menu_button.addMenu({
icon: webhook.config.icon,
title: webhook.config.title,
onclick: function() {
var func = new Function("options", webhook.config.function);
func(options);
}
});
}
});
}
});
return {
@@ -598,7 +598,7 @@ var View = Backbone.View.extend({
if ($.isArray(response) && response.length > 0) {
self.$el.append($("<div/>", { id: "webhook-view" }));
var WebhookApp = new Webhooks.WebhookView({
urlRoot: `${Galaxy.root}api/webhooks/workflow`,
type: "workflow",
toolId: job_def.tool_id,
toolVersion: job_def.tool_version
});
+1 -1
View File
@@ -227,7 +227,7 @@ var View = Backbone.View.extend({
if (response.jobs && response.jobs.length > 0) {
self.$el.append($("<div/>", { id: "webhook-view" }));
var WebhookApp = new Webhooks.WebhookView({
urlRoot: `${Galaxy.root}api/webhooks/tool`,
type: "tool",
toolId: job_def.tool_id
});
}
+46 -54
View File
@@ -1,66 +1,58 @@
/**
Webhooks
**/
import Utils from 'utils/utils';
var WebhookModel = Backbone.Model.extend({
defaults: {
activate: false
}
const Webhooks = Backbone.Collection.extend({
url: `${Galaxy.root}api/webhooks`
});
var Webhooks = Backbone.Collection.extend({
model: WebhookModel
});
const WebhookView = Backbone.View.extend({
el: '#webhook-view',
var WebhookView = Backbone.View.extend({
el: "#webhook-view",
initialize: function (options) {
const toolId = options.toolId || '';
const toolVersion = options.toolVersion || '';
initialize: function(options) {
var me = this;
var toolId = options.toolId || "";
var toolVersion = options.toolVersion || "";
this.$el.attr('tool_id', toolId);
this.$el.attr('tool_version', toolVersion);
this.$el.attr("tool_id", toolId);
this.$el.attr("tool_version", toolVersion);
this.model = new WebhookModel();
this.model.urlRoot = options.urlRoot;
this.model.fetch({
success: function() {
me.render();
}
});
},
render: function() {
var webhook = this.model.toJSON();
this.$el.html(`<div id="${webhook.name}"></div>`);
if (webhook.styles)
$("<style/>", { type: "text/css" })
.text(webhook.styles)
.appendTo("head");
if (webhook.script)
$("<script/>", { type: "text/javascript" })
.text(webhook.script)
.appendTo("head");
return this;
}
});
var add = options => {
var webhooks = new Webhooks();
webhooks.url = Galaxy.root + options.url;
const webhooks = new Webhooks();
webhooks.fetch({
async: options.async ? options.async : true,
success: options.callback
success: data => {
data.reset(filterType(data, options.type));
if (data.length > 0) {
const index = _.random(0, data.length - 1);
this.render(data.at(index));
}
}
});
},
render: function (model) {
const webhook = model.toJSON();
this.$el.html(`<div id="${webhook.id}"></div>`);
Utils.appendScriptStyle(webhook);
return this;
}
});
const load = options => {
const webhooks = new Webhooks();
webhooks.fetch({
async: options.async !== undefined ? options.async : true,
success: data => {
if (options.type) {
data.reset(filterType(data, options.type));
}
options.callback(data);
}
});
};
function filterType (data, type) {
return _.filter(data.models, item => item.get('type').indexOf(type) !== -1);
}
export default {
Webhooks: Webhooks,
WebhookView: WebhookView,
add: add
WebhookView: WebhookView,
load: load
};
+12 -14
View File
@@ -25,6 +25,8 @@ window.make_popup_menus = Popupmenu.make_popup_menus;
import init_tag_click_function from "ui/autocom_tagging";
window.init_tag_click_function = init_tag_click_function;
import Tours from "mvc/tours";
import Webhooks from "mvc/webhooks";
import Utils from "utils/utils";
// console.debug( 'galaxy globals loaded' );
// ============================================================================
@@ -176,23 +178,19 @@ $(document).ready(() => {
Tours.activeGalaxyTourRunner();
function onloadWebhooks() {
// Wait until Galaxy.config is loaded.
if (Galaxy.config) {
if (Galaxy.config.enable_webhooks) {
// Load all webhooks with the type 'onload'
$.getJSON(`${Galaxy.root}api/webhooks/onload/all`, webhooks => {
_.each(webhooks, webhook => {
if (Galaxy.root !== undefined) {
// Load all webhooks with the type 'onload'
Webhooks.load({
type: "onload",
callback: function (webhooks) {
webhooks.each((model) => {
var webhook = model.toJSON();
if (webhook.activate && webhook.script) {
$("<script/>", { type: "text/javascript" })
.text(webhook.script)
.appendTo("head");
$("<style/>", { type: "text/css" })
.text(webhook.styles)
.appendTo("head");
Utils.appendScriptStyle(webhook);
}
});
});
}
}
});
} else {
setTimeout(onloadWebhooks, 100);
}
@@ -1,4 +1,4 @@
name: searchover
id: searchover
type:
- masthead
activate: true
@@ -38,7 +38,7 @@ $(document).ready(function() {
e.stopPropagation();
if ( $( '.search-screen-overlay' ).is( ':visible' ) ){
self.removeOverlay();
}
}
else {
self.clearSearchResults();
self.showOverlay();
@@ -1,4 +1,4 @@
name: tool_list
id: tool_list
type:
- masthead
activate: true
@@ -13,7 +13,7 @@ function: >
'be patient, this might take a moment.');
}, 1);
$.getJSON(Galaxy.root + "api/webhooks/tool_list/get_data", function(data) {
$.getJSON(Galaxy.root + "api/webhooks/tool_list/data", function(data) {
var popup = window.open('tool_list.html');
var html = '<!DOCTYPE html><body><h2>' +
'Create a Docker flavour of this instance:</h2>' +
@@ -1,4 +1,4 @@
name: tour_generator
id: tour_generator
type:
- onload
- tool-menu
@@ -10,7 +10,7 @@ $(document).ready(function() {
$('#execute').attr('tour_id', 'execute');
Toastr.info('Tour generation might take some time.');
$.getJSON('/api/webhooks/tour_generator/get_data/', {
$.getJSON('/api/webhooks/tour_generator/data/', {
tool_id: me.toolId,
tool_version: me.toolVersion
}, function(obj) {
+9 -38
View File
@@ -3,7 +3,6 @@ API Controller providing Galaxy Webhooks
"""
import imp
import logging
import random
from galaxy.web import _future_expose_api_anonymous_and_sessionless as \
expose_api_anonymous_and_sessionless
@@ -17,7 +16,7 @@ class WebhooksController(BaseAPIController):
super(WebhooksController, self).__init__(app)
@expose_api_anonymous_and_sessionless
def get_all(self, trans, **kwd):
def all_webhooks(self, trans, **kwd):
"""
*GET /api/webhooks/
Returns all webhooks
@@ -28,35 +27,9 @@ class WebhooksController(BaseAPIController):
]
@expose_api_anonymous_and_sessionless
def get_random(self, trans, webhook_type, **kwd):
def webhook_data(self, trans, webhook_id, **kwd):
"""
*GET /api/webhooks/{webhook_type}
Returns a random webhook for a given type
"""
webhooks = [
webhook
for webhook in self.app.webhooks_registry.webhooks
if webhook_type in webhook.type and
webhook.activate is True
]
return random.choice(webhooks).to_dict() if webhooks else {}
@expose_api_anonymous_and_sessionless
def get_all_by_type(self, trans, webhook_type, **kwd):
"""
*GET /api/webhooks/{webhook_type}/all
Returns all webhooks for a given type
"""
return [
webhook.to_dict()
for webhook in self.app.webhooks_registry.webhooks
if webhook_type in webhook.type
]
@expose_api_anonymous_and_sessionless
def get_data(self, trans, webhook_name, **kwd):
"""
*GET /api/webhooks/{webhook_name}/get_data/{params}
*GET /api/webhooks/{webhook_id}/data/{params}
Returns the result of executing helper function
"""
params = {}
@@ -64,14 +37,12 @@ class WebhooksController(BaseAPIController):
for key, value in kwd.items():
params[key] = value
webhook = [
webhook = (
webhook
for webhook in self.app.webhooks_registry.webhooks
if webhook.name == webhook_name
]
if webhook.id == webhook_id
).next()
return imp.load_source('helper', webhook[0].helper).main(
trans,
webhook[0],
params,
) if webhook and webhook[0].helper != '' else {}
return imp.load_source(webhook.path, webhook.helper).main(
trans, webhook, params,
) if webhook and webhook.helper != '' else {}
+7 -19
View File
@@ -609,29 +609,17 @@ def populate_api_routes(webapp, app):
# ===== WEBHOOKS API =====
# ========================
webapp.mapper.connect('get_all',
webapp.mapper.connect('get_all_webhooks',
'/api/webhooks',
controller='webhooks',
action='get_all',
conditions=dict(method=["GET"]))
action='all_webhooks',
conditions=dict(method=['GET']))
webapp.mapper.connect('get_random',
'/api/webhooks/{webhook_type}',
webapp.mapper.connect('get_webhook_data',
'/api/webhooks/{webhook_id}/data',
controller='webhooks',
action='get_random',
conditions=dict(method=["GET"]))
webapp.mapper.connect('get_all_by_type',
'/api/webhooks/{webhook_type}/all',
controller='webhooks',
action='get_all_by_type',
conditions=dict(method=["GET"]))
webapp.mapper.connect('get_data',
'/api/webhooks/{webhook_name}/get_data',
controller='webhooks',
action='get_data',
conditions=dict(method=["GET"]))
action='webhook_data',
conditions=dict(method=['GET']))
# =======================
# ===== LIBRARY API =====
+56 -55
View File
@@ -1,10 +1,9 @@
"""
This module manages loading of Galaxy webhooks.
"""
import logging
import os
import yaml
import logging
from galaxy.util import config_directories_from_setting
@@ -12,11 +11,12 @@ log = logging.getLogger(__name__)
class Webhook(object):
def __init__(self, w_name, w_type, w_activate, w_path):
self.name = w_name
self.type = w_type
self.activate = w_activate
self.path = w_path
def __init__(self, id, type, activate, weight, path):
self.id = id
self.type = type
self.activate = activate
self.weight = weight
self.path = path
self.styles = ''
self.script = ''
self.helper = ''
@@ -24,12 +24,12 @@ class Webhook(object):
def to_dict(self):
return {
'name': self.name,
'id': self.id,
'type': self.type,
'activate': self.activate,
'styles': self.styles,
'script': self.script,
'config': self.config
'config': self.config,
}
@@ -48,56 +48,57 @@ class WebhooksRegistry(object):
def load_webhooks(self):
for directory in self.webhooks_directories:
config_dir = os.path.join(directory, 'config')
config_file_path = None
for config_file in ['config.yml', 'config.yaml']:
path = os.path.join(directory, config_file)
if os.path.isfile(path):
config_file_path = path
break
if not os.path.exists(config_dir):
log.warning('directory not found: %s', config_dir)
continue
if config_file_path:
try:
self.load_webhook_from_config(directory, config_file_path)
except Exception as e:
log.exception(e)
config_dir_contents = os.listdir(config_dir)
# We are assuming that all yml/yaml files in a webhooks'
# config directory are webhook config files.
for config_file in config_dir_contents:
if config_file.endswith('.yml') or config_file.endswith('.yaml'):
self.load_webhook_from_config(config_dir, config_file)
def load_webhook_from_config(self, webhook_dir, config_file_path):
with open(config_file_path) as file:
config = yaml.safe_load(file)
def load_webhook_from_config(self, config_dir, config_file):
weight = config.get('weight', 1)
if weight < 1:
raise ValueError('Webhook weight must be greater or equal 1.')
webhook = Webhook(
config.get('id'),
config.get('type'),
config.get('activate', False),
weight,
webhook_dir,
)
# Read styles into a string, assuming all styles are in a
# single file
try:
with open(os.path.join(config_dir, config_file)) as file:
config = yaml.safe_load(file)
path = os.path.normpath(os.path.join(config_dir, '..'))
webhook = Webhook(
config['name'],
config['type'],
config['activate'],
path,
)
styles_file = os.path.join(webhook_dir, 'styles.css')
with open(styles_file, 'r') as file:
webhook.styles = file.read().replace('\n', '')
except IOError:
pass
# Read styles into a string, assuming all styles are in a
# single file
try:
styles_file = os.path.join(path, 'static/styles.css')
with open(styles_file, 'r') as file:
webhook.styles = file.read().replace('\n', '')
except IOError:
pass
# Read script into a string, assuming everything is in a
# single file
try:
script_file = os.path.join(webhook_dir, 'script.js')
with open(script_file, 'r') as file:
webhook.script = file.read()
except IOError:
pass
# Read script into a string, assuming everything is in a
# single file
try:
script_file = os.path.join(path, 'static/script.js')
with open(script_file, 'r') as file:
webhook.script = file.read()
except IOError:
pass
# Save helper function path if it exists
helper_path = os.path.join(webhook_dir, '__init__.py')
if os.path.isfile(helper_path):
webhook.helper = helper_path
# Save helper function path if it exists
helper_path = os.path.join(path, 'helper/__init__.py')
if os.path.isfile(helper_path):
webhook.helper = helper_path
webhook.config = config
self.webhooks.append(webhook)
except Exception as e:
log.exception(e)
webhook.config = config
self.webhooks.append(webhook)
@@ -1,5 +1,5 @@
name: history_test1
id: history_test1
title: History Menu Webhook Item 1
type:
type:
- history-menu
activate: true
@@ -1,5 +1,5 @@
name: history_test2
id: history_test2
title: History Menu Webhook Item 2
type:
type:
- history-menu
activate: true
@@ -1,5 +1,5 @@
name: masthead_test
type:
id: masthead_test
type:
- masthead
activate: true
@@ -1,4 +1,4 @@
name: phdcomics
id: phdcomics
type:
- tool
- workflow
@@ -32,7 +32,7 @@ $(document).ready(function() {
getRandomComic: function() {
var me = this,
url = galaxyRoot + 'api/webhooks/phdcomics/get_data';
url = galaxyRoot + 'api/webhooks/phdcomics/data';
this.$comicImg.html($('<div/>', {
id: 'phdcomics-loader'
@@ -1,4 +1,4 @@
name: trans_object
id: trans_object
type:
- masthead
activate: true
@@ -7,6 +7,6 @@ icon: fa-user
tooltip: Show Username
function: >
$.getJSON(Galaxy.root + "api/webhooks/trans_object/get_data", function(data) {
$.getJSON(Galaxy.root + "api/webhooks/trans_object/data", function(data) {
alert('Username: ' + data.username);
});
@@ -1,4 +1,4 @@
name: xkcd
id: xkcd
type:
- tool
- workflow