Merge branch 'dev' into admin_grid_formbuilder
@@ -17,7 +17,6 @@
|
||||
"d3": "~3",
|
||||
"farbtastic": "~2.0.0-alpha.1",
|
||||
"toastr": "~2.1.0",
|
||||
"jQTouch": "git://github.com/senchalabs/jQTouch#~1.0.0",
|
||||
"bib2json": "git://github.com/galaxyproject/bib2json#galaxy",
|
||||
"jquery-form": "~3.46.0",
|
||||
"jquery-autocomplete": "git://github.com/dyve/jquery-autocomplete",
|
||||
|
||||
@@ -1,883 +0,0 @@
|
||||
(function() {
|
||||
|
||||
$.jQTouch = function(options) {
|
||||
// Initialize internal jQT variables
|
||||
var $body,
|
||||
$head=$('head'),
|
||||
history=[],
|
||||
newPageCount=0,
|
||||
jQTSettings={},
|
||||
$currentPage='',
|
||||
orientation='portrait',
|
||||
touchSelectors=[],
|
||||
publicObj={},
|
||||
tapBuffer=100, // High click delay = ~350, quickest animation (slide) = 250
|
||||
extensions=$.jQTouch.prototype.extensions,
|
||||
extTapHandlers=$.jQTouch.prototype.tapHandlers,
|
||||
tapHandlers=[],
|
||||
animations=[],
|
||||
hairExtensions='',
|
||||
defaults = {
|
||||
addGlossToIcon: true,
|
||||
backSelector: '.back, .cancel, .goback',
|
||||
cacheGetRequests: true,
|
||||
debug: true,
|
||||
defaultAnimation: 'slideleft',
|
||||
fixedViewport: true,
|
||||
formSelector: 'form',
|
||||
fullScreen: true,
|
||||
fullScreenClass: 'fullscreen',
|
||||
icon: null,
|
||||
icon4: null, // available in iOS 4.2 and later
|
||||
preloadImages: false,
|
||||
starter: $(document).ready,
|
||||
startupScreen: null,
|
||||
statusBar: 'default', // other options: black-translucent, black
|
||||
submitSelector: '.submit',
|
||||
touchSelector: 'a, .touch',
|
||||
trackScrollPositions: true,
|
||||
updateHash: true,
|
||||
useAnimations: true,
|
||||
useFastTouch: true,
|
||||
useTouchScroll: true,
|
||||
animations: [ // highest to lowest priority
|
||||
{name:'cubeleft', selector:'.cubeleft, .cube', is3d: true},
|
||||
{name:'cuberight', selector:'.cuberight', is3d: true},
|
||||
{name:'dissolve', selector:'.dissolve'},
|
||||
{name:'fade', selector:'.fade'},
|
||||
{name:'flipleft', selector:'.flipleft, .flip', is3d: true},
|
||||
{name:'flipright', selector:'.flipright', is3d: true},
|
||||
{name:'pop', selector:'.pop', is3d: true},
|
||||
{name:'swapleft', selector:'.swapleft, .swap', is3d: true},
|
||||
{name:'swapright', selector:'.swapright', is3d: true},
|
||||
{name:'slidedown', selector:'.slidedown'},
|
||||
{name:'slideright', selector:'.slideright'},
|
||||
{name:'slideup', selector:'.slideup'},
|
||||
{name:'slideleft', selector:'.slideleft, .slide, #jqt > * > ul li a'}
|
||||
]
|
||||
}; // end defaults
|
||||
|
||||
function warn(message) {
|
||||
if (window.console !== undefined && jQTSettings.debug === true) {
|
||||
console.warn(message);
|
||||
}
|
||||
}
|
||||
|
||||
function addAnimation(animation) {
|
||||
if (typeof(animation.selector) === 'string' && typeof(animation.name) === 'string') {
|
||||
animations.push(animation);
|
||||
}
|
||||
}
|
||||
|
||||
function addTapHandler(tapHandler) {
|
||||
if (typeof(tapHandler.name) === 'string' && typeof(tapHandler.isSupported) === 'function' && typeof(tapHandler.fn) === 'function') {
|
||||
tapHandlers.push(tapHandler);
|
||||
}
|
||||
}
|
||||
|
||||
function addPageToHistory(page, animation) {
|
||||
history.unshift({
|
||||
page: page,
|
||||
animation: animation,
|
||||
hash: '#' + page.attr('id'),
|
||||
id: page.attr('id')
|
||||
});
|
||||
}
|
||||
|
||||
// Unfortunately, we can not assume the 'tap' event
|
||||
// is being used for links, forms, etc.
|
||||
function clickHandler(e) {
|
||||
// Figure out whether to prevent default
|
||||
var $el = $(e.target);
|
||||
|
||||
// Find the nearest tappable ancestor
|
||||
if (!$el.is(touchSelectors.join(', '))) {
|
||||
$el = $(e.target).closest(touchSelectors.join(', '));
|
||||
}
|
||||
|
||||
// Prevent default if we found an internal link
|
||||
// (relative or absolute)
|
||||
if ($el && $el.attr('href') && !$el.isExternalLink()) {
|
||||
warn('Need to prevent default click behavior.');
|
||||
e.preventDefault();
|
||||
} else {
|
||||
warn('No need to prevent default click behavior.');
|
||||
}
|
||||
|
||||
// Trigger a tap event if touchstart is not on the job
|
||||
if ($.support.touch) {
|
||||
warn('Not converting click to a tap event because touch handler is on the job.');
|
||||
} else {
|
||||
warn('Converting click event to a tap event because touch handlers are not present or off.');
|
||||
$(e.target).trigger('tap', e);
|
||||
}
|
||||
}
|
||||
|
||||
function doNavigation(fromPage, toPage, animation, goingBack) {
|
||||
|
||||
goingBack = goingBack ? goingBack : false;
|
||||
|
||||
// Error check for target page
|
||||
if (toPage === undefined || toPage.length === 0) {
|
||||
$.fn.unselect();
|
||||
warn('Target element is missing.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Error check for fromPage === toPage
|
||||
if (toPage.hasClass('current')) {
|
||||
$.fn.unselect();
|
||||
warn('You are already on the page you are trying to navigate to.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Collapse the keyboard
|
||||
$(':focus').trigger('blur');
|
||||
|
||||
fromPage.trigger('pageAnimationStart', { direction: 'out', back: goingBack });
|
||||
toPage.trigger('pageAnimationStart', { direction: 'in', back: goingBack });
|
||||
|
||||
if ($.support.animationEvents && animation && jQTSettings.useAnimations) {
|
||||
// Fail over to 2d animation if need be
|
||||
if (!$.support.transform3d && animation.is3d) {
|
||||
warn('Did not detect support for 3d animations, falling back to ' + jQTSettings.defaultAnimation + '.');
|
||||
animation.name = jQTSettings.defaultAnimation;
|
||||
}
|
||||
|
||||
// Reverse animation if need be
|
||||
var finalAnimationName = animation.name,
|
||||
is3d = animation.is3d ? 'animating3d' : '';
|
||||
|
||||
if (goingBack) {
|
||||
finalAnimationName = finalAnimationName.replace(/left|right|up|down|in|out/, reverseAnimation);
|
||||
}
|
||||
|
||||
warn('finalAnimationName is ' + finalAnimationName + '.');
|
||||
|
||||
// Bind internal 'cleanup' callback
|
||||
fromPage.bind('webkitAnimationEnd', navigationEndHandler);
|
||||
|
||||
// Trigger animations
|
||||
$body.addClass('animating ' + is3d);
|
||||
|
||||
var lastScroll = window.pageYOffset;
|
||||
|
||||
// Position the incoming page so toolbar is at top of
|
||||
// viewport regardless of scroll position on from page
|
||||
if (jQTSettings.trackScrollPositions === true) {
|
||||
toPage.css('top', window.pageYOffset - (toPage.data('lastScroll') || 0));
|
||||
}
|
||||
|
||||
toPage.addClass(finalAnimationName + ' in current');
|
||||
fromPage.removeClass('current').addClass(finalAnimationName + ' out inmotion');
|
||||
|
||||
if (jQTSettings.trackScrollPositions === true) {
|
||||
fromPage.data('lastScroll', lastScroll);
|
||||
$('.scroll', fromPage).each(function() {
|
||||
$(this).data('lastScroll', this.scrollTop);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
toPage.addClass('current in');
|
||||
fromPage.removeClass('current');
|
||||
navigationEndHandler();
|
||||
}
|
||||
|
||||
// Housekeeping
|
||||
$currentPage = toPage;
|
||||
if (goingBack) {
|
||||
history.shift();
|
||||
} else {
|
||||
addPageToHistory($currentPage, animation);
|
||||
}
|
||||
setHash($currentPage.attr('id'));
|
||||
|
||||
// Private navigationEnd callback
|
||||
function navigationEndHandler(event) {
|
||||
var bufferTime = tapBuffer;
|
||||
|
||||
if ($.support.animationEvents && animation && jQTSettings.useAnimations) {
|
||||
fromPage.unbind('webkitAnimationEnd', navigationEndHandler);
|
||||
fromPage.removeClass(finalAnimationName + ' out inmotion');
|
||||
if (finalAnimationName) {
|
||||
toPage.removeClass(finalAnimationName);
|
||||
}
|
||||
$body.removeClass('animating animating3d');
|
||||
if (jQTSettings.trackScrollPositions === true) {
|
||||
toPage.css('top', -toPage.data('lastScroll'));
|
||||
|
||||
// Have to make sure the scroll/style resets
|
||||
// are outside the flow of this function.
|
||||
setTimeout(function() {
|
||||
toPage.css('top', 0);
|
||||
window.scroll(0, toPage.data('lastScroll'));
|
||||
$('.scroll', toPage).each(function() {
|
||||
this.scrollTop = - $(this).data('lastScroll');
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
} else {
|
||||
fromPage.removeClass(finalAnimationName + ' out inmotion');
|
||||
if (finalAnimationName) {
|
||||
toPage.removeClass(finalAnimationName);
|
||||
}
|
||||
bufferTime += 260;
|
||||
}
|
||||
|
||||
// 'in' class is intentionally delayed,
|
||||
// as it is our ghost click hack
|
||||
setTimeout(function() {
|
||||
toPage.removeClass('in');
|
||||
window.scroll(0,0);
|
||||
}, bufferTime);
|
||||
|
||||
fromPage.unselect();
|
||||
|
||||
// Trigger custom events
|
||||
toPage.trigger('pageAnimationEnd', {
|
||||
direction:'in',
|
||||
animation: animation,
|
||||
back: goingBack
|
||||
});
|
||||
fromPage.trigger('pageAnimationEnd', {
|
||||
direction:'out',
|
||||
animation: animation,
|
||||
back: goingBack
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function reverseAnimation(animation) {
|
||||
var opposites={
|
||||
'up' : 'down',
|
||||
'down' : 'up',
|
||||
'left' : 'right',
|
||||
'right' : 'left',
|
||||
'in' : 'out',
|
||||
'out' : 'in'
|
||||
};
|
||||
|
||||
return opposites[animation] || animation;
|
||||
}
|
||||
|
||||
function getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
// Error checking
|
||||
if (history.length < 1) {
|
||||
warn('History is empty.');
|
||||
}
|
||||
|
||||
if (history.length === 1) {
|
||||
warn('You are on the first panel.');
|
||||
window.history.go(-1);
|
||||
}
|
||||
|
||||
var from = history[0],
|
||||
to = history[1];
|
||||
|
||||
if (doNavigation(from.page, to.page, from.animation, true)) {
|
||||
return publicObj;
|
||||
} else {
|
||||
warn('Could not go back.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function goTo(toPage, animation) {
|
||||
var fromPage = history[0].page;
|
||||
|
||||
if (typeof animation === 'string') {
|
||||
for (var i=0, max=animations.length; i < max; i++) {
|
||||
if (animations[i].name === animation) {
|
||||
animation = animations[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof toPage === 'string') {
|
||||
var nextPage = $(toPage);
|
||||
|
||||
if (nextPage.length < 1) {
|
||||
showPageByHref(toPage, {
|
||||
animation: animation
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
toPage = nextPage;
|
||||
}
|
||||
}
|
||||
if (doNavigation(fromPage, toPage, animation)) {
|
||||
return publicObj;
|
||||
} else {
|
||||
warn('Could not animate pages.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function hashChangeHandler(e) {
|
||||
if (location.hash === history[0].hash) {
|
||||
warn('We are on the right panel.');
|
||||
return true;
|
||||
} else if (location.hash === '') {
|
||||
goBack();
|
||||
return true;
|
||||
} else if (history[1] && location.hash === history[1].hash) {
|
||||
goBack();
|
||||
return true;
|
||||
} else {
|
||||
// Lastly, just try going to the ID...
|
||||
warn('Could not find ID in history, just forwarding to DOM element.');
|
||||
goTo($(location.hash), jQTSettings.defaultAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
function initHairExtensions(options) {
|
||||
// Preload images
|
||||
if (jQTSettings.preloadImages) {
|
||||
for (var i = jQTSettings.preloadImages.length - 1; i >= 0; i--) {
|
||||
(new Image()).src = jQTSettings.preloadImages[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Set appropriate icon
|
||||
// (retina display available in iOS 4.2 and later.)
|
||||
var precomposed = (jQTSettings.addGlossToIcon) ? '' : '-precomposed';
|
||||
if (jQTSettings.icon) {
|
||||
hairExtensions += '<link rel="apple-touch-icon' + precomposed + '" href="' + jQTSettings.icon + '" />';
|
||||
}
|
||||
if (jQTSettings.icon4) {
|
||||
hairExtensions += '<link rel="apple-touch-icon' + precomposed + '" sizes="114x114" href="' + jQTSettings.icon4 + '" />';
|
||||
}
|
||||
// Set startup screen
|
||||
if (jQTSettings.startupScreen) {
|
||||
hairExtensions += '<link rel="apple-touch-startup-image" href="' + jQTSettings.startupScreen + '" />';
|
||||
}
|
||||
|
||||
// Set viewport
|
||||
if (jQTSettings.fixedViewport) {
|
||||
hairExtensions += '<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>';
|
||||
}
|
||||
|
||||
// Set full-screen
|
||||
if (jQTSettings.fullScreen) {
|
||||
hairExtensions += '<meta name="apple-mobile-web-app-capable" content="yes" />';
|
||||
if (jQTSettings.statusBar) {
|
||||
hairExtensions += '<meta name="apple-mobile-web-app-status-bar-style" content="' + jQTSettings.statusBar + '" />';
|
||||
}
|
||||
}
|
||||
|
||||
// Attach hair extensions
|
||||
if (hairExtensions) {
|
||||
$head.prepend(hairExtensions);
|
||||
}
|
||||
}
|
||||
|
||||
function initFXExtensions() {
|
||||
// Define public jQuery functions
|
||||
$.fn.isExternalLink = function() {
|
||||
var $el = $(this);
|
||||
return ($el.attr('target') === '_blank' || $el.attr('rel') === 'external' || $el.is('a[href^="http://maps.google.com"], a[href^="mailto:"], a[href^="tel:"], a[href^="javascript:"], a[href*="youtube.com/v"], a[href*="youtube.com/watch"]'));
|
||||
};
|
||||
$.fn.makeActive = function() {
|
||||
return $(this).addClass('active');
|
||||
};
|
||||
$.fn.unselect = function(obj) {
|
||||
if (obj) {
|
||||
obj.removeClass('active');
|
||||
} else {
|
||||
$('.active').removeClass('active');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getAnimation(el) {
|
||||
var animation;
|
||||
|
||||
for (var i=0, max=animations.length; i < max; i++) {
|
||||
if (el.is(animations[i].selector)) {
|
||||
animation = animations[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!animation) {
|
||||
warn('Animation could not be found. Using ' + jQTSettings.defaultAnimation + '.');
|
||||
animation = jQTSettings.defaultAnimation;
|
||||
}
|
||||
return animation;
|
||||
}
|
||||
|
||||
function insertPages(nodes, animation) {
|
||||
|
||||
var targetPage = null;
|
||||
|
||||
// Call dom.createElement element directly
|
||||
// instead of relying on $(nodes), to work around:
|
||||
// https://github.com/madrobby/zepto/issues/312
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = nodes;
|
||||
|
||||
$(div).children().each(function(index, node) {
|
||||
var $node = $(this);
|
||||
if (!$node.attr('id')) {
|
||||
$node.attr('id', 'page-' + (++newPageCount));
|
||||
}
|
||||
|
||||
// Remove any existing instance
|
||||
$('#' + $node.attr('id')).remove();
|
||||
|
||||
$body.append($node);
|
||||
$body.trigger('pageInserted', {page: $node});
|
||||
|
||||
if ($node.hasClass('current') || !targetPage) {
|
||||
targetPage = $node;
|
||||
}
|
||||
});
|
||||
if (targetPage !== null) {
|
||||
goTo(targetPage, animation);
|
||||
return targetPage;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function orientationChangeHandler() {
|
||||
scrollTo(0,0);
|
||||
orientation = Math.abs(window.orientation) === 90 ? 'landscape' : 'portrait';
|
||||
$body.removeClass('portrait landscape').addClass(orientation).trigger('turn', {orientation: orientation});
|
||||
}
|
||||
|
||||
function setHash(hash) {
|
||||
// Sanitize
|
||||
if (jQTSettings.updateHash) {
|
||||
location.hash = '#' + hash.replace(/^#/, '');
|
||||
}
|
||||
}
|
||||
|
||||
// Document ready stuff
|
||||
function start() {
|
||||
// Store some properties in a support object
|
||||
if (!$.support) $.support = {};
|
||||
$.support.animationEvents = (typeof window.WebKitAnimationEvent !== 'undefined');
|
||||
$.support.touch = (typeof window.TouchEvent !== 'undefined') && (window.navigator.userAgent.indexOf('Mobile') > -1) && jQTSettings.useFastTouch;
|
||||
$.support.transform3d = supportForTransform3d();
|
||||
$.support.ios5 = supportIOS5();
|
||||
|
||||
if (!$.support.touch) {
|
||||
warn('This device does not support touch interaction, or it has been deactivated by the developer. Some features might be unavailable.');
|
||||
}
|
||||
if (!$.support.transform3d) {
|
||||
warn('This device does not support 3d animation. 2d animations will be used instead.');
|
||||
}
|
||||
|
||||
// Add extensions
|
||||
for (var i=0, max=extensions.length; i < max; i++) {
|
||||
var fn = extensions[i];
|
||||
if ($.isFunction(fn)) {
|
||||
$.extend(publicObj, fn(publicObj));
|
||||
}
|
||||
}
|
||||
|
||||
// Add extensions tapHandlers
|
||||
for (var j=0, maxTapHandlers=extTapHandlers.length; j < maxTapHandlers; j++) {
|
||||
addTapHandler(extTapHandlers[j]);
|
||||
}
|
||||
// Add default tapHandlers
|
||||
addDefaultTapHandlers();
|
||||
|
||||
// Add animations
|
||||
for (var k=0, maxAnimations=defaults.animations.length; k < maxAnimations; k++) {
|
||||
var animation = defaults.animations[k];
|
||||
if (jQTSettings[animation.name + 'Selector'] !== undefined) {
|
||||
animation.selector = jQTSettings[animation.name + 'Selector'];
|
||||
}
|
||||
addAnimation(animation);
|
||||
}
|
||||
|
||||
// Create an array of stuff that needs touch event handling
|
||||
touchSelectors.push(jQTSettings.touchSelector);
|
||||
touchSelectors.push(jQTSettings.backSelector);
|
||||
touchSelectors.push(jQTSettings.submitSelector);
|
||||
$(touchSelectors.join(', ')).css('-webkit-touch-callout', 'none');
|
||||
|
||||
// Make sure we have a jqt element
|
||||
$body = $('#jqt');
|
||||
var anatomyLessons = [];
|
||||
|
||||
if ($body.length === 0) {
|
||||
warn('Could not find an element with the id "jqt", so the body id has been set to "jqt". If you are having any problems, wrapping your panels in a div with the id "jqt" might help.');
|
||||
$body = $(document.body).attr('id', 'jqt');
|
||||
}
|
||||
|
||||
// Add some specific css if need be
|
||||
if ($.support.transform3d) {
|
||||
anatomyLessons.push('supports3d');
|
||||
}
|
||||
|
||||
if (jQTSettings.useTouchScroll) {
|
||||
if ($.support.ios5) {
|
||||
anatomyLessons.push('touchscroll');
|
||||
} else {
|
||||
anatomyLessons.push('autoscroll');
|
||||
}
|
||||
}
|
||||
|
||||
if (jQTSettings.fullScreenClass && window.navigator.standalone === true) {
|
||||
anatomyLessons.push(jQTSettings.fullScreenClass, jQTSettings.statusBar);
|
||||
}
|
||||
|
||||
// Bind events
|
||||
$body
|
||||
.addClass(anatomyLessons.join(' '))
|
||||
.bind('click', clickHandler)
|
||||
.bind('orientationchange', orientationChangeHandler)
|
||||
.bind('submit', submitHandler)
|
||||
.bind('tap', tapHandler)
|
||||
.bind($.support.touch ? 'touchstart' : 'mousedown', touchStartHandler)
|
||||
.trigger('orientationchange');
|
||||
|
||||
$(window).bind('hashchange', hashChangeHandler);
|
||||
|
||||
var startHash = location.hash;
|
||||
|
||||
// Determine what the initial view should be
|
||||
if ($('#jqt > .current').length === 0) {
|
||||
$currentPage = $('#jqt > *:first-child').addClass('current');
|
||||
} else {
|
||||
$currentPage = $('#jqt > .current');
|
||||
}
|
||||
|
||||
setHash($currentPage.attr('id'));
|
||||
addPageToHistory($currentPage);
|
||||
|
||||
if ($(startHash).length === 1) {
|
||||
goTo(startHash);
|
||||
}
|
||||
}
|
||||
|
||||
function showPageByHref(href, options) {
|
||||
|
||||
var defaults = {
|
||||
data: null,
|
||||
method: 'GET',
|
||||
animation: null,
|
||||
callback: null,
|
||||
$referrer: null
|
||||
};
|
||||
|
||||
var settings = $.extend({}, defaults, options);
|
||||
|
||||
if (href !== '#') {
|
||||
$.ajax({
|
||||
url: href,
|
||||
data: settings.data,
|
||||
type: settings.method,
|
||||
success: function (data) {
|
||||
var firstPage = insertPages(data, settings.animation);
|
||||
if (firstPage) {
|
||||
if (settings.method === 'GET' && jQTSettings.cacheGetRequests === true && settings.$referrer) {
|
||||
settings.$referrer.attr('href', '#' + firstPage.attr('id'));
|
||||
}
|
||||
if (settings.callback) {
|
||||
settings.callback(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function (data) {
|
||||
if (settings.$referrer) {
|
||||
settings.$referrer.unselect();
|
||||
}
|
||||
if (settings.callback) {
|
||||
settings.callback(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (settings.$referrer) {
|
||||
settings.$referrer.unselect();
|
||||
}
|
||||
}
|
||||
|
||||
function submitHandler(e, callback) {
|
||||
|
||||
$(':focus').trigger('blur');
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var $form = (typeof(e)==='string') ? $(e).eq(0) : (e.target ? $(e.target) : $(e));
|
||||
|
||||
if ($form.length && $form.is(jQTSettings.formSelector) && $form.attr('action')) {
|
||||
showPageByHref($form.attr('action'), {
|
||||
data: $form.serialize(),
|
||||
method: $form.attr('method') || 'POST',
|
||||
animation: getAnimation($form),
|
||||
callback: callback
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function submitParentForm($el) {
|
||||
|
||||
var $form = $el.closest('form');
|
||||
if ($form.length === 0) {
|
||||
warn('No parent form found.');
|
||||
} else {
|
||||
warn('About to submit parent form.');
|
||||
$form.trigger('submit');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function supportForTransform3d() {
|
||||
|
||||
var head, body, style, div, result;
|
||||
|
||||
head = document.getElementsByTagName('head')[0];
|
||||
body = document.body;
|
||||
|
||||
style = document.createElement('style');
|
||||
style.textContent = '@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-webkit-transform-3d){#jqt-3dtest{height:3px}}';
|
||||
|
||||
div = document.createElement('div');
|
||||
div.id = 'jqt-3dtest';
|
||||
|
||||
// Add to the page
|
||||
head.appendChild(style);
|
||||
body.appendChild(div);
|
||||
|
||||
// Check the result
|
||||
result = div.offsetHeight === 3;
|
||||
|
||||
// Clean up
|
||||
style.parentNode.removeChild(style);
|
||||
div.parentNode.removeChild(div);
|
||||
|
||||
// Pass back result
|
||||
warn('Support for 3d transforms: ' + result + '.');
|
||||
return result;
|
||||
}
|
||||
|
||||
function supportIOS5() {
|
||||
var support = false;
|
||||
var REGEX_IOS_VERSION = /OS (\d+)(_\d+)* like Mac OS X/i;
|
||||
|
||||
var agentString = window.navigator.userAgent;
|
||||
if (REGEX_IOS_VERSION.test(agentString)) {
|
||||
support = (REGEX_IOS_VERSION.exec(agentString)[1] >= 5);
|
||||
}
|
||||
return support;
|
||||
}
|
||||
|
||||
function touchStartHandler(e) {
|
||||
|
||||
var $el = $(e.target),
|
||||
selectors = touchSelectors.join(', ');
|
||||
|
||||
// Find the nearest tappable ancestor
|
||||
if (!$el.is(selectors)) {
|
||||
$el = $el.closest(selectors);
|
||||
}
|
||||
|
||||
// Make sure we have a tappable element
|
||||
if ($el.length && $el.attr('href')) {
|
||||
$el.addClass('active');
|
||||
}
|
||||
|
||||
// Remove our active class if we move
|
||||
$el.on($.support.touch ? 'touchmove' : 'mousemove', function() {
|
||||
$el.removeClass('active');
|
||||
});
|
||||
|
||||
$el.on('touchend', function() {
|
||||
$el.unbind('touchmove mousemove');
|
||||
});
|
||||
}
|
||||
|
||||
function tapHandler(e) {
|
||||
|
||||
if (e.isDefaultPrevented()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Grab the target element
|
||||
var $el = $(e.target);
|
||||
|
||||
// Find the nearest tappable ancestor
|
||||
if (!$el.is(touchSelectors.join(', '))) {
|
||||
$el = $el.closest(touchSelectors.join(', '));
|
||||
}
|
||||
|
||||
// Make sure we have a tappable element
|
||||
if (!$el.length || !$el.attr('href')) {
|
||||
warn('Could not find a link related to tapped element.');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Init some vars
|
||||
var target = $el.attr('target'),
|
||||
hash = $el.prop('hash'),
|
||||
href = $el.attr('href');
|
||||
|
||||
var params = {
|
||||
e: e,
|
||||
$el: $el,
|
||||
target: target,
|
||||
hash: hash,
|
||||
href: href,
|
||||
jQTSettings: jQTSettings
|
||||
};
|
||||
|
||||
// Loop thru all handlers
|
||||
for (var i=0, len=tapHandlers.length; i<len; i++) {
|
||||
var handler = tapHandlers[i];
|
||||
var supported = handler.isSupported(e, params);
|
||||
if (supported) {
|
||||
var flag = handler.fn(e, params);
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addDefaultTapHandlers() {
|
||||
addTapHandler({
|
||||
name: 'external-link',
|
||||
isSupported: function(e, params) {
|
||||
return params.$el.isExternalLink();
|
||||
},
|
||||
fn: function(e, params) {
|
||||
params.$el.unselect();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
addTapHandler({
|
||||
name: 'back-selector',
|
||||
isSupported: function(e, params) {
|
||||
return params.$el.is(params.jQTSettings.backSelector);
|
||||
},
|
||||
fn: function(e, params) {
|
||||
// User clicked or tapped a back button
|
||||
goBack(params.hash);
|
||||
}
|
||||
});
|
||||
addTapHandler({
|
||||
name: 'submit-selector',
|
||||
isSupported: function(e, params) {
|
||||
return params.$el.is(params.jQTSettings.submitSelector);
|
||||
},
|
||||
fn: function(e, params) {
|
||||
// User clicked or tapped a submit element
|
||||
submitParentForm(params.$el);
|
||||
}
|
||||
});
|
||||
addTapHandler({
|
||||
name: 'webapp',
|
||||
isSupported: function(e, params) {
|
||||
return params.target === '_webapp';
|
||||
},
|
||||
fn: function(e, params) {
|
||||
// User clicked or tapped an internal link, fullscreen mode
|
||||
window.location = params.href;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
addTapHandler({
|
||||
name: 'no-op',
|
||||
isSupported: function(e, params) {
|
||||
return params.href === '#';
|
||||
},
|
||||
fn: function(e, params) {
|
||||
// Allow tap on item with no href
|
||||
params.$el.unselect();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
addTapHandler({
|
||||
name: 'standard',
|
||||
isSupported: function(e, params) {
|
||||
return params.hash && params.hash !== '#';
|
||||
},
|
||||
fn: function(e, params) {
|
||||
var animation = getAnimation(params.$el);
|
||||
// Internal href
|
||||
params.$el.addClass('active');
|
||||
goTo(
|
||||
$(params.hash).data('referrer', params.$el),
|
||||
animation,
|
||||
params.$el.hasClass('reverse')
|
||||
);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
addTapHandler({
|
||||
name: 'external',
|
||||
isSupported: function(e, params) {
|
||||
return true;
|
||||
},
|
||||
fn: function(e, params) {
|
||||
var animation = getAnimation(params.$el);
|
||||
|
||||
// External href
|
||||
params.$el.addClass('loading active');
|
||||
showPageByHref(params.$el.attr('href'), {
|
||||
animation: animation,
|
||||
callback: function() {
|
||||
params.$el.removeClass('loading');
|
||||
setTimeout($.fn.unselect, 250, params.$el);
|
||||
},
|
||||
$referrer: params.$el
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get the party started
|
||||
jQTSettings = $.extend({}, defaults, options);
|
||||
|
||||
initHairExtensions(options);
|
||||
|
||||
initFXExtensions();
|
||||
|
||||
// Expose public methods and properties
|
||||
publicObj = {
|
||||
addAnimation: addAnimation,
|
||||
animations: animations,
|
||||
getOrientation: getOrientation,
|
||||
goBack: goBack,
|
||||
insertPages: insertPages,
|
||||
goTo: goTo,
|
||||
history: history,
|
||||
settings: jQTSettings,
|
||||
submitForm: submitHandler
|
||||
};
|
||||
|
||||
// must be called publicObj assignement to prevent timing problem with extension loading.
|
||||
jQTSettings.starter(start);
|
||||
|
||||
return publicObj;
|
||||
};
|
||||
|
||||
$.jQTouch.prototype.extensions = [];
|
||||
$.jQTouch.prototype.tapHandlers = [];
|
||||
|
||||
// Extensions directly manipulate the jQTouch object,
|
||||
// before it's initialized
|
||||
$.jQTouch.addExtension = function(extension) {
|
||||
$.jQTouch.prototype.extensions.push(extension);
|
||||
};
|
||||
|
||||
// Experimental tap handlers that can bypass
|
||||
// default jQTouch tap handling
|
||||
$.jQTouch.addTapHandler = function(extension) {
|
||||
$.jQTouch.prototype.tapHandlers.push(extension);
|
||||
};
|
||||
|
||||
})(); // Double closure, ALL THE WAY ACROSS THE SKY
|
||||
@@ -808,17 +808,19 @@ var templates = {
|
||||
|
||||
// a single tool's link in the tool panel; will load the tool form in the center panel
|
||||
tool_link : _.template([
|
||||
'<span class="labels">',
|
||||
'<% _.each( labels, function( label ){ %>',
|
||||
'<span class="label label-default label-<%- label %>">',
|
||||
'<%- label %>',
|
||||
'</span>',
|
||||
'<% }); %>',
|
||||
'</span>',
|
||||
'<a class="<%- id %> tool-link" href="<%= link %>" target="<%- target %>" minsizehint="<%- min_width %>">',
|
||||
'<%- name %>',
|
||||
'</a>',
|
||||
' <%- description %>'
|
||||
'<span class="labels">',
|
||||
'<% _.each( labels, function( label ){ %>',
|
||||
'<span class="label label-default label-<%- label %>">',
|
||||
'<%- label %>',
|
||||
'</span>',
|
||||
'<% }); %>',
|
||||
'</span>',
|
||||
'<span class="tool-old-link">',
|
||||
'<%- name %>',
|
||||
'</span>',
|
||||
' <%- description %>',
|
||||
'</a>'
|
||||
].join('')),
|
||||
|
||||
// the tool form for entering tool parameters, viewing help and executing the tool
|
||||
|
||||
@@ -301,6 +301,7 @@ var View = Backbone.View.extend({
|
||||
} catch( e ) {
|
||||
this._handleDropStatus( 'danger' );
|
||||
}
|
||||
ev.preventDefault();
|
||||
},
|
||||
|
||||
/** Highlight drag result */
|
||||
|
||||
@@ -312,7 +312,7 @@ div.unified-panel-body {
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
}
|
||||
@panel-bg-color: #DFE5F9;
|
||||
|
||||
div.unified-panel-body-background {
|
||||
background: none repeat scroll 0 0 @panel-bg-color;
|
||||
}
|
||||
@@ -1546,6 +1546,15 @@ div.toolTitle
|
||||
}
|
||||
}
|
||||
|
||||
div a.tool-link {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
|
||||
span.tool-old-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
div.toolSectionBody div.toolPanelLabel
|
||||
{
|
||||
padding-top: 5px;
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
@bs-danger: #d9534f;
|
||||
@bs-info: #5bc0de;
|
||||
|
||||
@panel-bg-color: #DFE5F9;
|
||||
|
||||
// Derived variables used below
|
||||
|
||||
@sat: saturation(@base-color);
|
||||
|
||||
@@ -34,4 +34,7 @@
|
||||
|
||||
// Theme, expects tmp-site-config.less written by grunt
|
||||
@import "tmp-site-config.less";
|
||||
@import "theme/blue.less";
|
||||
@import "theme/blue.less";
|
||||
|
||||
// Theme: plain
|
||||
//@import "theme/plain.less";
|
||||
|
||||
@@ -1,438 +0,0 @@
|
||||
// Parts taken from iui.css (c) 2007-8 by iUI Project Members, see LICENSE.txt for license
|
||||
|
||||
@import "galaxy_bootstrap/variables.less";
|
||||
@import "galaxy_variables.less";
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Helvetica;
|
||||
background: #FFFFFF;
|
||||
color: #000000;
|
||||
overflow-x: hidden;
|
||||
-webkit-user-select: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
body > *:not(.toolbar) {
|
||||
display: none;
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
min-height: 372px;
|
||||
}
|
||||
|
||||
body[orient="landscape"] > *:not(.toolbar) {
|
||||
min-height: 268px;
|
||||
}
|
||||
|
||||
body > *[selected="true"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
a[selected], a:active {
|
||||
background-color: #194fdb !important;
|
||||
background-image: url(../iui/listArrowSel.png), url(../iui/selection.png) !important;
|
||||
background-repeat: no-repeat, repeat-x;
|
||||
background-position: right center, left top;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
a[selected="progress"] {
|
||||
background-image: url(../iui/loading.gif), url(../iui/selection.png) !important;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
body > .toolbar {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
border-bottom: 1px solid #2d3642;
|
||||
padding: 10px;
|
||||
height: 45px;
|
||||
background: url(../iui/toolbar.png) #6d84a2 repeat-x;
|
||||
}
|
||||
|
||||
.toolbar > h1 {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
left: 50%;
|
||||
margin: 1px 0 0 -75px;
|
||||
height: 45px;
|
||||
font-size: 20px;
|
||||
width: 150px;
|
||||
font-weight: bold;
|
||||
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
body[orient="landscape"] > .toolbar > h1 {
|
||||
margin-left: -125px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
body > .toolbar.masthead {
|
||||
background: @navbar-inverse-bg;
|
||||
}
|
||||
|
||||
body > .toolbar.masthead > h1 {
|
||||
left: 0; margin-left: 0; width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.button {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
top: 8px;
|
||||
right: 6px;
|
||||
margin: 0;
|
||||
border-width: 0 5px;
|
||||
padding: 0 3px;
|
||||
width: auto;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
font-family: inherit;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
text-shadow: rgba(0, 0, 0, 0.6) 0px -1px 0;
|
||||
text-overflow: ellipsis;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background: none;
|
||||
-webkit-border-image: url(../iui/toolButton.png) 0 5 0 5;
|
||||
}
|
||||
|
||||
.blueButton {
|
||||
-webkit-border-image: url(../iui/blueButton.png) 0 5 0 5;
|
||||
border-width: 0 5px;
|
||||
}
|
||||
|
||||
.leftButton {
|
||||
left: 6px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
#backButton {
|
||||
display: none;
|
||||
left: 6px;
|
||||
right: auto;
|
||||
padding: 0;
|
||||
max-width: 55px;
|
||||
border-width: 0 8px 0 14px;
|
||||
-webkit-border-image: url(../iui/backButton.png) 0 8 0 14;
|
||||
}
|
||||
|
||||
.whiteButton,
|
||||
.grayButton {
|
||||
display: block;
|
||||
border-width: 0 12px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.whiteButton {
|
||||
-webkit-border-image: url(../iui/whiteButton.png) 0 12 0 12;
|
||||
text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
|
||||
}
|
||||
|
||||
.grayButton {
|
||||
-webkit-border-image: url(../iui/grayButton.png) 0 12 0 12;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
body > ul > li {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid #E0E0E0;
|
||||
padding: 8px 0 8px 10px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
body > ul > li.group {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
margin-bottom: -2px;
|
||||
border-top: 1px solid #7d7d7d;
|
||||
border-bottom: 1px solid #999999;
|
||||
padding: 1px 10px;
|
||||
background: url(../iui/listGroup.png) repeat-x;
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
text-shadow: rgba(0, 0, 0, 0.4) 0 1px 0;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
body > ul > li.group:first-child {
|
||||
top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
body > ul > li > a {
|
||||
display: block;
|
||||
margin: -8px 0 -8px -10px;
|
||||
padding: 8px 32px 8px 10px;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
background: url(../iui/listArrow.png) no-repeat right center;
|
||||
}
|
||||
|
||||
a[target="_replace"] {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
padding-top: 25px;
|
||||
padding-bottom: 25px;
|
||||
font-size: 18px;
|
||||
color: cornflowerblue;
|
||||
background-color: #FFFFFF;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
body > .dialog {
|
||||
top: 0;
|
||||
width: 100%;
|
||||
min-height: 417px;
|
||||
z-index: 2;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
padding: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.dialog > fieldset {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border: none;
|
||||
border-top: 1px solid #6d84a2;
|
||||
padding: 10px 6px;
|
||||
background: url(../iui/toolbar.png) #7388a5 repeat-x;
|
||||
}
|
||||
|
||||
.dialog > fieldset > h1 {
|
||||
margin: 0 10px 0 10px;
|
||||
padding: 0;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dialog > fieldset > label {
|
||||
position: absolute;
|
||||
margin: 16px 0 0 6px;
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
|
||||
|
||||
input:not(input[type|=radio]):not(input[type|=checkbox]) {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin: 8px 0 0 0;
|
||||
padding: 6px 6px 6px 44px;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
body > .panel {
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
padding: 10px;
|
||||
background: #c8c8c8 url(../iui/pinstripes.png);
|
||||
}
|
||||
|
||||
.panel > fieldset {
|
||||
position: relative;
|
||||
margin: 0 0 20px 0;
|
||||
padding: 0;
|
||||
background: #FFFFFF;
|
||||
-webkit-border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
border: 1px solid #999999;
|
||||
text-align: right;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.row {
|
||||
position: relative;
|
||||
min-height: 42px;
|
||||
border-bottom: 1px solid #999999;
|
||||
-webkit-border-radius: 0;
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
fieldset > .row:last-child {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.row > input:not(input[type|=radio]):not(input[type|=checkbox]) {
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding: 12px 10px 0 110px;
|
||||
height: 42px;
|
||||
background: none;
|
||||
}
|
||||
.row > input[type|=radio], .row > input[type|=checkbox] {
|
||||
margin: 7px 7px 0 0;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
.row > label {
|
||||
position: absolute;
|
||||
margin: 0 0 0 14px;
|
||||
line-height: 42px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.row > a {
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
display: block;
|
||||
padding: 8px 32px 8px 14px;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
background: url(../iui/listArrow.png) no-repeat right center;
|
||||
}
|
||||
|
||||
.row > .error {
|
||||
height: 25px;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
padding: 0 0 0 110px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.row > span {
|
||||
position: absolute;
|
||||
padding: 12px 10px 0 110px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.row > .toggle {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
width: 100px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
border: 1px solid #888888;
|
||||
-webkit-border-radius: 6px;
|
||||
background: #FFFFFF url(../iui/toggle.png) repeat-x;
|
||||
font-size: 19px;
|
||||
font-weight: bold;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.toggle[toggled="true"] {
|
||||
border: 1px solid #143fae;
|
||||
background: #194fdb url(../iui/toggleOn.png) repeat-x;
|
||||
}
|
||||
|
||||
.toggleOn {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
top: 0;
|
||||
color: #FFFFFF;
|
||||
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
|
||||
}
|
||||
|
||||
.toggleOff {
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
right: 0;
|
||||
top: 0;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.toggle[toggled="true"] > .toggleOn {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.toggle[toggled="true"] > .toggleOff {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
width: 40px;
|
||||
height: 28px;
|
||||
border: 1px solid #888888;
|
||||
-webkit-border-radius: 6px;
|
||||
background: #ffffff url(../iui/thumb.png) repeat-x;
|
||||
}
|
||||
|
||||
.toggle[toggled="true"] > .thumb {
|
||||
left: auto;
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
.panel > h2 {
|
||||
margin: 0 0 8px 14px;
|
||||
font-size: inherit;
|
||||
font-weight: bold;
|
||||
color: #4d4d70;
|
||||
text-shadow: rgba(255, 255, 255, 0.75) 2px 2px 0;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
#preloader {
|
||||
display: none;
|
||||
background-image: url(loading.gif), url(selection.png),
|
||||
url(blueButton.png), url(listArrowSel.png), url(listGroup.png);
|
||||
}
|
||||
|
||||
// State colors
|
||||
|
||||
.state-color-queued {
|
||||
background: @state-default-bg;
|
||||
}
|
||||
|
||||
.state-color-ok {
|
||||
background: @state-success-bg;
|
||||
}
|
||||
|
||||
.state-color-error {
|
||||
background: @state-danger-bg;
|
||||
}
|
||||
|
||||
.state-color-running {
|
||||
background: @state-running-bg;
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
@panel-bg-color: white;
|
||||
@side-panel-bg: white;
|
||||
@base-text-color: black;
|
||||
|
||||
@brand-primary: #8181f3;
|
||||
@base-color-1: black;
|
||||
@navbar-inverse-color: black;
|
||||
@navbar-inverse-bg: white;
|
||||
@navbar-inverse-link-color: black;
|
||||
@navbar-inverse-link-hover-color: @gray-dark;
|
||||
@jumbotron-bg: white;
|
||||
|
||||
@form-heading-bg: black;
|
||||
@border-radius-large: 0px;
|
||||
@border-radius-base: 0px;
|
||||
@input-border-radius: 0px;
|
||||
// y'all're seriously obsesed with round edges.
|
||||
* {
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
.state-icon {
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
|
||||
|
||||
// Tables
|
||||
@table-heading-bg: black;
|
||||
@table-border-color: black;
|
||||
th a {
|
||||
color: white;
|
||||
&:hover {
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
|
||||
.jumbotron {
|
||||
box-shadow: 0 0 11px black;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
li.dropdown:hover a.dropdown-toggle:focus {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#masthead .navbar-brand a {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
@navbar-hover-thingy-link-color: darken(white, 10%);
|
||||
@navbar-hover-thingy-background: lighten(black, 10%);
|
||||
|
||||
#masthead {
|
||||
.nav > li > a {
|
||||
&:hover {
|
||||
color: @navbar-hover-thingy-link-color !important;
|
||||
}
|
||||
}
|
||||
.navbar-tabs {
|
||||
.toggle {
|
||||
color : @navbar-hover-thingy-link-color !important;
|
||||
}
|
||||
.dropdown-note {
|
||||
color : @navbar-hover-thingy-link-color !important;
|
||||
}
|
||||
}
|
||||
li.dropdown:hover {
|
||||
background: @navbar-hover-thingy-background;
|
||||
}
|
||||
li.dropdown > a:hover .caret {
|
||||
border-top-color: @navbar-hover-thingy-link-color !important;
|
||||
border-bottom-color: @navbar-hover-thingy-link-color !important;
|
||||
}
|
||||
li.dropdown.active > a:hover {
|
||||
color: @navbar-hover-thingy-link-color !important;
|
||||
background: @navbar-hover-thingy-background !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Tool links
|
||||
|
||||
a.tool-link {
|
||||
//display: block;
|
||||
//padding: 0.5em;
|
||||
|
||||
&:hover {
|
||||
background: @gray-lighter;
|
||||
}
|
||||
}
|
||||
|
||||
@navbar-default-bg: white;
|
||||
|
||||
#masthead {
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
|
||||
.search-clear.fa.fa-times-circle {
|
||||
color: #d82c2c
|
||||
}
|
||||
|
||||
div.toolMenuContainer {
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
|
||||
#tool-search {
|
||||
padding-left: 1em;
|
||||
background: white;
|
||||
//border-bottom: 1px solid @gray-light
|
||||
top: 65px; // seems to be the real / correct value.
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#tool-search-query {
|
||||
border: 1px solid transparent;
|
||||
background: #eee;
|
||||
|
||||
&:focus, &:active {
|
||||
background: white;
|
||||
border: 1px solid black;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#tool-search {
|
||||
padding-left: 1em;
|
||||
background: white;
|
||||
//border-bottom: 1px solid @gray-light
|
||||
top: 65px; // seems to be the real / correct value.
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
div.search div.search-input input {
|
||||
border: 1px solid transparent;
|
||||
background: #eee;
|
||||
|
||||
&:focus, &:active {
|
||||
background: white;
|
||||
border: 1px solid black;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Easy to click tool section titles
|
||||
div.toolSectionWrapper {
|
||||
margin-bottom: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
padding-left: 0px;
|
||||
border-left: 1px solid black;
|
||||
margin-left: 0.2em;
|
||||
|
||||
div.toolSectionTitle {
|
||||
padding-left: 0.2em;
|
||||
border-left: 2px solid black;
|
||||
}
|
||||
}
|
||||
|
||||
div.toolTitleNoSection {
|
||||
margin-bottom: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
padding-left: 0.5em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div.toolSectionTitle, div.toolSectionWrapper {
|
||||
a {
|
||||
padding-top: 0.4em;
|
||||
padding-bottom: 0.4em;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
div.toolPanelLabel {
|
||||
margin-left: 0.7em !important;
|
||||
}
|
||||
div.toolSectionBody div.toolPanelLabel {
|
||||
margin-left: 1em !important;
|
||||
}
|
||||
|
||||
div.toolTitle, div.toolTitleNoSection {
|
||||
margin-left: 0em !important;
|
||||
padding-left: 1em !important;
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
|
||||
a {
|
||||
font-weight: normal;
|
||||
padding-top: 0.4em;
|
||||
padding-bottom: 0.4em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: @gray-lighter;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background: @brand-primary !important;
|
||||
border: 1px solid black !important;
|
||||
color: contrast(@brand-primary) !important;
|
||||
}
|
||||
|
||||
// Adjust older tool forms
|
||||
.toolFormTitle, .form .form-title {
|
||||
color: white;
|
||||
a {
|
||||
color: white !important;
|
||||
border: 1px solid white !important;
|
||||
}
|
||||
}
|
||||
// portlets
|
||||
.portlet-header {
|
||||
|
||||
.portlet-operations > div {
|
||||
color: white !important;
|
||||
background: transparent;
|
||||
}
|
||||
.portlet-title {
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
.ui-portlet-repeat {
|
||||
border-left-width: 1px !important;
|
||||
}
|
||||
.form-row .help, .toolParamHelp {
|
||||
color: @gray-dark !important;
|
||||
}
|
||||
|
||||
// History
|
||||
@state-default-text: @gray-dark;
|
||||
@state-default-bg: @gray-lighter;
|
||||
@state-default-border: @border-default-color;
|
||||
|
||||
@state-paused-border: @gray-lighter;
|
||||
@state-paused-bg: white;
|
||||
|
||||
@state-running-border: black;
|
||||
@state-running-bg: @gray-light;
|
||||
|
||||
@state-danger-border: black;
|
||||
@state-danger-bg: lighten(red, 5%);
|
||||
|
||||
@state-success-border: black;
|
||||
@state-success-bg: lighten(green, 15%);
|
||||
|
||||
.current-history-panel {
|
||||
.annotation-display {
|
||||
.annotation {
|
||||
border: 1px solid @gray-light !important;
|
||||
background: white !important;
|
||||
|
||||
textarea {
|
||||
border: none;
|
||||
}
|
||||
textarea:focus {
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.icon-btn, div.icon-btn, div.icon-btn > a {
|
||||
background: transparent;
|
||||
color: black;
|
||||
border: 0px;
|
||||
}
|
||||
a.icon-btn:hover {
|
||||
background: @gray-light;
|
||||
}
|
||||
|
||||
|
||||
ul.list-items {
|
||||
border: 0px;
|
||||
|
||||
.dataset {
|
||||
border: 0px;
|
||||
|
||||
div.summary {
|
||||
.help-text {
|
||||
color: black;
|
||||
}
|
||||
.job-error-text {
|
||||
background: @gray-darker;
|
||||
color: white;
|
||||
border: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.dataset-peek {
|
||||
background: @gray-darker !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.primary-actions, .left, .right {
|
||||
a.icon-btn, div.icon-btn, div.icon-btn > a {
|
||||
background: transparent;
|
||||
color: white;
|
||||
border: 0px;
|
||||
}
|
||||
a.icon-btn:hover {
|
||||
background: @gray-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.warnings {
|
||||
div {
|
||||
border: 1px solid black;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.dataset.state-running {
|
||||
.title-bar {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
.dataset.state-paused, .dataset.state-new, .dataset.state-queued {
|
||||
.title-bar {
|
||||
color: black;
|
||||
}
|
||||
.primary-actions, .left, .right {
|
||||
a.icon-btn, div.icon-btn, div.icon-btn > a {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.current-history-panel .list-item.history-content.current-content {
|
||||
border-left: 5px solid @gray-darker !important;
|
||||
}
|
||||
|
||||
// Modals
|
||||
//
|
||||
div.modal {
|
||||
div.modal-footer {
|
||||
button {
|
||||
border: 1px solid black;
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select2
|
||||
|
||||
.select2-container {
|
||||
box-shadow: none;
|
||||
|
||||
ul.select2-choices {
|
||||
border: 1px solid @gray-dark;
|
||||
box-shadow: none;
|
||||
|
||||
li.select2-search-choice {
|
||||
background: white;
|
||||
color: black;
|
||||
border: 1px solid black;
|
||||
}
|
||||
}
|
||||
}
|
||||
// pages
|
||||
.unified-panel-header {
|
||||
.panel-header-text {
|
||||
color: black !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Library
|
||||
.library_style_container tr:hover td {
|
||||
background-color: @gray-lighter !important;
|
||||
}
|
||||
|
||||
.library_style_container tr.dark td {
|
||||
background-color: @gray-light !important;
|
||||
border-bottom-color: @gray-light !important;
|
||||
}
|
||||
|
||||
// Pagination
|
||||
.pagination > .active > a {
|
||||
background-color: @brand-primary !important;
|
||||
}
|
||||
|
||||
.pagination a {
|
||||
padding-left: 0.8em !important;
|
||||
padding-right: 0.8em !important;
|
||||
}
|
||||
@@ -20,7 +20,6 @@ module.exports = function( grunt ){
|
||||
'bib2json': [ 'Parser.js', 'bibtex.js' ],
|
||||
|
||||
'farbtastic': [ 'src/farbtastic.js', 'farbtastic.js' ],
|
||||
'jQTouch': [ 'src/reference/jqtouch.js', 'jquery/jqtouch.js' ],
|
||||
'bootstrap-tour': [ 'build/js/bootstrap-tour.js', 'bootstrap-tour.js' ],
|
||||
'jquery.complexify': [ 'jquery.complexify.js', 'jquery.complexify.js' ],
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ module.exports = function( grunt ){
|
||||
'base',
|
||||
'autocomplete_tagging',
|
||||
'embed_item',
|
||||
'iphone',
|
||||
'library',
|
||||
'trackster',
|
||||
'circster',
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<datatype extension="bowtie_base_index" type="galaxy.datatypes.ngsindex:BowtieBaseIndex" mimetype="text/html" display_in_upload="false"/>
|
||||
<datatype extension="csfasta" type="galaxy.datatypes.sequence:csFasta" display_in_upload="true"/>
|
||||
<datatype extension="data" type="galaxy.datatypes.data:Data" mimetype="application/octet-stream" max_optional_metadata_filesize="1048576" />
|
||||
<datatype extension="d3_hierarchy" type="galaxy.datatypes.text:Json" mimetype="application/json" subclass="true" display_in_upload="false"/>
|
||||
<datatype extension="d3_hierarchy" type="galaxy.datatypes.text:Json" mimetype="application/json" subclass="true" display_in_upload="true"/>
|
||||
<datatype extension="data_manager_json" type="galaxy.datatypes.text:Json" mimetype="application/json" subclass="true" display_in_upload="false"/>
|
||||
<datatype extension="dbn" type="galaxy.datatypes.sequence:DotBracket" display_in_upload="true" description="Dot-Bracket format is a text-based format for storing both an RNA sequence and its corresponding 2D structure." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Dbn"/>
|
||||
<datatype extension="fai" type="galaxy.datatypes.tabular:Tabular" display_in_upload="true" subclass="true" description="A Fasta Index File is a text file consisting of lines each with five TAB-delimited columns : Name, Length, offset, linebases, Linewidth" description_url="http://www.htslib.org/doc/faidx.html" />
|
||||
@@ -144,6 +144,7 @@
|
||||
</datatype>
|
||||
<datatype extension="toolshed.gz" type="galaxy.datatypes.binary:Binary" mimetype="multipart/x-gzip" subclass="true" />
|
||||
<datatype extension="h5" type="galaxy.datatypes.binary:H5" mimetype="application/octet-stream" display_in_upload="true"/>
|
||||
<datatype extension="mz5" type="galaxy.datatypes.binary:H5" subclass="true" mimetype="application/octet-stream" display_in_upload="true"/>
|
||||
<datatype extension="html" type="galaxy.datatypes.text:Html" mimetype="text/html"/>
|
||||
<datatype extension="interval" type="galaxy.datatypes.interval:Interval" display_in_upload="true" description="File must start with definition line in the following format (columns may be in any order)." >
|
||||
<converter file="interval_to_bed_converter.xml" target_datatype="bed"/>
|
||||
@@ -311,10 +312,12 @@
|
||||
<display file="iobio/vcf.xml" />
|
||||
</datatype>
|
||||
<datatype extension="bcf" type="galaxy.datatypes.binary:Bcf" mimetype="application/octet-stream" display_in_upload="true">
|
||||
<converter file="bcf_to_bcf_bgzip_converter.xml" target_datatype="bcf_bgzip"/>
|
||||
<converter file="bcf_to_bcf_uncompressed_converter.xml" target_datatype="bcf_uncompressed"/>
|
||||
</datatype>
|
||||
<datatype extension="bcf_bgzip" type="galaxy.datatypes.binary:Binary" mimetype="application/octet-stream" subclass="true">
|
||||
<converter file="bcf_bgzip_to_bcf_converter.xml" target_datatype="bcf"/>
|
||||
<!-- bcf_bgzip is just an alias for bcf for backward-compatibility -->
|
||||
<datatype extension="bcf_bgzip" type="galaxy.datatypes.binary:Bcf" subclass="true" />
|
||||
<datatype extension="bcf_uncompressed" type="galaxy.datatypes.binary:BcfUncompressed" mimetype="application/octet-stream">
|
||||
<converter file="bcf_uncompressed_to_bcf_converter.xml" target_datatype="bcf"/>
|
||||
</datatype>
|
||||
<datatype extension="velvet" type="galaxy.datatypes.assembly:Velvet" display_in_upload="false"/>
|
||||
<datatype extension="wig" type="galaxy.datatypes.interval:Wiggle" display_in_upload="true" description="The wiggle format is line-oriented. Wiggle data is preceded by a track definition line, which adds a number of options for controlling the default display of this track." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Wig">
|
||||
@@ -326,7 +329,7 @@
|
||||
<datatype extension="interval_index" type="galaxy.datatypes.binary:Binary" subclass="true" />
|
||||
<datatype extension="tabix" type="galaxy.datatypes.binary:Binary" subclass="true" />
|
||||
<datatype extension="bgzip" type="galaxy.datatypes.binary:Binary" subclass="true" />
|
||||
<datatype extension="vcf_bgzip" type="galaxy.datatypes.tabular:VcfGz" type_extension="bgzip" subclass="true" display_in_upload="true">
|
||||
<datatype extension="vcf_bgzip" type="galaxy.datatypes.tabular:VcfGz" display_in_upload="true">
|
||||
<display file="igv/vcf.xml" />
|
||||
<converter file="vcf_bgzip_to_tabix_converter.xml" target_datatype="tabix"/>
|
||||
</datatype>
|
||||
|
||||
@@ -674,19 +674,32 @@ class CRAM(Binary):
|
||||
Binary.register_sniffable_binary_format('cram', 'cram', CRAM)
|
||||
|
||||
|
||||
class Bcf(Binary):
|
||||
"""Class describing a BCF file"""
|
||||
class BaseBcf(Binary):
|
||||
edam_format = "format_3020"
|
||||
edam_data = "data_3498"
|
||||
file_ext = "bcf"
|
||||
|
||||
|
||||
class Bcf(BaseBcf):
|
||||
"""
|
||||
Class describing a (BGZF-compressed) BCF file
|
||||
|
||||
>>> from galaxy.datatypes.sniff import get_test_fname
|
||||
>>> fname = get_test_fname('1.bcf')
|
||||
>>> Bcf().sniff(fname)
|
||||
True
|
||||
>>> fname = get_test_fname('1.bcf_uncompressed')
|
||||
>>> Bcf().sniff(fname)
|
||||
False
|
||||
"""
|
||||
|
||||
MetadataElement(name="bcf_index", desc="BCF Index File", param=metadata.FileParameter, file_ext="csi", readonly=True, no_value=None, visible=False, optional=True)
|
||||
|
||||
def sniff(self, filename):
|
||||
# BCF is compressed in the BGZF format, and must not be uncompressed in Galaxy.
|
||||
# The first 3 bytes of any bcf file is 'BCF', and the file is binary.
|
||||
try:
|
||||
header = gzip.open(filename).read(3)
|
||||
# The first 3 bytes of any BCF file are 'BCF', and the file is binary.
|
||||
if header == b'BCF':
|
||||
return True
|
||||
return False
|
||||
@@ -725,6 +738,34 @@ class Bcf(Binary):
|
||||
Binary.register_sniffable_binary_format("bcf", "bcf", Bcf)
|
||||
|
||||
|
||||
class BcfUncompressed(Bcf):
|
||||
"""
|
||||
Class describing an uncompressed BCF file
|
||||
|
||||
>>> from galaxy.datatypes.sniff import get_test_fname
|
||||
>>> fname = get_test_fname( '1.bcf_uncompressed' )
|
||||
>>> BcfUncompressed().sniff( fname )
|
||||
True
|
||||
>>> fname = get_test_fname( '1.bcf' )
|
||||
>>> BcfUncompressed().sniff( fname )
|
||||
False
|
||||
"""
|
||||
file_ext = "bcf_uncompressed"
|
||||
|
||||
def sniff(self, filename):
|
||||
try:
|
||||
header = open(filename).read(3)
|
||||
# The first 3 bytes of any BCF file are 'BCF', and the file is binary.
|
||||
if header == b'BCF':
|
||||
return True
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
Binary.register_sniffable_binary_format("bcf_uncompressed", "bcf_uncompressed", BcfUncompressed)
|
||||
|
||||
|
||||
class H5(Binary):
|
||||
"""
|
||||
Class describing an HDF5 file
|
||||
@@ -890,7 +931,7 @@ class BigBed(BigWig):
|
||||
Binary.register_sniffable_binary_format("bigbed", "bigbed", BigBed)
|
||||
|
||||
|
||||
class TwoBit (Binary):
|
||||
class TwoBit(Binary):
|
||||
"""Class describing a TwoBit format nucleotide file"""
|
||||
edam_format = "format_3009"
|
||||
edam_data = "data_0848"
|
||||
@@ -926,7 +967,7 @@ Binary.register_sniffable_binary_format("twobit", "twobit", TwoBit)
|
||||
|
||||
|
||||
@dataproviders.decorators.has_dataproviders
|
||||
class SQlite (Binary):
|
||||
class SQlite(Binary):
|
||||
"""Class describing a Sqlite database """
|
||||
MetadataElement(name="tables", default=[], param=ListParameter, desc="Database Tables", readonly=True, visible=True, no_value=[])
|
||||
MetadataElement(name="table_columns", default={}, param=DictParameter, desc="Database Table Columns", readonly=True, visible=True, no_value={})
|
||||
@@ -1447,7 +1488,7 @@ Binary.register_sniffable_binary_format("oxli.graphlabels", "oxligl",
|
||||
OxliGraphLabels)
|
||||
|
||||
|
||||
class SearchGuiArchive (CompressedArchive):
|
||||
class SearchGuiArchive(CompressedArchive):
|
||||
"""Class describing a SearchGUI archive """
|
||||
MetadataElement(name="searchgui_version", default='1.28.0', param=MetadataParameter, desc="SearchGui Version",
|
||||
readonly=True, visible=True, no_value=None)
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Uses bcftools to extract a bcf from a bcf.gz
|
||||
|
||||
usage: %prog in_file out_file
|
||||
"""
|
||||
import optparse
|
||||
import subprocess
|
||||
|
||||
|
||||
def main():
|
||||
# Read options, args.
|
||||
parser = optparse.OptionParser()
|
||||
(options, args) = parser.parse_args()
|
||||
input_fname, output_fname = args
|
||||
|
||||
subprocess.call(["bcftools", "view", input_fname, "-o", output_fname, "-O", "u"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,12 +0,0 @@
|
||||
<tool id="CONVERTER_bcf_bgzip_to_bcf" name="Convert BCF_BGZIP to BCF" version="0.0.1" hidden="false">
|
||||
<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
|
||||
<command>python '$__tool_directory__/bcf_bgzip_to_bcf_converter.py' '$input1' '$output1'</command>
|
||||
<inputs>
|
||||
<param format="bcf_bgzip" name="input1" type="data" label="Choose bcf_bgzip file"/>
|
||||
</inputs>
|
||||
<outputs>
|
||||
<data format="bcf" name="output1"/>
|
||||
</outputs>
|
||||
<help>
|
||||
</help>
|
||||
</tool>
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Uses bcftools to compress a bcf into a bcf.gz
|
||||
|
||||
usage: %prog in_file out_file
|
||||
"""
|
||||
import optparse
|
||||
import subprocess
|
||||
|
||||
|
||||
def main():
|
||||
# Read options, args.
|
||||
parser = optparse.OptionParser()
|
||||
(options, args) = parser.parse_args()
|
||||
input_fname, output_fname = args
|
||||
|
||||
subprocess.call(["bcftools", "view", input_fname, "-o", output_fname, "-O", "b"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,12 +0,0 @@
|
||||
<tool id="CONVERTER_bcf_to_bcf_bgzip" name="Convert BCF to BCF_BGZIP" version="0.0.1" hidden="false">
|
||||
<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
|
||||
<command>python '$__tool_directory__/bcf_to_bcf_bgzip_converter.py' '$input1' '$output1'</command>
|
||||
<inputs>
|
||||
<param format="bcf" name="input1" type="data" label="Choose bcf file"/>
|
||||
</inputs>
|
||||
<outputs>
|
||||
<data format="bcf_bgzip" name="output1"/>
|
||||
</outputs>
|
||||
<help>
|
||||
</help>
|
||||
</tool>
|
||||
@@ -0,0 +1,17 @@
|
||||
<tool id="CONVERTER_bcf_to_bcf_uncompressed" name="Convert BCF to uncompressed BCF" version="0.0.1" hidden="false">
|
||||
<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
|
||||
<requirements>
|
||||
<requirement type="package" version="1.5">bcftools</requirement>
|
||||
</requirements>
|
||||
<command detect_errors="exit_code"><![CDATA[
|
||||
bcftools view -o '$output1' -O u '$input1'
|
||||
]]></command>
|
||||
<inputs>
|
||||
<param name="input1" type="data" format="bcf" label="Input BCF dataset" />
|
||||
</inputs>
|
||||
<outputs>
|
||||
<data name="output1" format="bcf_uncompressed" />
|
||||
</outputs>
|
||||
<help>
|
||||
</help>
|
||||
</tool>
|
||||
@@ -0,0 +1,17 @@
|
||||
<tool id="CONVERTER_bcf_uncompressed_to_bcf" name="Convert uncompressed BCF to BCF" version="0.0.1" hidden="false">
|
||||
<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
|
||||
<requirements>
|
||||
<requirement type="package" version="1.5">bcftools</requirement>
|
||||
</requirements>
|
||||
<command detect_errors="exit_code"><![CDATA[
|
||||
bcftools view -o '$output1' -O b '$input1'
|
||||
]]></command>
|
||||
<inputs>
|
||||
<param name="input1" type="data" format="bcf_uncompressed" label="Input uncompressed BCF dataset" />
|
||||
</inputs>
|
||||
<outputs>
|
||||
<data name="output1" format="bcf" />
|
||||
</outputs>
|
||||
<help>
|
||||
</help>
|
||||
</tool>
|
||||
@@ -372,7 +372,7 @@ class Data(object):
|
||||
tmp_file_name = tmp_fh.name
|
||||
dir_items = sorted(os.listdir(file_path))
|
||||
base_path, item_name = os.path.split(file_path)
|
||||
tmp_fh.write('<html><head><h3>Directory %s contents: %d items</h3></head>\n' % (item_name, len(dir_items)))
|
||||
tmp_fh.write('<html><head><h3>Directory %s contents: %d items</h3></head>\n' % (escape(item_name), len(dir_items)))
|
||||
tmp_fh.write('<body><p/><table cellpadding="2">\n')
|
||||
for index, fname in enumerate(dir_items):
|
||||
if index % 2 == 0:
|
||||
@@ -386,10 +386,10 @@ class Data(object):
|
||||
# href = url_for(controller='dataset', action='display',
|
||||
# dataset_id=trans.security.encode_id(data.dataset.id),
|
||||
# preview=preview, filename=fname, to_ext=to_ext)
|
||||
tmp_fh.write('<tr bgcolor="%s"><td>%s</td></tr>\n' % (bgcolor, fname))
|
||||
tmp_fh.write('<tr bgcolor="%s"><td>%s</td></tr>\n' % (bgcolor, escape(fname)))
|
||||
tmp_fh.write('</table></body></html>\n')
|
||||
tmp_fh.close()
|
||||
return open(tmp_file_name)
|
||||
return self._yield_user_file_content(trans, data, tmp_file_name)
|
||||
mime = mimetypes.guess_type(file_path)[0]
|
||||
if not mime:
|
||||
try:
|
||||
@@ -397,7 +397,7 @@ class Data(object):
|
||||
except:
|
||||
mime = "text/plain"
|
||||
self._clean_and_set_mime_type(trans, mime)
|
||||
return open(file_path)
|
||||
return self._yield_user_file_content(trans, data, file_path)
|
||||
else:
|
||||
return paste.httpexceptions.HTTPNotFound("Could not find '%s' on the extra files path %s." % (filename, file_path))
|
||||
self._clean_and_set_mime_type(trans, data.get_mime())
|
||||
@@ -420,23 +420,29 @@ class Data(object):
|
||||
max_peek_size = 10000000 # 10 MB for html
|
||||
preview = util.string_as_bool(preview)
|
||||
if not preview or isinstance(data.datatype, datatypes.images.Image) or os.stat(data.file_name).st_size < max_peek_size:
|
||||
if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html":
|
||||
# Sanitize anytime we respond with plain text/html content.
|
||||
# Check to see if this dataset's parent job is whitelisted
|
||||
# We cannot currently trust imported datasets for rendering.
|
||||
if not data.creating_job.imported and data.creating_job.tool_id in trans.app.config.sanitize_whitelist:
|
||||
return open(data.file_name).read()
|
||||
# This is returning to the browser, it needs to be encoded.
|
||||
# TODO Ideally this happens a layer higher, but this is a bad
|
||||
# issue affecting many tools
|
||||
return sanitize_html(open(data.file_name).read()).encode('utf-8')
|
||||
return open(data.file_name)
|
||||
return self._yield_user_file_content(trans, data, data.file_name)
|
||||
else:
|
||||
trans.response.set_content_type("text/html")
|
||||
return trans.stream_template_mako("/dataset/large_file.mako",
|
||||
truncated_data=open(data.file_name).read(max_peek_size),
|
||||
data=data)
|
||||
|
||||
def _yield_user_file_content(self, trans, from_dataset, filename):
|
||||
"""This method is responsible for sanitizing the HTML if needed."""
|
||||
if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html":
|
||||
# Sanitize anytime we respond with plain text/html content.
|
||||
# Check to see if this dataset's parent job is whitelisted
|
||||
# We cannot currently trust imported datasets for rendering.
|
||||
if not from_dataset.creating_job.imported and from_dataset.creating_job.tool_id in trans.app.config.sanitize_whitelist:
|
||||
return open(filename)
|
||||
|
||||
# This is returning to the browser, it needs to be encoded.
|
||||
# TODO Ideally this happens a layer higher, but this is a bad
|
||||
# issue affecting many tools
|
||||
return sanitize_html(open(filename).read()).encode('utf-8')
|
||||
|
||||
return open(filename)
|
||||
|
||||
def _download_filename(self, dataset, to_ext, hdca=None, element_identifier=None):
|
||||
def escape(raw_identifier):
|
||||
return ''.join(c in FILENAME_VALID_CHARS and c or '_' for c in raw_identifier)[0:150]
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
<tool id="__SET_METADATA__" name="Set External Metadata" version="1.0.1" tool_type="set_metadata">
|
||||
<type class="SetMetadataTool" module="galaxy.tools"/>
|
||||
<requirements>
|
||||
<requirement type="package">samtools</requirement>
|
||||
</requirements>
|
||||
<action module="galaxy.tools.actions.metadata" class="SetMetadataToolAction"/>
|
||||
<command>"\${GALAXY_PYTHON:-python}" "${set_metadata}" ${__SET_EXTERNAL_METADATA_COMMAND_LINE__}</command>
|
||||
<inputs>
|
||||
<param format="data" name="input1" type="data" label="File to set metadata on."/>
|
||||
<param name="__ORIGINAL_DATASET_STATE__" type="hidden" value=""/>
|
||||
<param name="__SET_EXTERNAL_METADATA_COMMAND_LINE__" type="hidden" value="">
|
||||
<sanitizer sanitize="False"/>
|
||||
</param>
|
||||
</inputs>
|
||||
<configfiles>
|
||||
<configfile name="set_metadata">from galaxy_ext.metadata.set_metadata import set_metadata; set_metadata()</configfile>
|
||||
</configfiles>
|
||||
<type class="SetMetadataTool" module="galaxy.tools"/>
|
||||
<requirements>
|
||||
<requirement type="package">samtools</requirement>
|
||||
<requirement type="package" version="1.5">bcftools</requirement>
|
||||
</requirements>
|
||||
<action module="galaxy.tools.actions.metadata" class="SetMetadataToolAction"/>
|
||||
<command>"\${GALAXY_PYTHON:-python}" "${set_metadata}" ${__SET_EXTERNAL_METADATA_COMMAND_LINE__}</command>
|
||||
<configfiles>
|
||||
<configfile name="set_metadata">from galaxy_ext.metadata.set_metadata import set_metadata; set_metadata()</configfile>
|
||||
</configfiles>
|
||||
<inputs>
|
||||
<param name="input1" type="data" format="data" label="File to set metadata on"/>
|
||||
<param name="__ORIGINAL_DATASET_STATE__" type="hidden" value=""/>
|
||||
<param name="__SET_EXTERNAL_METADATA_COMMAND_LINE__" type="hidden" value="">
|
||||
<sanitizer sanitize="False"/>
|
||||
</param>
|
||||
</inputs>
|
||||
</tool>
|
||||
|
||||
@@ -679,7 +679,6 @@ class BaseVcf(Tabular):
|
||||
track_type = "VariantTrack"
|
||||
data_sources = {"data": "tabix", "index": "bigwig"}
|
||||
|
||||
file_ext = 'vcf'
|
||||
column_names = ['Chrom', 'Pos', 'ID', 'Ref', 'Alt', 'Qual', 'Filter', 'Info', 'Format', 'data']
|
||||
|
||||
MetadataElement(name="columns", default=10, desc="Number of columns", readonly=True, visible=False)
|
||||
@@ -735,12 +734,12 @@ class BaseVcf(Tabular):
|
||||
return self.genomic_region_dataprovider(dataset, **settings)
|
||||
|
||||
|
||||
class Vcf (BaseVcf):
|
||||
extension = 'vcf'
|
||||
class Vcf(BaseVcf):
|
||||
file_ext = 'vcf'
|
||||
|
||||
|
||||
class VcfGz(BaseVcf, binary.Binary):
|
||||
extension = 'vcf.gz'
|
||||
file_ext = 'vcf_bgzip'
|
||||
compressed = True
|
||||
|
||||
MetadataElement(name="tabix_index", desc="Vcf Index File", param=metadata.FileParameter, file_ext="tbi", readonly=True, no_value=None, visible=False, optional=True)
|
||||
|
||||
@@ -433,6 +433,8 @@ class Response(object):
|
||||
"""
|
||||
Send an HTTP redirect response to (target `url`)
|
||||
"""
|
||||
if "\n" in url or "\r" in url:
|
||||
raise httpexceptions.HTTPInternalServerError("Invalid redirect URL encountered.")
|
||||
raise httpexceptions.HTTPFound(url.encode('utf-8'), headers=self.wsgi_headeritems())
|
||||
|
||||
def wsgi_headeritems(self):
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
from galaxy import web
|
||||
from galaxy.web.base.controller import BaseUIController
|
||||
|
||||
|
||||
class Mobile(BaseUIController):
|
||||
|
||||
@web.expose
|
||||
def index(self, trans, **kwargs):
|
||||
return trans.response.send_redirect(web.url_for(controller='root', action='index'))
|
||||
# return trans.fill_template( "mobile/index.mako" )
|
||||
|
||||
@web.expose
|
||||
def history_list(self, trans):
|
||||
return trans.response.send_redirect(web.url_for(controller='root', action='index'))
|
||||
# return trans.fill_template( "mobile/history/list.mako" )
|
||||
|
||||
@web.expose
|
||||
def history_detail(self, trans, id):
|
||||
return trans.response.send_redirect(web.url_for(controller='root', action='index'))
|
||||
# history = trans.sa_session.query( trans.app.model.History ).get( id )
|
||||
# assert history.user == trans.user
|
||||
# return trans.fill_template( "mobile/history/detail.mako", history=history )
|
||||
|
||||
@web.expose
|
||||
def dataset_detail(self, trans, id):
|
||||
return trans.response.send_redirect(web.url_for(controller='root', action='index'))
|
||||
# dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
|
||||
# assert dataset.history.user == trans.user
|
||||
# return trans.fill_template( "mobile/dataset/detail.mako", dataset=dataset )
|
||||
|
||||
@web.expose
|
||||
def dataset_peek(self, trans, id):
|
||||
return trans.response.send_redirect(web.url_for(controller='root', action='index'))
|
||||
# dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( id )
|
||||
# assert dataset.history.user == trans.user
|
||||
# return trans.fill_template( "mobile/dataset/peek.mako", dataset=dataset )
|
||||
|
||||
@web.expose
|
||||
def settings(self, trans, email=None, password=None):
|
||||
return trans.response.send_redirect(web.url_for(controller='root', action='index'))
|
||||
# message = None
|
||||
# if email is not None and password is not None:
|
||||
# if email == "":
|
||||
# self.__logout( trans )
|
||||
# message = "Logged out"
|
||||
# else:
|
||||
# error = self.__login( trans, email, password )
|
||||
# message = error or "Login changed"
|
||||
# return trans.fill_template( "mobile/settings.mako", message=message )
|
||||
|
||||
def __logout(self, trans):
|
||||
return trans.response.send_redirect(web.url_for(controller='root', action='index'))
|
||||
# trans.log_event( "User logged out" )
|
||||
# trans.handle_user_logout()
|
||||
|
||||
def __login(self, trans, login="", password=""):
|
||||
return trans.response.send_redirect(web.url_for(controller='root', action='index'))
|
||||
# error = password_error = None
|
||||
# user = trans.sa_session.query( model.User ).filter(or_(
|
||||
# email == login,
|
||||
# username == login
|
||||
# )).first()
|
||||
# if not user:
|
||||
# autoreg = trans.app.auth_manager.check_auto_registration(trans, login, password)
|
||||
# if autoreg[0]:
|
||||
# kwd = {}
|
||||
# kwd['email'] = autoreg[1]
|
||||
# kwd['username'] = autoreg[2]
|
||||
# params = util.Params( kwd )
|
||||
# message = " ".join( [ validate_email( trans, kwd['email'] ),
|
||||
# validate_publicname( trans, kwd['username'] ) ] ).rstrip()
|
||||
# if not message:
|
||||
# message, status, user, success = self.__register( trans, 'user', False, **kwd )
|
||||
# if success:
|
||||
# # The handle_user_login() method has a call to the history_set_default_permissions() method
|
||||
# # (needed when logging in with a history), user needs to have default permissions set before logging in
|
||||
# trans.handle_user_login( user )
|
||||
# trans.log_event( "User (auto) created a new account" )
|
||||
# trans.log_event( "User logged in" )
|
||||
# else:
|
||||
# message = "Auto-registration failed, contact your local Galaxy administrator. %s" % message
|
||||
# else:
|
||||
# message = "Auto-registration failed, contact your local Galaxy administrator. %s" % message
|
||||
# else:
|
||||
# message = "No such user (please note that login is case sensitive)"
|
||||
# elif user.deleted:
|
||||
# error = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
|
||||
# elif user.external:
|
||||
# error = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
|
||||
# elif not trans.app.auth_manager.check_password(user, password):
|
||||
# error = "Invalid password"
|
||||
# else:
|
||||
# trans.handle_user_login( user )
|
||||
# trans.log_event( "User logged in" )
|
||||
# return error
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Universe configuration builder."""
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from six.moves import configparser
|
||||
@@ -67,6 +68,17 @@ class Configuration(object):
|
||||
if not os.path.isdir(path):
|
||||
raise ConfigurationError("Directory does not exist: %s" % path)
|
||||
|
||||
@property
|
||||
def sentry_dsn_public(self):
|
||||
"""
|
||||
Sentry URL with private key removed for use in client side scripts,
|
||||
sentry server will need to be configured to accept events
|
||||
"""
|
||||
if self.sentry_dsn:
|
||||
return re.sub(r"^([^:/?#]+:)?//(\w+):(\w+)", r"\1//\2", self.sentry_dsn)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def get_database_engine_options(kwargs):
|
||||
"""
|
||||
|
||||
@@ -1087,17 +1087,19 @@ class WorkflowModuleInjector(object):
|
||||
# Populate module.
|
||||
module = step.module = module_factory.from_workflow_step(self.trans, step)
|
||||
|
||||
# Fix any missing parameters
|
||||
step.upgrade_messages = module.check_and_update_state()
|
||||
|
||||
# Any connected input needs to have value DummyDataset (these
|
||||
# are not persisted so we need to do it every time)
|
||||
module.add_dummy_datasets(connections=step.input_connections, steps=steps)
|
||||
state, step_errors = module.compute_runtime_state(self.trans, step_args)
|
||||
step.state = state
|
||||
|
||||
# Fix any missing parameters
|
||||
step.upgrade_messages = module.check_and_update_state()
|
||||
|
||||
# Populate subworkflow components
|
||||
if step.type == "subworkflow":
|
||||
subworkflow = step.subworkflow
|
||||
populate_module_and_state(self.trans, subworkflow, param_map={}, )
|
||||
populate_module_and_state(self.trans, subworkflow, param_map={})
|
||||
return step_errors
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 816 B |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 162 B |
|
Before Width: | Height: | Size: 264 B |
|
Before Width: | Height: | Size: 517 B |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 362 B |
|
Before Width: | Height: | Size: 259 B |
|
Before Width: | Height: | Size: 308 B |
|
Before Width: | Height: | Size: 943 B |
|
Before Width: | Height: | Size: 271 B |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 117 B |
|
Before Width: | Height: | Size: 159 B |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 163 B |
|
Before Width: | Height: | Size: 531 B |
|
Before Width: | Height: | Size: 269 B |
|
Before Width: | Height: | Size: 171 B |
|
Before Width: | Height: | Size: 978 B |
@@ -1,436 +0,0 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Helvetica;
|
||||
overflow-x: hidden;
|
||||
-webkit-user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
*, a {
|
||||
/*-webkit-tap-highlight-color: rbga(23,126,191,.5) !important;*/
|
||||
-webkit-tap-highlight-color:rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.edgetoedge a, .panel a {
|
||||
/*-webkit-tap-highlight-color: rbga(23,126,191,.5) !important;*/
|
||||
-webkit-tap-highlight-color:rgba(23, 126, 191, .4);
|
||||
}
|
||||
|
||||
body > * {
|
||||
display: none;
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
min-height: 480px;
|
||||
-webkit-transform: translate(0px,0px);
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
body[orient="landscape"] > * {
|
||||
min-height: 320px;
|
||||
}
|
||||
|
||||
body > *[selected="true"], body > *[selected="selected"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.edgetoedge a[selected=true], .edgetoedge a:active, .panel a[selected=true], .panel a:active {
|
||||
background-color: rgb(170,170,238) !important;
|
||||
}
|
||||
|
||||
a[selected="progress"] {
|
||||
background-color: rgb(170,170,238) !important;
|
||||
background-image: url(img/loading.gif) !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: right center !important;
|
||||
}
|
||||
|
||||
/* @group Toolbar */
|
||||
.toolbar {
|
||||
-webkit-box-sizing: border-box;
|
||||
padding: 10px;
|
||||
/* height: 60px; */
|
||||
/* padding-top: 28px; */
|
||||
/* background: #000 url(img/toolbar.gif) bottom left repeat-x; */
|
||||
height: 42px;
|
||||
background: rgb(44,49,67);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.toolbar > h1 {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
left: 50%;
|
||||
margin: 1px 0 0 -75px;
|
||||
height: 45px;
|
||||
font-size: 20px;
|
||||
width: 150px;
|
||||
font-weight: bold;
|
||||
/*text-shadow: rgba(0, 0, 0, .75) -1px -1px 0;*/
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: #f6f6f6;
|
||||
}
|
||||
|
||||
body[orient="landscape"] .toolbar > h1 {
|
||||
margin-left: -125px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
.button {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
bottom: 5px;
|
||||
right: 6px;
|
||||
margin: 0;
|
||||
border-width: 0 5px;
|
||||
padding: 0 3px;
|
||||
width: auto;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
font-family: inherit;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
text-shadow: rgba(0, 0, 0, 0.6) 0px -1px 0;
|
||||
text-overflow: ellipsis;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background: none;
|
||||
-webkit-border-image: url(img/button.png) 0 5 0 5;
|
||||
}
|
||||
|
||||
.button:active {
|
||||
-webkit-border-image: url(img/button_clicked.png) 0 5 0 5;
|
||||
|
||||
}
|
||||
|
||||
.blueButton {
|
||||
-webkit-border-image: url(img/blueButton.png) 0 5 0 5;
|
||||
border-width: 0 5px;
|
||||
}
|
||||
|
||||
.leftButton {
|
||||
left: 6px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.toolbar .back {
|
||||
left: 6px;
|
||||
right: auto;
|
||||
padding: 0;
|
||||
max-width: 55px;
|
||||
border-width: 0 8px 0 15px;
|
||||
-webkit-border-image: url(img/back_button.png) 0 8 0 15;
|
||||
}
|
||||
|
||||
.toolbar .back:active {
|
||||
-webkit-border-image: url(img/back_button_clicked.png) !important;
|
||||
}
|
||||
|
||||
.whiteButton,
|
||||
.grayButton {
|
||||
display: block;
|
||||
border-width: 0 12px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-decoration: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.whiteButton {
|
||||
-webkit-border-image: url(img/whiteButton.png) 0 12 0 12;
|
||||
text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
|
||||
}
|
||||
|
||||
.grayButton {
|
||||
-webkit-border-image: url(img/grayButton.png) 0 12 0 12;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
|
||||
/* @group Edge to edge */
|
||||
|
||||
.edgetoedge {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.edgetoedge > li {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid #E0E0E0;
|
||||
padding: 8px 0 8px 10px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
list-style: none;
|
||||
/* background: url(../img/bg_row.gif) 0 2px repeat-x; */
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.edgetoedge > li.group {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
margin-bottom: -2px;
|
||||
border-top: 1px solid #7d7d7d;
|
||||
border-bottom: 1px solid #999999;
|
||||
padding: 1px 10px;
|
||||
background: url(img/listGroup.png) repeat-x;
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
text-shadow: rgba(0, 0, 0, 0.4) 0 1px 0;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.edgetoedge > li.group:first-child, .inset > li.group:first-child {
|
||||
top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.edgetoedge a, .inset a {
|
||||
display: block;
|
||||
margin: -8px 0 -8px -10px;
|
||||
padding: 8px 32px 8px 10px;
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
/*
|
||||
background-image: url(img/bg_row.gif), url(img/chevron.png);
|
||||
background-repeat: repeat-x, no-repeat;
|
||||
background-position: 0 1px, right center;
|
||||
*/
|
||||
background-image: url(img/chevron.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
}
|
||||
/* @end */
|
||||
|
||||
a[target="_replace"] {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
padding-top: 25px;
|
||||
padding-bottom: 25px;
|
||||
font-size: 18px;
|
||||
color: cornflowerblue;
|
||||
background-color: #FFFFFF;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
body > .dialog {
|
||||
top: 0;
|
||||
width: 100%;
|
||||
min-height: 417px;
|
||||
z-index: 2;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
padding: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.dialog > fieldset {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border: none;
|
||||
border-top: 1px solid #6d84a2;
|
||||
padding: 10px 6px;
|
||||
background: url(img/toolbar.png) #7388a5 repeat-x;
|
||||
}
|
||||
|
||||
.dialog > fieldset > h1 {
|
||||
margin: 0 10px 0 10px;
|
||||
padding: 0;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dialog > fieldset > label {
|
||||
position: absolute;
|
||||
margin: 16px 0 0 6px;
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
input {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin: 8px 0 0 0;
|
||||
padding: 6px 6px 6px 44px;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
|
||||
.panel {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
background: #c8c8c8 url(img/pinstripes.png);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.pad {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.panel fieldset {
|
||||
position: relative;
|
||||
margin: 0 0 20px 0;
|
||||
padding: 0;
|
||||
background: #FFFFFF;
|
||||
-webkit-border-radius: 10px;
|
||||
border: 1px solid #999999;
|
||||
/* text-align: right; */
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.row {
|
||||
position: relative;
|
||||
min-height: 42px;
|
||||
border-bottom: 1px solid #999999;
|
||||
-webkit-border-radius: 0;
|
||||
/* text-align: right; */
|
||||
}
|
||||
|
||||
fieldset .row:last-child {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.row > input {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding: 12px 10px 0 110px;
|
||||
min-height: 42px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.row > span {
|
||||
display: block;
|
||||
text-align: left;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding: 12px 10px 10px 110px;
|
||||
min-height: 42px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.row > a {
|
||||
display: block;
|
||||
height: 42px;
|
||||
text-decoration: none;
|
||||
padding: 0 0 0 14px;
|
||||
line-height: 42px;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
background-image: url(img/chevron.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
}
|
||||
|
||||
.row > label {
|
||||
position: absolute;
|
||||
margin: 0 0 0 14px;
|
||||
line-height: 42px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.row > .toggle {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
width: 100px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
border: 1px solid #888888;
|
||||
-webkit-border-radius: 6px;
|
||||
background: #FFFFFF url(img/toggle.png) repeat-x;
|
||||
font-size: 19px;
|
||||
font-weight: bold;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.toggle[toggled="true"] {
|
||||
border: 1px solid #143fae;
|
||||
background: #194fdb url(img/toggleOn.png) repeat-x;
|
||||
}
|
||||
|
||||
.toggleOn {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
top: 0;
|
||||
color: #FFFFFF;
|
||||
text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
|
||||
}
|
||||
|
||||
.toggleOff {
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
right: 0;
|
||||
top: 0;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.toggle[toggled="true"] > .toggleOn {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.toggle[toggled="true"] > .toggleOff {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
width: 40px;
|
||||
height: 28px;
|
||||
border: 1px solid #888888;
|
||||
-webkit-border-radius: 6px;
|
||||
background: #ffffff url(img/thumb.png) repeat-x;
|
||||
}
|
||||
|
||||
.toggle[toggled="true"] > .thumb {
|
||||
left: auto;
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
.panel h2 {
|
||||
margin: 0 0 8px 14px;
|
||||
font-size: inherit;
|
||||
font-weight: bold;
|
||||
color: rgb(17, 20, 23, .5);
|
||||
text-shadow: rgba(255, 255, 255, 0.75) 1px 1px 0;
|
||||
}
|
||||
|
||||
.panel p a {
|
||||
color: #4195ca;
|
||||
}
|
||||
|
||||
#about {
|
||||
background: rgb(17, 20, 23);
|
||||
color: #ddd;
|
||||
text-shadow: rgba(255, 255, 255, 0.3) 0px -1px 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
@@ -102,58 +102,59 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="float: left; padding-left: 10px; font-size: 36px;">→</div>
|
||||
<div class="toolForm" style="float: right; width: 45%; padding: 0px;">
|
||||
<div class="toolFormTitle">Destination History:</div>
|
||||
<div class="toolFormBody">
|
||||
<div class="form-row" id="single-destination">
|
||||
<select id="single-dest-select" name="target_history_id">
|
||||
%for i, hist in enumerate(target_histories):
|
||||
<%
|
||||
encoded_id = trans.security.encode_id(hist.id)
|
||||
source_history_text = ""
|
||||
selected = ""
|
||||
if hist == source_history:
|
||||
source_history_text = " (source history)"
|
||||
if encoded_id == target_history_id:
|
||||
selected = " selected='selected'"
|
||||
%>
|
||||
<option value="${encoded_id}"${selected}>${i + 1}: ${h.truncate( util.unicodify( hist.name ), 30) | h}${source_history_text}</option>
|
||||
%endfor
|
||||
</select><br /><br />
|
||||
<a style="margin-left: 10px;" href="javascript:void(0);" id="select-multiple">Choose multiple histories</a>
|
||||
</div>
|
||||
<div id="multiple-destination" style="display: none;">
|
||||
%for i, hist in enumerate( target_histories ):
|
||||
<%
|
||||
cur_history_text = ""
|
||||
encoded_id = trans.security.encode_id(hist.id)
|
||||
if hist == source_history:
|
||||
cur_history_text = " <strong>(source history)</strong>"
|
||||
%>
|
||||
<div class="form-row">
|
||||
<input type="checkbox" name="target_history_ids" id="hist_${encoded_id}" value="${encoded_id}"/>
|
||||
<label for="hist_${encoded_id}" style="display: inline; font-weight:normal;">${i + 1}: ${ util.unicodify( hist.name ) | h }${cur_history_text}</label>
|
||||
</div>
|
||||
%endfor
|
||||
</div>
|
||||
%if trans.get_user():
|
||||
<%
|
||||
checked = ""
|
||||
if "create_new_history" in target_history_ids:
|
||||
checked = " checked='checked'"
|
||||
%>
|
||||
<hr />
|
||||
<div style="text-align: center; color: #888;">— OR —</div>
|
||||
<div class="form-row">
|
||||
<label for="new_history_name" style="display: inline; font-weight:normal;">New history named:</label>
|
||||
<input id="new_history_name" type="text" name="new_history_name" />
|
||||
<div style="float: right; width: 45%; padding: 0px;">
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">Destination History:</div>
|
||||
<div class="toolFormBody">
|
||||
<div class="form-row" id="single-destination">
|
||||
<select id="single-dest-select" name="target_history_id">
|
||||
%for i, hist in enumerate(target_histories):
|
||||
<%
|
||||
encoded_id = trans.security.encode_id(hist.id)
|
||||
source_history_text = ""
|
||||
selected = ""
|
||||
if hist == source_history:
|
||||
source_history_text = " (source history)"
|
||||
if encoded_id == target_history_id:
|
||||
selected = " selected='selected'"
|
||||
%>
|
||||
<option value="${encoded_id}"${selected}>${i + 1}: ${h.truncate( util.unicodify( hist.name ), 30) | h}${source_history_text}</option>
|
||||
%endfor
|
||||
</select><br /><br />
|
||||
<a style="margin-left: 10px;" href="javascript:void(0);" id="select-multiple">Choose multiple histories</a>
|
||||
</div>
|
||||
%endif
|
||||
<div id="multiple-destination" style="display: none;">
|
||||
%for i, hist in enumerate( target_histories ):
|
||||
<%
|
||||
cur_history_text = ""
|
||||
encoded_id = trans.security.encode_id(hist.id)
|
||||
if hist == source_history:
|
||||
cur_history_text = " <strong>(source history)</strong>"
|
||||
%>
|
||||
<div class="form-row">
|
||||
<input type="checkbox" name="target_history_ids" id="hist_${encoded_id}" value="${encoded_id}"/>
|
||||
<label for="hist_${encoded_id}" style="display: inline; font-weight:normal;">${i + 1}: ${ util.unicodify( hist.name ) | h }${cur_history_text}</label>
|
||||
</div>
|
||||
%endfor
|
||||
</div>
|
||||
%if trans.get_user():
|
||||
<%
|
||||
checked = ""
|
||||
if "create_new_history" in target_history_ids:
|
||||
checked = " checked='checked'"
|
||||
%>
|
||||
<hr />
|
||||
<div style="text-align: center; color: #888;">— OR —</div>
|
||||
<div class="form-row">
|
||||
<label for="new_history_name" style="display: inline; font-weight:normal;">New history named:</label>
|
||||
<input id="new_history_name" type="text" name="new_history_name" />
|
||||
</div>
|
||||
%endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row" style="text-align: center;">
|
||||
<input type="submit" class="primary-button" name="do_copy" value="Copy History Items"/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="form-row" style="text-align: center;">
|
||||
<input type="submit" class="primary-button" name="do_copy" value="Copy History Items"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<div id="dataset_${dataset.id}" title="Dataset" class="panel">
|
||||
<div class="toolbar">
|
||||
<h1>${dataset.display_name()}</h1>
|
||||
<a class="back button" href="#">Back</a>
|
||||
</div>
|
||||
|
||||
<div class="pad">
|
||||
<fieldset>
|
||||
<div class="row">
|
||||
<label>State</label> <span>${dataset.state}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Content</label> <span>${dataset.blurb}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Format</label> <span>${dataset.ext}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Info</label> <span>${dataset.display_info()}</span>
|
||||
</div>
|
||||
%if dataset.state == "ok":
|
||||
<div class="row">
|
||||
<a href="${h.url_for(controller='mobile', action='dataset_peek', id=dataset.id )}">Peek</a>
|
||||
</div>
|
||||
%endif
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
@@ -1,12 +0,0 @@
|
||||
<div id="dataset_peek_${dataset.id}" title="Dataset Peek" class="panel">
|
||||
<div class="toolbar">
|
||||
<h1>${dataset.display_name()}</h1>
|
||||
<a class="back button" href="#">Back</a>
|
||||
</div>
|
||||
|
||||
<div class="pad" style="overflow: auto;">
|
||||
<pre>
|
||||
${dataset.display_peek()}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,52 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>
|
||||
Galaxy
|
||||
%if app.config.brand:
|
||||
| ${app.config.brand}
|
||||
%endif
|
||||
${form.title}
|
||||
</title>
|
||||
<meta name="viewport" content="width=devicewidth; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
|
||||
<link rel="apple-touch-icon" href="${h.url_for('/static/iui/iui-logo-touch-icon.png')}" />
|
||||
<meta name="apple-touch-fullscreen" content="YES" />
|
||||
<style type="text/css" media="screen">@import "${h.url_for('/static/style/iphone.css')}";</style>
|
||||
## <script type="application/x-javascript" src="${h.url_for('/static/iui/iui.js')}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="toolbar">
|
||||
<h1 id="pageTitle">${form.title}</h1>
|
||||
<a id="backButton" class="button" href="#"></a>
|
||||
</div>
|
||||
|
||||
<form title="${form.title}" class="panel" selected="true" name="${form.name}" action="${form.action}" method="post" >
|
||||
<fieldset>
|
||||
%for input in form.inputs:
|
||||
<%
|
||||
cls = "row"
|
||||
if input.error:
|
||||
cls += " form-row-error"
|
||||
%>
|
||||
<div class="${cls}">
|
||||
%if input.use_label:
|
||||
<label>
|
||||
${input.label}:
|
||||
</label>
|
||||
%endif
|
||||
<input type="${input.type}" name="${input.name}" value="${input.value}" size="40">
|
||||
%if input.error:
|
||||
<div class="error">Error: ${input.error}</div>
|
||||
%endif
|
||||
</div>
|
||||
|
||||
%endfor
|
||||
</fieldset>
|
||||
<input class="whiteButton" type="submit" value="${form.submit_text}">
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,80 +0,0 @@
|
||||
<div id="history_detail_${history.id}">
|
||||
<div class="toolbar">
|
||||
<h1>${history.name}</h1>
|
||||
<a class="back button" href="#">Back</a>
|
||||
</div>
|
||||
<ul class="edgetoedge">
|
||||
|
||||
%for data in history.active_datasets:
|
||||
%if data.visible:
|
||||
|
||||
<%
|
||||
if data.state in ['no state','',None]:
|
||||
data_state = "queued"
|
||||
else:
|
||||
data_state = str( data.state )
|
||||
%>
|
||||
|
||||
<li id="historyItemContainer-${data.id}">
|
||||
|
||||
<div style="float: left; padding-right: 8px;">
|
||||
<div style='display: none;' id="progress-${data.id}">
|
||||
<img src="${h.url_for('/static/style/data_running.gif')}" border="0">
|
||||
</div>
|
||||
%if data_state == 'running':
|
||||
<div><img src="${h.url_for('/static/style/data_running.gif')}" border="0"></div>
|
||||
%elif data_state == 'upload':
|
||||
<div><img src="${h.url_for('/static/style/data_upload.gif')}" border="0"></div>
|
||||
%else:
|
||||
<div><img src="${h.url_for( "/static/style/data_%s.png" % data_state )}" border="0"></div>
|
||||
%endif
|
||||
</div>
|
||||
|
||||
<a href="${h.url_for(controller='mobile', action="dataset_detail", id=data.id )}">
|
||||
|
||||
<div>${data.hid}: ${data.display_name()}</div>
|
||||
|
||||
<div class="secondary">
|
||||
## Body for history items, extra info and actions, data "peek"
|
||||
<% current_user_roles = trans.get_current_user_roles() %>
|
||||
%if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ):
|
||||
<div>You do not have permission to view this dataset.</div>
|
||||
%elif data_state == "queued":
|
||||
<div>Job is waiting to run</div>
|
||||
%elif data_state == "running":
|
||||
<div>Job is currently running</div>
|
||||
%elif data_state == "error":
|
||||
<div>
|
||||
An error occurred running this job.
|
||||
</div>
|
||||
%elif data_state == "discarded":
|
||||
<div>
|
||||
The job creating this dataset was cancelled before completion.
|
||||
</div>
|
||||
%elif data_state == 'setting_metadata':
|
||||
<div>Metadata is being Auto-Detected.</div>
|
||||
%elif data_state == "empty":
|
||||
<div>No data: <i>${data.display_info()}</i></div>
|
||||
%elif data_state in [ "ok", "failed_metadata" ]:
|
||||
<div>
|
||||
%if data_state == "failed_metadata":
|
||||
Warning: setting metadata failed,
|
||||
%endif
|
||||
${data.blurb},
|
||||
format: <span class="${data.ext}">${data.ext}</span>,
|
||||
database: <span class="${data.dbkey}">${data.dbkey}</span>
|
||||
</div>
|
||||
%else:
|
||||
<div>Error: unknown dataset state "${data_state}".</div>
|
||||
%endif
|
||||
</div>
|
||||
|
||||
</a>
|
||||
|
||||
</li>
|
||||
%endif
|
||||
|
||||
%endfor
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1,55 +0,0 @@
|
||||
<div id="history_list">
|
||||
<div class="toolbar">
|
||||
<h1>Histories</h1>
|
||||
<a class="back button" href="#">Back</a>
|
||||
</div>
|
||||
|
||||
%if trans.user is None:
|
||||
<ul class="edgetoedge">
|
||||
<li><i style="color: gray"> No histories available (not logged in) </i></li>
|
||||
</ul>
|
||||
|
||||
%else:
|
||||
<ul class="edgetoedge">
|
||||
|
||||
%for i, history in enumerate( trans.user.histories ):
|
||||
|
||||
%if not ( history.purged or history.deleted ):
|
||||
|
||||
|
||||
<li>
|
||||
|
||||
<a href="${h.url_for(controller='mobile', action="history_detail", id=history.id )}">
|
||||
${history.name | h}
|
||||
|
||||
<div class="secondary">${h.date.distance_of_time_in_words( history.update_time, h.date.datetime.utcnow() )} ago</div>
|
||||
|
||||
<div class="counts">
|
||||
<%
|
||||
total_ok = sum( 1 for d in history.active_datasets if d.state == 'ok' )
|
||||
total_running = sum( 1 for d in history.active_datasets if d.state == 'running' )
|
||||
total_queued = sum( 1 for d in history.active_datasets if d.state == 'queued' )
|
||||
total_error = sum( 1 for d in history.active_datasets if d.state in ( 'error', 'fail' ) )
|
||||
parts = []
|
||||
if total_ok:
|
||||
parts.append( "<span style='color: #66AA66'>" + str(total_ok) + " finished</span>" )
|
||||
if total_queued:
|
||||
parts.append( "<span style='color: #888888'>" + str(total_queued) + " queued</span>" )
|
||||
if total_running:
|
||||
parts.append( "<span style='color: #AAAA66'>" + str(total_running) + " running</span>" )
|
||||
if total_error:
|
||||
parts.append( "<span style='color: #AA6666'>" + str(total_error) + " failed</span>" )
|
||||
|
||||
%>
|
||||
${", ".join( parts )}
|
||||
</div>
|
||||
|
||||
</a>
|
||||
|
||||
</li>
|
||||
%endif
|
||||
%endfor
|
||||
|
||||
</ul>
|
||||
%endif
|
||||
</div>
|
||||
@@ -1,57 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>
|
||||
Galaxy
|
||||
%if app.config.brand:
|
||||
| ${app.config.brand}
|
||||
%endif
|
||||
</title>
|
||||
|
||||
<style>
|
||||
li > a > div {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
div.secondary {
|
||||
font-size: 13px;
|
||||
color: gray;
|
||||
}
|
||||
div.counts {
|
||||
padding-top: 1px;
|
||||
font-size: 13px;
|
||||
color: gray;
|
||||
}
|
||||
.logo {
|
||||
background: center left no-repeat url(${h.url_for('/static/images/galaxyIcon_noText.png')});
|
||||
padding-left: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style type="text/css" media="screen">@import "${h.url_for('/static/jqtouch/jqtouch.css')}";</style>
|
||||
<script type="text/javascript" src="${h.url_for('/static/scripts/libs/jquery/jquery.js')}"></script>
|
||||
<script type="text/javascript" src="${h.url_for('/static/scripts/libs/jquery/jqtouch.js')}"></script>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
$(document).jQTouch( {
|
||||
icon: "${h.url_for('/static/images/galaxyIcon_noText.png')}",
|
||||
slideInSelector: 'ul li a, .row a, a.async'
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<div id="home" selected="true">
|
||||
<div class="toolbar">
|
||||
<h1><span class="logo">Galaxy</span></h1>
|
||||
<a class="button async" href="${h.url_for(controller='mobile', action='settings' )}">Settings</a>
|
||||
</div>
|
||||
<ul class="edgetoedge">
|
||||
<li><a href="${h.url_for(controller='mobile', action='history_list' )}">Histories</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,73 +0,0 @@
|
||||
<%inherit file="/base.mako"/>
|
||||
<%namespace file="/message.mako" import="render_msg" />
|
||||
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />
|
||||
<%namespace file="/common/template_common.mako" import="render_template_fields" />
|
||||
|
||||
<% current_user_roles = trans.get_current_user_roles() %>
|
||||
|
||||
%if message:
|
||||
${render_msg( message, status )}
|
||||
%endif
|
||||
|
||||
%if trans.app.security_agent.can_modify_library_item( current_user_roles, library ):
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">Change library name and description</div>
|
||||
<div class="toolFormBody">
|
||||
<form name="library" action="${h.url_for( controller='library_common', action='library_info', id=trans.security.encode_id( library.id ), cntrller='mobile' )}" method="post" >
|
||||
<div class="form-row">
|
||||
<label>Name:</label>
|
||||
<div style="float: left; width: 250px; margin-right: 10px;">
|
||||
<input type="text" name="name" value="${library.name}" size="40"/>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Description:</label>
|
||||
<div style="float: left; width: 250px; margin-right: 10px;">
|
||||
<input type="text" name="description" value="${library.description}" size="40"/>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Synopsis:</label>
|
||||
<div style="float: left; width: 250px; margin-right: 10px;">
|
||||
<input type="text" name="synopsis" value="${library.synopsis}" size="40"/>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
<input type="submit" name="library_info_button" value="Save"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<p/>
|
||||
%else:
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">View information about ${library.name}</div>
|
||||
<div class="form-row">
|
||||
<label>Name:</label>
|
||||
${library.name}
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="form-row">
|
||||
<label>Description:</label>
|
||||
${library.description}
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="form-row">
|
||||
<label>Synopsis:</label>
|
||||
${library.synopsis}
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="toolForm">
|
||||
${render_template_fields( cntrller='mobile', item_type='library', widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, library_id=trans.security.encode_id( library.id ), info_association=info_association, inherited=inherited )}
|
||||
</div>
|
||||
</div>
|
||||
%endif
|
||||
%if trans.app.security_agent.can_manage_library_item( current_user_roles, library ):
|
||||
<% roles = trans.app.security_agent.get_legitimate_roles( trans, library, 'mobile' ) %>
|
||||
${render_permission_form( library, library.name, h.url_for( controller='library_common', cntrller='mobile', action='library_permissions', id=trans.security.encode_id( library.id ) ), roles )}
|
||||
%endif
|
||||
|
||||
%if widgets:
|
||||
${render_template_fields( cntrller='mobile', item_type='library', widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, library_id=trans.security.encode_id( library.id ), info_association=info_association, inherited=inherited )}
|
||||
%endif
|
||||
@@ -1,34 +0,0 @@
|
||||
<form id="settings" class="panel" action="${h.url_for(controller='mobile', action='settings' )}" method="post">
|
||||
|
||||
<div class="toolbar">
|
||||
<h1>Settings</h1>
|
||||
<a class="back button leftButton" href="#">Cancel</a>
|
||||
<input class="button blueButton" type="submit" href="#" value="Save">
|
||||
</div>
|
||||
|
||||
<div class="pad">
|
||||
|
||||
|
||||
<h2>User information</h2>
|
||||
<fieldset>
|
||||
<%
|
||||
if t.user:
|
||||
email = t.user.email
|
||||
else:
|
||||
email = ""
|
||||
%>
|
||||
|
||||
<div class="row">
|
||||
<label>Email</label>
|
||||
<input type="text" name="email" value="${email}">
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Password</label>
|
||||
<input type="password" name="password" value ="">
|
||||
</div>
|
||||
</fieldset>
|
||||
%if message:
|
||||
<div>${message}</div>
|
||||
%endif
|
||||
</div>
|
||||
</form>
|
||||
@@ -133,9 +133,17 @@ class JobsApiTestCase(api.ApiTestCase):
|
||||
def test_deleting_output_keep_running_until_all_deleted(self):
|
||||
history_id, job_state, outputs = self._setup_running_two_output_job(120)
|
||||
|
||||
self._hack_to_skip_test_if_state_ok(job_state)
|
||||
|
||||
# Delete one of the two outputs and make sure the job is still running.
|
||||
self._raw_update_history_item(history_id, outputs[0]["id"], {"deleted": True})
|
||||
|
||||
self._hack_to_skip_test_if_state_ok(job_state)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
self._hack_to_skip_test_if_state_ok(job_state)
|
||||
|
||||
state = job_state().json()["state"]
|
||||
assert state == "running", state
|
||||
|
||||
@@ -159,12 +167,17 @@ class JobsApiTestCase(api.ApiTestCase):
|
||||
output_dataset_paths = []
|
||||
output_dataset_paths_exist = False
|
||||
|
||||
self._hack_to_skip_test_if_state_ok(job_state)
|
||||
|
||||
current_state = job_state().json()["state"]
|
||||
assert current_state == "running", current_state
|
||||
|
||||
# Purge one of the two outputs and make sure the job is still running.
|
||||
self._raw_update_history_item(history_id, outputs[0]["id"], {"purged": True})
|
||||
time.sleep(1)
|
||||
|
||||
self._hack_to_skip_test_if_state_ok(job_state)
|
||||
|
||||
current_state = job_state().json()["state"]
|
||||
assert current_state == "running", current_state
|
||||
|
||||
@@ -210,6 +223,12 @@ class JobsApiTestCase(api.ApiTestCase):
|
||||
assert os.path.exists(output_dataset_paths[1])
|
||||
assert not os.path.exists(output_dataset_paths[0])
|
||||
|
||||
def _hack_to_skip_test_if_state_ok(self, job_state):
|
||||
from nose.plugins.skip import SkipTest
|
||||
if job_state().json()["state"] == "ok":
|
||||
message = "Job state switch from running to ok too quickly - the rest of the test requires the job to be in a running state. Skipping test."
|
||||
raise SkipTest(message)
|
||||
|
||||
def _setup_running_two_output_job(self, sleep_time):
|
||||
history_id = self.dataset_populator.new_history()
|
||||
payload = self.dataset_populator.run_tool_payload(
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
<datatype extension="fastqcssanger" type="galaxy.datatypes.sequence:FastqCSSanger" display_in_upload="true" />
|
||||
<datatype extension="fastqillumina" type="galaxy.datatypes.sequence:FastqIllumina" display_in_upload="true" />
|
||||
<datatype extension="sam" type="galaxy.datatypes.tabular:Sam" display_in_upload="true" />
|
||||
<datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true" description="A binary file compressed in the BGZF format with a '.bam' file extension." description_url="https://galaxyproject.org/learn/datatypes/#bam" />
|
||||
<datatype extension="bcf" type="galaxy.datatypes.binary:Bcf" mimetype="application/octet-stream" display_in_upload="true" description="A binary file compressed in the BGZF format with a '.bcf' file extension." description_url="https://galaxyproject.org/learn/datatypes/#bcf" />
|
||||
<datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true" description="A binary file compressed in the BGZF format with a '.bam' file extension." description_url="https://galaxyproject.org/learn/datatypes/#bam" />
|
||||
<datatype extension="bcf" type="galaxy.datatypes.binary:Bcf" mimetype="application/octet-stream" display_in_upload="true" description="A binary file compressed in the BGZF format with a '.bcf' file extension." description_url="https://galaxyproject.org/learn/datatypes/#bcf" />
|
||||
<datatype extension="biom1" type="galaxy.datatypes.text:Biom1" display_in_upload="True" subclass="True" mimetype="application/json"/>
|
||||
<datatype extension="bed" type="galaxy.datatypes.interval:Bed" display_in_upload="true" description="BED format provides a flexible way to define the data lines that are displayed in an annotation track. BED lines have three required columns and nine additional optional columns. The three required columns are chrom, chromStart and chromEnd." description_url="https://galaxyproject.org/learn/datatypes/#bed">
|
||||
</datatype>
|
||||
<datatype extension="xml" type="galaxy.datatypes.xml:GenericXml" mimetype="application/xml" display_in_upload="true"/>
|
||||
<datatype extension="vcf" type="galaxy.datatypes.tabular:Vcf" display_in_upload="true"/>
|
||||
<datatype extension="bgzip" type="galaxy.datatypes.binary:Binary" subclass="true" />
|
||||
<datatype extension="vcf_bgzip" type="galaxy.datatypes.tabular:VcfGz" type_extension="bgzip" subclass="true" display_in_upload="true"/>
|
||||
<datatype extension="vcf_bgzip" type="galaxy.datatypes.tabular:VcfGz" display_in_upload="true"/>
|
||||
<datatype extension="html" type="galaxy.datatypes.text:Html" mimetype="text/html"/>
|
||||
</registration>
|
||||
</datatypes>
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
import time
|
||||
|
||||
from .framework import SeleniumTestCase, selenium_test
|
||||
|
||||
# Test case data
|
||||
HISTORY1_NAME = 'First'
|
||||
HISTORY2_NAME = 'Second'
|
||||
HISTORY3_NAME = 'Third'
|
||||
HISTORY4_NAME = 'Four'
|
||||
HISTORY1_TAGS = ['tag1', 'tag2']
|
||||
HISTORY2_TAGS = ['tag3']
|
||||
HISTORY3_TAGS = ['tag1']
|
||||
HISTORY3_ANNOT = 'some description'
|
||||
|
||||
|
||||
class HistoryGridTestCase(SeleniumTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(HistoryGridTestCase, self).setUp()
|
||||
self.ensure_users_and_histories()
|
||||
|
||||
@selenium_test
|
||||
def test_history_grid_histories(self):
|
||||
self.navigate_to_published_histories_page()
|
||||
self.assert_grid_histories_are([HISTORY2_NAME, HISTORY3_NAME, HISTORY1_NAME])
|
||||
|
||||
@selenium_test
|
||||
def test_history_grid_search_standard(self):
|
||||
self.navigate_to_published_histories_page()
|
||||
|
||||
input_selector = '#input-free-text-search-filter'
|
||||
search_input = self.wait_for_selector(input_selector)
|
||||
search_input.send_keys(HISTORY1_NAME)
|
||||
self.send_enter(search_input)
|
||||
self.assert_grid_histories_are([HISTORY1_NAME])
|
||||
|
||||
self.unset_filter('free-text-search', HISTORY1_NAME)
|
||||
search_input = self.wait_for_selector(input_selector)
|
||||
search_input.send_keys(HISTORY4_NAME)
|
||||
self.send_enter(search_input)
|
||||
self.assert_grid_histories_are(['No Items'])
|
||||
|
||||
@selenium_test
|
||||
def test_history_grid_search_advanced(self):
|
||||
self.navigate_to_published_histories_page()
|
||||
|
||||
advanced_search_selector = '#standard-search .advanced-search-toggle'
|
||||
advanced_search_link = self.wait_for_selector(advanced_search_selector)
|
||||
advanced_search_link.click()
|
||||
|
||||
name_filter_selector = '#input-name-filter'
|
||||
annot_filter_selector = '#input-annotation-filter'
|
||||
owner_filter_selector = '#input-username-filter'
|
||||
tags_filter_selector = '#input-tags-filter'
|
||||
|
||||
# Search by name
|
||||
self.set_filter(name_filter_selector, HISTORY1_NAME)
|
||||
self.assert_grid_histories_are([HISTORY1_NAME])
|
||||
self.unset_filter('name', HISTORY1_NAME)
|
||||
|
||||
# Search by annotation
|
||||
annotation = HISTORY3_ANNOT.split(' ')[0]
|
||||
self.set_filter(annot_filter_selector, annotation)
|
||||
self.assert_grid_histories_are([HISTORY3_NAME])
|
||||
self.unset_filter('annotation', annotation)
|
||||
|
||||
# Search by owner
|
||||
owner = self.user2_email.split('@')[0]
|
||||
self.set_filter(owner_filter_selector, owner)
|
||||
self.assert_grid_histories_are([HISTORY2_NAME])
|
||||
self.unset_filter('username', owner)
|
||||
|
||||
# Search by tags
|
||||
self.set_filter(tags_filter_selector, HISTORY1_TAGS[0])
|
||||
self.assert_grid_histories_are([HISTORY3_NAME, HISTORY1_NAME])
|
||||
self.unset_filter('tags', HISTORY1_TAGS[0])
|
||||
|
||||
@selenium_test
|
||||
def test_history_grid_sort_by_name(self):
|
||||
self.navigate_to_published_histories_page()
|
||||
sort_link = self.wait_for_selector('th#name-header > a')
|
||||
sort_link.click()
|
||||
self.assert_grid_histories_are([HISTORY1_NAME, HISTORY2_NAME, HISTORY3_NAME])
|
||||
|
||||
@selenium_test
|
||||
def test_history_grid_sort_by_owner(self):
|
||||
self.navigate_to_published_histories_page()
|
||||
sort_link = self.wait_for_selector('th#username-header > a')
|
||||
sort_link.click()
|
||||
self.assert_grid_histories_are([HISTORY1_NAME, HISTORY3_NAME, HISTORY2_NAME])
|
||||
|
||||
@selenium_test
|
||||
def test_history_grid_tag_click(self):
|
||||
self.navigate_to_published_histories_page()
|
||||
|
||||
tags = None
|
||||
grid = self.wait_for_selector('#grid-table-body')
|
||||
for row in grid.find_elements_by_tag_name('tr'):
|
||||
cell = row.find_elements_by_tag_name('td')[0] # Name
|
||||
if cell.text == HISTORY1_NAME:
|
||||
tags = row.find_elements_by_tag_name('td')[4] # Tags
|
||||
break
|
||||
assert tags is not None
|
||||
|
||||
tag_button_selector = '.tag-area > .tag-button:first-child > .tag-name'
|
||||
tag_button = tags.find_element_by_css_selector(tag_button_selector)
|
||||
assert tag_button.text == HISTORY1_TAGS[0]
|
||||
|
||||
tag_button.click()
|
||||
|
||||
self.assert_grid_histories_are([HISTORY3_NAME, HISTORY1_NAME])
|
||||
|
||||
def get_histories(self, sleep=False):
|
||||
time.sleep(1.5)
|
||||
|
||||
names = []
|
||||
grid = self.wait_for_selector('#grid-table-body')
|
||||
for row in grid.find_elements_by_tag_name('tr'):
|
||||
cell = row.find_elements_by_tag_name('td')[0] # Name
|
||||
names.append(cell.text)
|
||||
|
||||
return names
|
||||
|
||||
def assert_grid_histories_are(self, expected_histories, sort_matters=True):
|
||||
actual_histories = self.get_histories()
|
||||
if not sort_matters:
|
||||
expected_histories = set(expected_histories)
|
||||
actual_histories = set(actual_histories)
|
||||
|
||||
self.assertEqual(expected_histories, actual_histories)
|
||||
|
||||
def set_filter(self, selector, value):
|
||||
filter_input = self.wait_for_selector_clickable(selector)
|
||||
filter_input.send_keys(value)
|
||||
self.send_enter(filter_input)
|
||||
|
||||
def unset_filter(self, filter_key, filter_value):
|
||||
close_link_selector = 'a[filter_key="%s"][filter_val="%s"]' % \
|
||||
(filter_key, filter_value)
|
||||
close_link = self.wait_for_selector_clickable(close_link_selector)
|
||||
close_link.click()
|
||||
time.sleep(.5)
|
||||
|
||||
def set_tags(self, tags):
|
||||
tag_icon_selector = self.test_data['historyPanel']['selectors']['history']['tagIcon']
|
||||
tag_area_selector = self.test_data['historyPanel']['selectors']['history']['tagArea']
|
||||
|
||||
if not self.is_displayed(tag_area_selector):
|
||||
tag_icon = self.wait_for_selector_clickable(tag_icon_selector)
|
||||
tag_icon.click()
|
||||
|
||||
tag_area_selector += ' .tags-input input'
|
||||
tag_area = self.wait_for_selector_clickable(tag_area_selector)
|
||||
tag_area.click()
|
||||
|
||||
for tag in tags:
|
||||
tag_area.send_keys(tag)
|
||||
self.send_enter(tag_area)
|
||||
time.sleep(.5)
|
||||
|
||||
def set_annotation(self, annotation):
|
||||
anno_icon_selector = self.test_data['historyPanel']['selectors']['history']['annoIcon']
|
||||
anno_area_selector = self.test_data['historyPanel']['selectors']['history']['annoArea']
|
||||
|
||||
if not self.is_displayed(anno_area_selector):
|
||||
annon_icon = self.wait_for_selector_clickable(anno_icon_selector)
|
||||
annon_icon.click()
|
||||
|
||||
anno_area_selector += ' .annotation'
|
||||
annon_area = self.wait_for_selector_clickable(anno_area_selector)
|
||||
annon_area.click()
|
||||
|
||||
area_editable_selector = anno_area_selector + ' textarea'
|
||||
done_button_selector = anno_area_selector + ' button'
|
||||
annon_area_editable = self.wait_for_selector_clickable(area_editable_selector)
|
||||
anno_done_button = self.wait_for_selector_clickable(done_button_selector)
|
||||
|
||||
annon_area_editable.click()
|
||||
annon_area_editable.send_keys(annotation)
|
||||
anno_done_button.click()
|
||||
|
||||
def ensure_users_and_histories(self):
|
||||
if getattr(HistoryGridTestCase, "user1_email", None):
|
||||
return
|
||||
|
||||
HistoryGridTestCase.user1_email = self._get_random_email()
|
||||
HistoryGridTestCase.user2_email = self._get_random_email()
|
||||
self.register(self.user1_email)
|
||||
self.create_history(HISTORY1_NAME)
|
||||
self.set_tags(HISTORY1_TAGS)
|
||||
self.publish_current_history()
|
||||
|
||||
self.create_history(HISTORY3_NAME)
|
||||
self.set_tags(HISTORY3_TAGS)
|
||||
self.set_annotation(HISTORY3_ANNOT)
|
||||
self.publish_current_history()
|
||||
self.logout_if_needed()
|
||||
|
||||
self.register(self.user2_email)
|
||||
self.create_history(HISTORY2_NAME)
|
||||
self.set_tags(HISTORY2_TAGS)
|
||||
self.publish_current_history()
|
||||
|
||||
def create_history(self, name):
|
||||
self.click_history_option('Create New')
|
||||
|
||||
# Rename the history
|
||||
editable_text_input_element = self.click_to_rename_history()
|
||||
editable_text_input_element.send_keys(name)
|
||||
self.send_enter(editable_text_input_element)
|
||||
|
||||
def publish_current_history(self):
|
||||
self.click_history_option('Share or Publish')
|
||||
with self.main_panel():
|
||||
selector = 'input[name="make_accessible_and_publish"]'
|
||||
publish_button = self.wait_for_selector_clickable(selector)
|
||||
publish_button.click()
|
||||
|
||||
def navigate_to_published_histories_page(self):
|
||||
self.home()
|
||||
self.click_masthead_user() # Open masthead menu
|
||||
self.click_label(
|
||||
self.navigation_data['labels']['masthead']['menus']['libraries'])
|
||||
selector = 'a[href="/histories/list_published"]'
|
||||
histories_link = self.wait_for_selector_clickable(selector)
|
||||
histories_link.click()
|
||||
|
||||
def click_history_option(self, option_label):
|
||||
self.home()
|
||||
self.click_history_options() # Open history menu
|
||||
|
||||
# Click labelled option
|
||||
menu_option = self.driver.find_element_by_link_text(option_label)
|
||||
menu_option.click()
|
||||
|
||||
def click_to_rename_history(self):
|
||||
self.history_panel_name_element().click()
|
||||
edit_title_input_selector = self.test_data['historyPanel']['selectors']['history']['nameEditableTextInput']
|
||||
return self.wait_for_selector(edit_title_input_selector)
|
||||
|
||||
def is_displayed(self, selector):
|
||||
element = self.driver.find_element_by_css_selector(selector)
|
||||
return element.is_displayed()
|
||||