mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge remote-tracking branch 'upstream/dev' into workflow_list_fixes
This commit is contained in:
+9
-22
@@ -1,26 +1,13 @@
|
||||
module.exports = function(grunt) {
|
||||
"use strict";
|
||||
|
||||
var GALAXY_PATHS = {
|
||||
dist : '../static/scripts',
|
||||
maps : '../static/maps',
|
||||
// this symlink allows us to serve uncompressed scripts in DEV_PATH for use with sourcemaps
|
||||
srcSymlink : '../static/src',
|
||||
},
|
||||
TOOLSHED_PATHS = {
|
||||
dist : '../static/toolshed/scripts',
|
||||
maps : '../static/toolshed/maps',
|
||||
srcSymlink : '../static/toolshed/src',
|
||||
};
|
||||
|
||||
grunt.config.set( 'app', 'galaxy' );
|
||||
grunt.config.set( 'paths', GALAXY_PATHS );
|
||||
if( grunt.option( 'app' ) === 'toolshed' ){
|
||||
grunt.config.set( 'app', grunt.option( 'app' ) );
|
||||
grunt.config.set( 'paths', TOOLSHED_PATHS );
|
||||
}
|
||||
|
||||
dist: "../static/scripts",
|
||||
maps: "../static/maps",
|
||||
// this symlink allows us to serve uncompressed scripts in DEV_PATH for use with sourcemaps
|
||||
srcSymlink: "../static/src"
|
||||
};
|
||||
grunt.config.set("app", "galaxy");
|
||||
grunt.config.set("paths", GALAXY_PATHS);
|
||||
// see the sub directory grunt-tasks/ for individual task definitions
|
||||
grunt.loadTasks( 'grunt-tasks' );
|
||||
grunt.registerTask( 'default', [ 'uglify' ] );
|
||||
grunt.loadTasks("grunt-tasks");
|
||||
grunt.registerTask("default", ["style"]);
|
||||
};
|
||||
|
||||
@@ -66,13 +66,3 @@ As mentioned above, 'make client' will also rebuild styles. If you *only* want
|
||||
to run the style task, use the following command from the `client` directory:
|
||||
|
||||
yarn run style
|
||||
|
||||
|
||||
The Toolshed Client Build
|
||||
=========================
|
||||
|
||||
The toolshed client is not tightly integrated with the rest of the build
|
||||
system. To build the toolshed client, execute the following command from the
|
||||
`client` directory.
|
||||
|
||||
yarn run build-toolshed
|
||||
|
||||
@@ -1,11 +1,37 @@
|
||||
import _l from "utils/localization";
|
||||
import GalaxyApp from "galaxy";
|
||||
import WorkflowView from "mvc/workflow/workflow-view";
|
||||
import Trackster from "viz/trackster";
|
||||
import Circster from "viz/circster";
|
||||
import Phyloviz from "viz/phyloviz";
|
||||
import Sweepster from "viz/sweepster";
|
||||
import GalaxyLibrary from "galaxy.library";
|
||||
import AdminToolshed from "admin.toolshed";
|
||||
import Masthead from "layout/masthead";
|
||||
import user from "mvc/user/user-model";
|
||||
import Modal from "mvc/ui/ui-modal";
|
||||
import pagesEditorOnload from "galaxy.pages";
|
||||
import Data from "mvc/dataset/data";
|
||||
import History from "mvc/history/history-model";
|
||||
import StructureView from "mvc/history/history-structure-view";
|
||||
import HistoryContents from "mvc/history/history-contents";
|
||||
import MultiPanel from "mvc/history/multi-panel";
|
||||
import HistoryView from "mvc/history/history-view";
|
||||
import HistoryViewEdit from "mvc/history/history-view-edit";
|
||||
import HistoryViewAnnotated from "mvc/history/history-view-annotated";
|
||||
import HistoryCopyDialog from "mvc/history/copy-dialog";
|
||||
import HDAListItemEdit from "mvc/history/hda-li-edit";
|
||||
import HDAModel from "mvc/history/hda-model";
|
||||
import addLogging from "utils/add-logging";
|
||||
import LegacyGridView from "legacy/grid/grid-view";
|
||||
import * as run_stats from "reports/run_stats";
|
||||
import ToolshedGroups from "toolshed/toolshed.groups";
|
||||
|
||||
if (window.Galaxy && window.Galaxy.debug === undefined) {
|
||||
//TODO: (kind of a temporary hack?) Must have Galaxy.logging for some of the imports
|
||||
//here; remove when imports are all fixed.
|
||||
addLogging(window.Galaxy, "GalaxyApp");
|
||||
}
|
||||
|
||||
export function mastheadEntry(options) {
|
||||
if (!Galaxy.user) {
|
||||
@@ -34,17 +60,139 @@ export function workflowEntry(options) {
|
||||
new WorkflowView(options);
|
||||
}
|
||||
|
||||
function libraryEntry(options) {
|
||||
export function libraryEntry(options) {
|
||||
new GalaxyLibrary.GalaxyApp(options);
|
||||
}
|
||||
|
||||
export function historyEntry(options) {
|
||||
$("#toggle-deleted").modeButton({
|
||||
initialMode: options.initialModeDeleted,
|
||||
modes: [
|
||||
{ mode: "showing_deleted", html: _l("Exclude deleted") },
|
||||
{ mode: "not_showing_deleted", html: _l("Include deleted") }
|
||||
]
|
||||
});
|
||||
$("#toggle-hidden").modeButton({
|
||||
initialMode: options.initialModeHidden,
|
||||
modes: [
|
||||
{ mode: "showing_hidden", html: _l("Exclude hidden") },
|
||||
{ mode: "not_showing_hidden", html: _l("Include hidden") }
|
||||
]
|
||||
});
|
||||
$("#switch").click(function() {
|
||||
//##HACK:ity hack hack
|
||||
//##TODO: remove when out of iframe
|
||||
var hview =
|
||||
Galaxy.currHistoryPanel || (window.top.Galaxy && window.top.Galaxy.currHistoryPanel)
|
||||
? window.top.Galaxy.currHistoryPanel
|
||||
: null;
|
||||
if (hview) {
|
||||
hview.switchToHistory("${ history[ 'id' ] }");
|
||||
} else {
|
||||
window.location = "${ switch_to_url }";
|
||||
}
|
||||
});
|
||||
// use_panels effects where the the center_panel() is rendered:
|
||||
// w/o it renders to the body, w/ it renders to #center - we need to adjust a few things for scrolling to work
|
||||
if (options.hasMasthead) {
|
||||
$("#center").addClass("flex-vertical-container");
|
||||
}
|
||||
|
||||
let viewClass = options.userIsOwner ? HistoryViewEdit.HistoryViewEdit : HistoryView.HistoryView;
|
||||
let historyModel = new History.History(options.historyJSON);
|
||||
|
||||
// attach the copy dialog to the import button now that we have a history
|
||||
$("#import").click(function() {
|
||||
HistoryCopyDialog(historyModel, {
|
||||
useImport: true,
|
||||
// use default datasets option to match the toggle-deleted button
|
||||
allDatasets: $("#toggle-deleted").modeButton("getMode").mode === "showing_deleted"
|
||||
}).done(function() {
|
||||
if (window === window.parent) {
|
||||
window.location = Galaxy.root;
|
||||
} else if (Galaxy.currHistoryPanel) {
|
||||
Galaxy.currHistoryPanel.loadCurrentHistory();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let historyView = new viewClass({
|
||||
el: $("#history-" + options.historyJSON.id),
|
||||
className: viewClass.prototype.className + " wide",
|
||||
$scrollContainer: options.hasMasthead
|
||||
? function() {
|
||||
return this.$el.parent();
|
||||
}
|
||||
: undefined,
|
||||
model: historyModel,
|
||||
show_deleted: options.showDeletedJson,
|
||||
show_hidden: options.showHiddenJson,
|
||||
purgeAllowed: options.allow_user_dataset_purge
|
||||
});
|
||||
historyView.trigger("loading");
|
||||
historyModel
|
||||
.fetchContents({ silent: true })
|
||||
.fail(function() {
|
||||
alert("Galaxy history failed to load");
|
||||
})
|
||||
.done(function() {
|
||||
historyView.trigger("loading-done");
|
||||
historyView.render();
|
||||
});
|
||||
$("#toggle-deleted").on("click", function() {
|
||||
historyView.toggleShowDeleted();
|
||||
});
|
||||
$("#toggle-hidden").on("click", function() {
|
||||
historyView.toggleShowHidden();
|
||||
});
|
||||
}
|
||||
|
||||
export function multiHistoryEntry(options) {
|
||||
let histories = new History.HistoryCollection([], {
|
||||
includeDeleted: options.includingDeleted,
|
||||
order: options.order,
|
||||
limitOnFirstFetch: options.limit,
|
||||
limitPerFetch: options.limit,
|
||||
currentHistoryId: options.current_history_id
|
||||
});
|
||||
|
||||
let multipanel = new MultiPanel.MultiPanelColumns({
|
||||
el: $("#center").get(0),
|
||||
histories: histories
|
||||
});
|
||||
|
||||
histories.fetchFirst({ silent: true }).done(function() {
|
||||
multipanel.createColumns();
|
||||
multipanel.render(0);
|
||||
});
|
||||
}
|
||||
|
||||
export const bundleEntries = {
|
||||
library: libraryEntry,
|
||||
masthead: mastheadEntry,
|
||||
workflow: workflowEntry,
|
||||
trackster: tracksterEntry,
|
||||
circster: circsterEntry,
|
||||
adminToolshed: adminToolshedEntry
|
||||
adminToolshed: adminToolshedEntry,
|
||||
pages: pagesEditorOnload,
|
||||
phyloviz: Phyloviz.PhylovizView,
|
||||
createTabularDatasetChunkedView: Data.createTabularDatasetChunkedView,
|
||||
multiHistory: multiHistoryEntry,
|
||||
history: historyEntry,
|
||||
History: History.History,
|
||||
HistoryContents: HistoryContents.HistoryContents,
|
||||
SweepsterVisualization: Sweepster.SweepsterVisualization,
|
||||
SweepsterVisualizationView: Sweepster.SweepsterVisualizationView,
|
||||
HistoryCopyDialog,
|
||||
HistoryViewAnnotated,
|
||||
Trackster,
|
||||
StructureView,
|
||||
HDAListItemEdit,
|
||||
HDAModel,
|
||||
GalaxyApp,
|
||||
LegacyGridView,
|
||||
run_stats,
|
||||
ToolshedGroups
|
||||
};
|
||||
|
||||
window.bundleEntries = bundleEntries;
|
||||
|
||||
@@ -256,6 +256,9 @@ GalaxyApp.prototype.toString = function toString() {
|
||||
return `GalaxyApp(${userEmail})`;
|
||||
};
|
||||
|
||||
// This is not great. Rework to be a singleton-style Galaxy app accessible/created by import
|
||||
window.Galaxy = window.Galaxy || new GalaxyApp();
|
||||
|
||||
// ============================================================================
|
||||
export default {
|
||||
GalaxyApp: GalaxyApp
|
||||
|
||||
@@ -176,7 +176,7 @@ var GalaxyLibrary = Backbone.View.extend({
|
||||
mod_toastr.info("You must select at least one dataset to download");
|
||||
Galaxy.libraries.library_router.navigate(`folders/${folder_id}`, { trigger: true, replace: true });
|
||||
} else {
|
||||
Galaxy.libraries.folderToolbarView.download(folder_id, format);
|
||||
Galaxy.libraries.folderToolbarView.download(format);
|
||||
Galaxy.libraries.library_router.navigate(`folders/${folder_id}`, { trigger: false, replace: true });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,6 +5,8 @@ import "libs/jquery/jquery.wymeditor";
|
||||
import "libs/jquery/jquery.autocomplete";
|
||||
import GridView from "mvc/grid/grid-view";
|
||||
|
||||
var WYMeditor = window.WYMeditor;
|
||||
|
||||
var CONTROLS = {
|
||||
// Item types.
|
||||
ITEM_HISTORY: "item_history",
|
||||
@@ -487,7 +489,7 @@ WYMeditor.editor.prototype.dialog = function(dialogType, dialogFeatures, bodyHtm
|
||||
}
|
||||
};
|
||||
|
||||
export default function editor_onload() {
|
||||
export default function pagesEditorOnload() {
|
||||
// Generic error handling
|
||||
$(document).ajaxError((e, x) => {
|
||||
// console.log( e, x );
|
||||
|
||||
@@ -17,10 +17,8 @@ var Router = Backbone.Router.extend({
|
||||
data.__identifer = Math.random()
|
||||
.toString(36)
|
||||
.substr(2);
|
||||
if (!$.isEmptyObject(data)) {
|
||||
url += url.indexOf("?") == -1 ? "?" : "&";
|
||||
url += $.param(data, true);
|
||||
}
|
||||
url += url.indexOf("?") == -1 ? "?" : "&";
|
||||
url += $.param(data, true);
|
||||
Galaxy.params = data;
|
||||
this.navigate(url, { trigger: true });
|
||||
},
|
||||
|
||||
@@ -4754,3 +4754,5 @@ WYMeditor.WymClassSafari.prototype.getTagForStyle = function(style) {
|
||||
if(/super/.test(style)) return 'sup';
|
||||
return false;
|
||||
};
|
||||
|
||||
window.WYMeditor = WYMeditor;
|
||||
|
||||
@@ -278,8 +278,8 @@ var ListCollectionCreator = Backbone.View.extend(BASE_MVC.LoggableMixin)
|
||||
|
||||
/** describe what is wrong with a particular element if anything */
|
||||
_isElementInvalid: function(element) {
|
||||
if (element.history_content_type !== "dataset") {
|
||||
return _l("is not a dataset");
|
||||
if (element.history_content_type === "dataset_collection") {
|
||||
return _l("is a collection, this is not allowed");
|
||||
}
|
||||
var validState = element.state === STATES.OK || _.contains(STATES.NOT_READY_STATES, element.state);
|
||||
if (!validState) {
|
||||
|
||||
@@ -1796,7 +1796,8 @@ var pairedCollectionCreatorModal = function _pairedCollectionCreatorModal(datase
|
||||
oncreate: function(creator, response) {
|
||||
Galaxy.modal.hide();
|
||||
deferred.resolve(response);
|
||||
}
|
||||
},
|
||||
title: _l("Create a collection of paired datasets")
|
||||
});
|
||||
|
||||
if (!window.Galaxy || !Galaxy.modal) {
|
||||
@@ -1805,7 +1806,7 @@ var pairedCollectionCreatorModal = function _pairedCollectionCreatorModal(datase
|
||||
|
||||
creator = new PairedCollectionCreator(options);
|
||||
Galaxy.modal.show({
|
||||
title: _l("Create a collection of paired datasets"),
|
||||
title: options.title,
|
||||
body: creator.$el,
|
||||
width: "80%",
|
||||
height: "800px",
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import _l from "utils/localization";
|
||||
// Additional dependencies: jQuery, underscore.
|
||||
import Modal from "mvc/ui/ui-modal";
|
||||
import Frames from "mvc/ui/ui-frames";
|
||||
import mod_icon_btn from "mvc/ui/icon-button";
|
||||
// Additional dependencies: jQuery, underscore.
|
||||
/**
|
||||
* Dataset metedata.
|
||||
*/
|
||||
|
||||
@@ -286,47 +286,39 @@ var DatasetListItemView = _super.extend(
|
||||
return this._renderMetaFileDownloadButton();
|
||||
}
|
||||
|
||||
return $(
|
||||
[
|
||||
'<a class="download-btn icon-btn" ',
|
||||
'href="',
|
||||
this.model.urls.download,
|
||||
`" title="${_l("Download")}" download>`,
|
||||
'<span class="fa fa-floppy-o"></span>',
|
||||
"</a>"
|
||||
].join("")
|
||||
);
|
||||
return $(`
|
||||
<a class="download-btn icon-btn" href="${this.model.urls.download}" title="${_l("Download")}">
|
||||
<span class="fa fa-floppy-o"></span>
|
||||
</a>`);
|
||||
},
|
||||
|
||||
/** Render the download button which opens a dropdown with links to download assoc. meta files (indeces, etc.) */
|
||||
/** Render the download button which opens a dropdown with links to download assoc. meta files (indices, etc.) */
|
||||
_renderMetaFileDownloadButton: function() {
|
||||
var urls = this.model.urls;
|
||||
return $(
|
||||
[
|
||||
'<div class="metafile-dropdown dropdown">',
|
||||
'<a class="download-btn icon-btn" href="javascript:void(0)" data-toggle="dropdown"',
|
||||
` title="${_l("Download")}">`,
|
||||
'<span class="fa fa-floppy-o"></span>',
|
||||
"</a>",
|
||||
'<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">',
|
||||
`<li><a href="${urls.download}" download>`,
|
||||
_l("Download dataset"),
|
||||
"</a></li>",
|
||||
_.map(this.model.get("meta_files"), meta_file =>
|
||||
[
|
||||
'<li><a href="',
|
||||
urls.meta_download + meta_file.file_type,
|
||||
'">',
|
||||
_l("Download"),
|
||||
" ",
|
||||
meta_file.file_type,
|
||||
"</a></li>"
|
||||
].join("")
|
||||
).join("\n"),
|
||||
"</ul>",
|
||||
"</div>"
|
||||
].join("\n")
|
||||
);
|
||||
return $(`
|
||||
<div class="metafile-dropdown dropdown">
|
||||
<a class="download-btn icon-btn" href="${urls.download}" data-toggle="dropdown" title="${_l(
|
||||
"Download"
|
||||
)}">
|
||||
<span class="fa fa-floppy-o"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
|
||||
<li>
|
||||
<a href="${urls.download}">
|
||||
${_l("Download dataset")}
|
||||
</a>
|
||||
</li>
|
||||
${_.map(
|
||||
this.model.get("meta_files"),
|
||||
meta_file =>
|
||||
`<li>
|
||||
<a href="${urls.meta_download + meta_file.file_type}">
|
||||
${_l("Download")} ${meta_file.file_type}
|
||||
</a>
|
||||
</li>`
|
||||
)}
|
||||
</ul>
|
||||
</div>`);
|
||||
},
|
||||
|
||||
_renderNametags: function() {
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
function _labelIfName(tag) {
|
||||
if (tag.indexOf("name:") == 0) {
|
||||
return `<span class="label label-info">${_.escape(tag.slice(5))}</span>`;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
function _templateNametag(tag) {
|
||||
return `<span class="label label-info">${_.escape(tag.slice(5))}</span>`;
|
||||
}
|
||||
|
||||
function nametagTemplate(historyItem) {
|
||||
return `<span class="nametags">${_.sortBy(_.uniq(historyItem.tags))
|
||||
.map(_labelIfName)
|
||||
.join("")}</span>`;
|
||||
let uniqueNametags = _.filter(_.uniq(historyItem.tags), t => t.indexOf("name:") === 0);
|
||||
let nametagsDisplay = _.sortBy(uniqueNametags).map(_templateNametag);
|
||||
return `
|
||||
<div class="nametags" title="${uniqueNametags.length} nametags">
|
||||
${nametagsDisplay.join("")}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,17 +39,16 @@ export var View = Backbone.View.extend({
|
||||
if (!this.visible) {
|
||||
this.visible = true;
|
||||
this.$el.fadeIn("fast");
|
||||
if (this.options.closing_events) {
|
||||
var self = this;
|
||||
$(document).on("keyup.ui-modal", e => {
|
||||
if (e.keyCode == 27) {
|
||||
self.hide(true);
|
||||
}
|
||||
});
|
||||
this.$backdrop.on("click", () => {
|
||||
self.hide(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (this.options.closing_events) {
|
||||
$(document).on("keyup.ui-modal", e => {
|
||||
if (e.keyCode == 27) {
|
||||
this.hide(true);
|
||||
}
|
||||
});
|
||||
this.$backdrop.on("click", () => {
|
||||
this.hide(true);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import Utils from "utils/utils";
|
||||
import Buttons from "mvc/ui/ui-buttons";
|
||||
var View = Backbone.View.extend({
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
this.data = [];
|
||||
this.data2 = [];
|
||||
this.model =
|
||||
@@ -28,7 +27,9 @@ var View = Backbone.View.extend({
|
||||
pagesize: 20
|
||||
}).set(options);
|
||||
this.on("change", () => {
|
||||
self.model.get("onchange") && self.model.get("onchange")(self.value());
|
||||
if (this.model.get("onchange")) {
|
||||
this.model.get("onchange")(this.value());
|
||||
}
|
||||
});
|
||||
this.listenTo(this.model, "change:data", this._changeData, this);
|
||||
this.listenTo(this.model, "change:disabled", this._changeDisabled, this);
|
||||
@@ -40,8 +41,11 @@ var View = Backbone.View.extend({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
this.model.get("searchable") ? this._renderSearchable() : this._renderClassic();
|
||||
if (this.model.get("searchable")) {
|
||||
this._renderSearchable();
|
||||
} else {
|
||||
this._renderClassic();
|
||||
}
|
||||
this.$el.addClass(this.model.get("cls")).attr("id", this.model.get("id"));
|
||||
this.$select
|
||||
.empty()
|
||||
@@ -49,8 +53,8 @@ var View = Backbone.View.extend({
|
||||
.attr("id", `${this.model.get("id")}_select`)
|
||||
.prop("multiple", this.model.get("multiple"))
|
||||
.on("change", () => {
|
||||
self.value(self._getValue());
|
||||
self.trigger("change");
|
||||
this.value(this._getValue());
|
||||
this.trigger("change");
|
||||
});
|
||||
this._changeData();
|
||||
this._changeWait();
|
||||
@@ -60,7 +64,6 @@ var View = Backbone.View.extend({
|
||||
|
||||
/** Renders the classic selection field */
|
||||
_renderClassic: function() {
|
||||
var self = this;
|
||||
this.$el
|
||||
.addClass(this.model.get("multiple") ? "ui-select-multiple" : "ui-select")
|
||||
.append((this.$select = $("<select/>")))
|
||||
@@ -76,12 +79,12 @@ var View = Backbone.View.extend({
|
||||
.off("mousedown")
|
||||
.on("mousedown", event => {
|
||||
var currentY = event.pageY;
|
||||
var currentHeight = self.$select.height();
|
||||
self.minHeight = self.minHeight || currentHeight;
|
||||
var currentHeight = this.$select.height();
|
||||
this.minHeight = this.minHeight || currentHeight;
|
||||
$("#dd-helper")
|
||||
.show()
|
||||
.on("mousemove", event => {
|
||||
self.$select.height(Math.max(currentHeight + (event.pageY - currentY), self.minHeight));
|
||||
this.$select.height(Math.max(currentHeight + (event.pageY - currentY), this.minHeight));
|
||||
})
|
||||
.on("mouseup mouseleave", () => {
|
||||
$("#dd-helper")
|
||||
@@ -98,25 +101,27 @@ var View = Backbone.View.extend({
|
||||
|
||||
/** Renders the default select2 field */
|
||||
_renderSearchable: function() {
|
||||
var self = this;
|
||||
this.$el.append((this.$select = $("<div/>"))).append((this.$dropdown = $("<div/>")));
|
||||
this.$dropdown.hide();
|
||||
if (!this.model.get("multiple")) {
|
||||
this.$dropdown.show().on("click", () => {
|
||||
self.$select.select2 && self.$select.select2("open");
|
||||
if (this.$select.select2) {
|
||||
this.$select.select2("open");
|
||||
}
|
||||
});
|
||||
}
|
||||
this.all_button = null;
|
||||
if (this.model.get("multiple") && !this.model.get("individual") && !this.model.get("readonly")) {
|
||||
this.all_button = new Buttons.ButtonCheck({
|
||||
onclick: function() {
|
||||
onclick: () => {
|
||||
var new_value = [];
|
||||
self.all_button.value() !== 0 &&
|
||||
_.each(self.model.get("data"), option => {
|
||||
if (this.all_button.value() !== 0) {
|
||||
_.each(this.model.get("data"), option => {
|
||||
new_value.push(option.value);
|
||||
});
|
||||
self.value(new_value);
|
||||
self.trigger("change");
|
||||
}
|
||||
this.value(new_value);
|
||||
this.trigger("change");
|
||||
}
|
||||
});
|
||||
this.$el.prepend(this.all_button.$el);
|
||||
@@ -127,7 +132,7 @@ var View = Backbone.View.extend({
|
||||
_match: function(term, text) {
|
||||
return (
|
||||
!term ||
|
||||
term == "" ||
|
||||
term === "" ||
|
||||
String(text)
|
||||
.toUpperCase()
|
||||
.indexOf(term.toUpperCase()) >= 0
|
||||
@@ -136,18 +141,17 @@ var View = Backbone.View.extend({
|
||||
|
||||
/** Updates the selection options */
|
||||
_changeData: function() {
|
||||
var self = this;
|
||||
this.data = [];
|
||||
if (!this.model.get("multiple") && this.model.get("optional")) {
|
||||
this.data.push({
|
||||
value: "__null__",
|
||||
label: self.model.get("empty_text")
|
||||
label: this.model.get("empty_text")
|
||||
});
|
||||
}
|
||||
_.each(this.model.get("data"), option => {
|
||||
self.data.push(option);
|
||||
this.data.push(option);
|
||||
});
|
||||
if (this.length() == 0) {
|
||||
if (this.length() === 0) {
|
||||
this.data.push({
|
||||
value: "__null__",
|
||||
label: this.model.get("error_text")
|
||||
@@ -156,61 +160,71 @@ var View = Backbone.View.extend({
|
||||
if (this.model.get("searchable")) {
|
||||
this.data2 = [];
|
||||
_.each(this.data, (option, index) => {
|
||||
self.data2.push({
|
||||
this.data2.push({
|
||||
order: index,
|
||||
id: option.value,
|
||||
text: option.label,
|
||||
tags: option.tags
|
||||
});
|
||||
});
|
||||
this.$select.data("select2") && this.$select.select2("destroy");
|
||||
if (this.$select.data("select2")) {
|
||||
this.$select.select2("destroy");
|
||||
}
|
||||
this.matched_tags = {};
|
||||
this.$select.select2({
|
||||
data: self.data2,
|
||||
data: this.data2,
|
||||
closeOnSelect: !this.model.get("multiple"),
|
||||
multiple: this.model.get("multiple"),
|
||||
query: function(q) {
|
||||
self.matched_tags = {};
|
||||
var pagesize = self.model.get("pagesize");
|
||||
var results = _.filter(self.data2, e => {
|
||||
query: q => {
|
||||
this.matched_tags = {};
|
||||
var pagesize = this.model.get("pagesize");
|
||||
var results = _.filter(this.data2, e => {
|
||||
var found = false;
|
||||
_.each(e.tags, tag => {
|
||||
if (self._match(q.term, tag)) {
|
||||
found = self.matched_tags[tag] = true;
|
||||
if (this._match(q.term, tag)) {
|
||||
found = this.matched_tags[tag] = true;
|
||||
}
|
||||
});
|
||||
return found || self._match(q.term, e.text);
|
||||
return found || this._match(q.term, e.text);
|
||||
});
|
||||
q.callback({
|
||||
results: results.slice((q.page - 1) * pagesize, q.page * pagesize),
|
||||
more: results.length >= q.page * pagesize
|
||||
});
|
||||
},
|
||||
formatResult: function(result) {
|
||||
return `${_.escape(result.text)}<div class="ui-tags">${_.reduce(
|
||||
result.tags,
|
||||
(memo, tag) => {
|
||||
if (self.matched_tags[tag]) {
|
||||
formatResult: result => {
|
||||
let extraTagWarning = "";
|
||||
let filteredTags = _.filter(result.tags, t => this.matched_tags.hasOwnProperty(t));
|
||||
if (filteredTags.length > 5) {
|
||||
extraTagWarning = ` <div class="label label-warning">${filteredTags.length -
|
||||
5} more tags</div>`;
|
||||
}
|
||||
return `
|
||||
${_.escape(result.text)}
|
||||
<div class="ui-tags">
|
||||
${_.reduce(
|
||||
filteredTags.slice(0, 5),
|
||||
(memo, tag) => {
|
||||
return `${memo} <div class="label label-info">${_.escape(tag)}</div>`;
|
||||
}
|
||||
return memo;
|
||||
},
|
||||
""
|
||||
)}</div>`;
|
||||
},
|
||||
""
|
||||
)}
|
||||
${extraTagWarning}
|
||||
</div>`;
|
||||
}
|
||||
});
|
||||
this.$(".select2-container .select2-search input").off("blur");
|
||||
} else {
|
||||
this.$select.find("option").remove();
|
||||
_.each(this.data, option => {
|
||||
self.$select.append(
|
||||
this.$select.append(
|
||||
$("<option/>")
|
||||
.attr("value", option.value)
|
||||
.html(_.escape(option.label))
|
||||
);
|
||||
});
|
||||
}
|
||||
this.model.set("disabled", this.model.get("readonly") || this.length() == 0);
|
||||
this.model.set("disabled", this.model.get("readonly") || this.length() === 0);
|
||||
this._changeValue();
|
||||
},
|
||||
|
||||
@@ -252,7 +266,9 @@ var View = Backbone.View.extend({
|
||||
|
||||
/** Return/Set current selection */
|
||||
value: function(new_value) {
|
||||
new_value !== undefined && this.model.set("value", new_value);
|
||||
if (new_value !== undefined) {
|
||||
this.model.set("value", new_value);
|
||||
}
|
||||
return this._getValue();
|
||||
},
|
||||
|
||||
@@ -311,9 +327,13 @@ var View = Backbone.View.extend({
|
||||
/** Update all available options at once */
|
||||
add: function(options, sorter) {
|
||||
_.each(this.model.get("data"), v => {
|
||||
v.keep && !_.findWhere(options, { value: v.value }) && options.push(v);
|
||||
if (v.keep && !_.findWhere(options, { value: v.value })) {
|
||||
options.push(v);
|
||||
}
|
||||
});
|
||||
sorter && options && options.sort(sorter);
|
||||
if (sorter && options) {
|
||||
options.sort(sorter);
|
||||
}
|
||||
this.model.set("data", options);
|
||||
},
|
||||
|
||||
@@ -334,7 +354,6 @@ var View = Backbone.View.extend({
|
||||
|
||||
/** Set value to dom */
|
||||
_setValue: function(new_value) {
|
||||
var self = this;
|
||||
if (new_value === null || new_value === undefined) {
|
||||
new_value = "__null__";
|
||||
}
|
||||
@@ -351,8 +370,10 @@ var View = Backbone.View.extend({
|
||||
if ($.isArray(new_value)) {
|
||||
var val = [];
|
||||
_.each(new_value, v => {
|
||||
var d = _.findWhere(self.data2, { id: v });
|
||||
d && val.push(d);
|
||||
var d = _.findWhere(this.data2, { id: v });
|
||||
if (d) {
|
||||
val.push(d);
|
||||
}
|
||||
});
|
||||
new_value = val;
|
||||
} else {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// dependencies
|
||||
import Utils from "utils/utils";
|
||||
import Ui from "mvc/ui/ui-misc";
|
||||
import Table from "mvc/ui/ui-table";
|
||||
import List from "mvc/ui/ui-list";
|
||||
|
||||
// collection of libraries
|
||||
var Libraries = Backbone.Collection.extend({
|
||||
url: `${Galaxy.root}api/libraries?deleted=false`
|
||||
@@ -85,7 +84,9 @@ var View = Backbone.View.extend({
|
||||
|
||||
// add change event. fires on trigger
|
||||
this.on("change", () => {
|
||||
options.onchange && options.onchange(self.value());
|
||||
if (options.onchange) {
|
||||
options.onchange(self.value());
|
||||
}
|
||||
});
|
||||
|
||||
// create elements
|
||||
|
||||
@@ -1,169 +1,244 @@
|
||||
/** zh localization */
|
||||
/* by steven shen */
|
||||
define({
|
||||
// ----------------------------------------------------------------------------- masthead
|
||||
"Analyze Data": "数据分析",
|
||||
Workflow: "流程",
|
||||
"Shared Data": "共享的数据",
|
||||
"Data Libraries": "数据库",
|
||||
Histories: "已发布的历史",
|
||||
Workflows: "已发布的流程",
|
||||
Visualizations: "已发布的可视化",
|
||||
Pages: "已发布的页面",
|
||||
Visualization: "可视化",
|
||||
"New Track Browser": "创建 Track Browser",
|
||||
"Saved Visualizations": "已保存的保存",
|
||||
"Interactive Environments": "交互式环境",
|
||||
Admin: "管理员",
|
||||
Help: "帮助",
|
||||
Support: "支持",
|
||||
Search: "搜索",
|
||||
"Mailing Lists": "邮件列表",
|
||||
Videos: "视频",
|
||||
Wiki: false,
|
||||
"How to Cite Galaxy": "引用",
|
||||
"Interactive Tours": "使用引导",
|
||||
User: "用户",
|
||||
Login: "登陆",
|
||||
Register: "注册",
|
||||
"Login or Register": "登陆或注册",
|
||||
"Logged in as": "您已登陆为",
|
||||
Preferences: "用户偏好性",
|
||||
"Custom Builds": "自定义构建集",
|
||||
Logout: "退出",
|
||||
"Saved Histories": "保存历史",
|
||||
"Saved Datasets": "保存数据集",
|
||||
"Saved Pages": "保存页面",
|
||||
|
||||
//Tooltip
|
||||
"Account and saved data": "账号及数据保存",
|
||||
"Account registration or login": "注册与登录",
|
||||
"Support, contact, and community": "支持,联系,社区",
|
||||
"Administer this Galaxy": "管理您的Galaxy",
|
||||
"Visualize datasets": "数据集可视化",
|
||||
"Access published resources": "访问发布的资源",
|
||||
"Chain tools into workflows": "将工具链接到工作流程中",
|
||||
"Analysis home view": "数据分析主页",
|
||||
|
||||
// ---------------------------------------------------------------------------- histories
|
||||
// ---- history/options-menu
|
||||
"History Lists": "历史列表",
|
||||
// Saved histories is defined above.
|
||||
"Saved Histories": "保存历史",
|
||||
"Histories Shared with Me": "分享给您历史",
|
||||
"Current History": "当前历史",
|
||||
"Create New": "创建新的历史",
|
||||
"Copy History": "复制历史",
|
||||
"Share or Publish": "分享或发布历史",
|
||||
"Show Structure": "展示结构",
|
||||
"Extract Workflow": "提取为工作流",
|
||||
// Delete is defined elsewhere, but is also in this menu.
|
||||
Delete: "删除",
|
||||
"Delete Permanently": "永久删除",
|
||||
"Dataset Actions": "数据操作",
|
||||
"Copy Datasets": "复制数据集",
|
||||
"Dataset Security": "数据安全",
|
||||
"Resume Paused Jobs": "恢复已暂停的任务",
|
||||
"Collapse Expanded Datasets": false,
|
||||
"Unhide Hidden Datasets": "取消隐藏的数据集",
|
||||
"Delete Hidden Datasets": "删除隐藏的数据集",
|
||||
"Purge Deleted Datasets": "清空已删除的数据集",
|
||||
Downloads: "下载",
|
||||
"Export Tool Citations": "导出工具文献引用",
|
||||
"Export History to File": "导出历史到文件",
|
||||
"Other Actions": "其他操作",
|
||||
"Import from File": "从文件导入",
|
||||
Webhooks: false,
|
||||
|
||||
// ---- history-model
|
||||
// ---- history-view
|
||||
"This history is empty": "历史已空",
|
||||
"No matching datasets found": "未找到匹配的数据集",
|
||||
//"An error occurred while getting updates from the server" :
|
||||
//false,
|
||||
//"Please contact a Galaxy administrator if the problem persists" :
|
||||
//false,
|
||||
"An error occurred while getting updates from the server": "从服务器更新出现错误",
|
||||
"Please contact a Galaxy administrator if the problem persists": "如果问题仍然存在,请联系Galaxy管理员",
|
||||
//TODO:
|
||||
//"An error was encountered while <% where %>" :
|
||||
//false,
|
||||
"Search datasets": "搜索数据集",
|
||||
"You are currently viewing a deleted history!": "正在查看已删除的历史",
|
||||
"You are over your disk quota": "您已超过磁盘配额",
|
||||
//"Tool execution is on hold until your disk usage drops below your allocated quota" :
|
||||
//false,
|
||||
All: "皆",
|
||||
"An error was encountered while <% where %>": "出现错误,当执行以下操作时: <% where %>",
|
||||
"search datasets": "搜索数据集",
|
||||
"You are currently viewing a deleted history!": "您正在查看已删除的历史记录",
|
||||
"You are over your disk quota": "您超出了您的磁盘配额",
|
||||
"Tool execution is on hold until your disk usage drops below your allocated quota":
|
||||
"工具执行处于暂停状态,直到您的磁盘使用量低于您分配的配额",
|
||||
All: "所有的",
|
||||
None: "一个也没有",
|
||||
"For all selected": "为每个选定",
|
||||
|
||||
// ---- history-view-edit
|
||||
//"Edit history tags" :
|
||||
//false,
|
||||
//"Edit history Annotation" :
|
||||
//false,
|
||||
"Edit history tags": "编辑历史标签",
|
||||
"Edit history Annotation": "编辑历史备注",
|
||||
"Click to rename history": "单击要重命名的历史",
|
||||
// multi operations
|
||||
"Operations on multiple datasets": "编辑多个数据集",
|
||||
//"Hide datasets" :
|
||||
//false,
|
||||
//"Unhide datasets" :
|
||||
//false,
|
||||
//"Delete datasets" :
|
||||
//false,
|
||||
//"Undelete datasets" :
|
||||
//false,
|
||||
"Hide datasets": "隐藏数据集",
|
||||
"Unhide datasets": "显示数据集",
|
||||
"Delete datasets": "删除数据集",
|
||||
"Undelete datasets": "取消删除数据集",
|
||||
"Permanently delete datasets": "永久删除数据集",
|
||||
"This will permanently remove the data in your datasets. Are you sure?": "这将永久在你的数据集删除数据。你确定?",
|
||||
"This will permanently remove the data in your datasets. Are you sure?": "这将永久在您的数据集删除数据。你确定?",
|
||||
|
||||
// ---- history-view-annotated
|
||||
Dataset: "数据集",
|
||||
//"Annotation" :
|
||||
//false,
|
||||
Dataset: "数据",
|
||||
Annotation: "备注",
|
||||
|
||||
// ---- history-view-edit-current
|
||||
"This history is empty. Click 'Get Data' on the left tool menu to start": "历史已空,请单击左边窗格中‘获取数据’",
|
||||
"You must be logged in to create histories": "你必须登录后才能创建历史",
|
||||
//TODO:
|
||||
//"You can <% loadYourOwn %> or <% externalSource %>" :
|
||||
"You can ": "您可以 ",
|
||||
" or ": " 或者 ",
|
||||
"load your own data": "上传您的个人数据",
|
||||
"get data from an external source": "从外部来源获取数据",
|
||||
|
||||
// these aren't in zh/ginga.po and the template doesn't localize
|
||||
//"Include Deleted Datasets" :
|
||||
//false,
|
||||
//"load your own data" :
|
||||
//false,
|
||||
//"get data from an external source" :
|
||||
//"Include Hidden Datasets" :
|
||||
//false,
|
||||
|
||||
// ---------------------------------------------------------------------------- datasets
|
||||
// ---- hda-model
|
||||
//"Unable to purge dataset" :
|
||||
//false,
|
||||
"Unable to purge dataset": "无法清除数据集",
|
||||
|
||||
// ---- hda-base
|
||||
// display button
|
||||
//"Cannot display datasets removed from disk" :
|
||||
//false,
|
||||
//"This dataset must finish uploading before it can be viewed" :
|
||||
//false,
|
||||
//"This dataset is not yet viewable" :
|
||||
//false,
|
||||
"View data": "数据",
|
||||
"Cannot display datasets removed from disk": "无法显示已从磁盘中删除的数据集",
|
||||
"This dataset must finish uploading before it can be viewed": "此数据集必须先完成上传, 然后才能查看",
|
||||
"This dataset is not yet viewable": "此数据集是不可见的",
|
||||
"View data": "查看数据",
|
||||
// download button
|
||||
Download: "下载",
|
||||
"Download dataset": "下载数据集",
|
||||
//"Additional files" :
|
||||
//false,
|
||||
"Additional files": "其他文件",
|
||||
// info/show_params
|
||||
"View details": "查看详情",
|
||||
|
||||
// dataset states
|
||||
// state: new
|
||||
//"This is a new dataset and not all of its data are available yet" :
|
||||
//false,
|
||||
"This is a new dataset and not all of its data are available yet": "这是一个新的数据集,并不是所有的数据都可用",
|
||||
// state: noPermission
|
||||
//"You do not have permission to view this dataset" :
|
||||
//false,
|
||||
"You do not have permission to view this dataset": "您无权查看此数据集",
|
||||
// state: discarded
|
||||
//"The job creating this dataset was cancelled before completion" :
|
||||
//false,
|
||||
"The job creating this dataset was cancelled before completion": "创建此数据集的任务在完成之前已被取消",
|
||||
// state: queued
|
||||
"This job is waiting to run": "等待运行的进程",
|
||||
"This job is waiting to run": "任务正在等待运行",
|
||||
// state: upload
|
||||
//"This dataset is currently uploading" :
|
||||
//false,
|
||||
"This dataset is currently uploading": "此数据集正在上传中",
|
||||
// state: setting_metadata
|
||||
//"Metadata is being auto-detected" :
|
||||
//false,
|
||||
"Metadata is being auto-detected": "元数据正在被自动检测中",
|
||||
// state: running
|
||||
"This job is currently running": "正在运行的进程",
|
||||
"This job is currently running": "任务正在运行中",
|
||||
// state: paused
|
||||
//"This job is paused. Use the \"Resume Paused Jobs\" in the history menu to resume" :
|
||||
//false,
|
||||
'This job is paused. Use the "Resume Paused Jobs" in the history menu to resume':
|
||||
'此任务已暂停。使用历史菜单中的 "恢复已暂停的工作" 来恢复',
|
||||
// state: error
|
||||
"An error occurred with this dataset": "进程运行时出错",
|
||||
"An error occurred with this dataset": "此数据集发生错误",
|
||||
// state: empty
|
||||
"No data": "没有数据",
|
||||
// state: failed_metadata
|
||||
//"An error occurred setting the metadata for this dataset" :
|
||||
//false,
|
||||
"An error occurred setting the metadata for this dataset": "设置此数据集的元数据时发生错误",
|
||||
|
||||
// ajax error prefix
|
||||
//"There was an error getting the data for this dataset" :
|
||||
//false,
|
||||
"There was an error getting the data for this dataset": "获取此数据集的数据时出错",
|
||||
|
||||
// purged'd/del'd msg
|
||||
//"This dataset has been deleted and removed from disk" :
|
||||
//false,
|
||||
"This dataset has been deleted and removed from disk": "此数据集已被删除并从磁盘中删除",
|
||||
"This dataset has been deleted": "此数据集已被删除",
|
||||
"This dataset has been hidden": "此数据集已隐藏",
|
||||
"This dataset has been hidden": "此数据集已被隐藏",
|
||||
|
||||
format: "格式",
|
||||
database: "数据库",
|
||||
|
||||
// ---- hda-edit
|
||||
"Edit attributes": "编辑属性",
|
||||
//"Cannot edit attributes of datasets removed from disk" :
|
||||
//false,
|
||||
//"Undelete dataset to edit attributes" :
|
||||
//false,
|
||||
//"This dataset must finish uploading before it can be edited" :
|
||||
//false,
|
||||
//"This dataset is not yet editable" :
|
||||
//false,
|
||||
"Cannot edit attributes of datasets removed from disk": "无法编辑已从磁盘中删除的数据集的属性",
|
||||
"Undelete dataset to edit attributes": "取消删除数据集以编辑属性",
|
||||
"This dataset must finish uploading before it can be edited": "该数据集必须先上传完成, 然后才能编辑",
|
||||
"This dataset is not yet editable": "该数据集不可编辑",
|
||||
|
||||
Delete: "删除",
|
||||
//"Dataset is already deleted" :
|
||||
//false,
|
||||
"Dataset is already deleted": "数据集已被删除",
|
||||
|
||||
"View or report this error": "报告错误",
|
||||
"View or report this error": "查看或报告此错误",
|
||||
|
||||
"Run this job again": "重新运行",
|
||||
"Run this job again": "重新运行此任务",
|
||||
|
||||
Visualize: "图形",
|
||||
//"Visualize in" :
|
||||
//false,
|
||||
Visualize: "可视化",
|
||||
"Visualize in": "的可视化",
|
||||
|
||||
"Undelete it": "反删除",
|
||||
"Undelete it": "取消删除",
|
||||
"Permanently remove it from disk": "从磁盘中永久删除",
|
||||
"Unhide it": "取消隐藏"
|
||||
"Unhide it": "取消隐藏",
|
||||
|
||||
//"You may be able to" :
|
||||
//false,
|
||||
//"set it manually or retry auto-detection" :
|
||||
//false,
|
||||
"You may be able to": "您可能可以",
|
||||
"set it manually or retry auto-detection": "手动设置或重试自动检测",
|
||||
|
||||
//"Edit dataset tags" :
|
||||
//false,
|
||||
//"Edit dataset annotation" :
|
||||
//false,
|
||||
"Edit dataset tags": "编辑数据集标签",
|
||||
"Edit dataset annotation": "编辑数据集备注",
|
||||
|
||||
"Tool Help": "工具帮助",
|
||||
|
||||
// ---------------------------------------------------------------------------- admin
|
||||
"Search Tool Shed": "搜索 Tool Shed",
|
||||
"Monitor installing repositories": "",
|
||||
"Manage installed tools": "管理已安装的工具",
|
||||
"Reset metadata": "重置元数据",
|
||||
"Download local tool": "下载本地工具",
|
||||
"Tool lineage": false,
|
||||
"Reload a tool's configuration": "重新加载工具的配置",
|
||||
"Review tool migration stages": "查看工具迁移状态",
|
||||
"View Tool Error Logs": "查看工具错误日志",
|
||||
"Manage Display Whitelist": "管理显示白名单",
|
||||
"Manage Tool Dependencies": "管理工具依赖",
|
||||
Users: "用户",
|
||||
Groups: "组别",
|
||||
"API keys": false,
|
||||
"Impersonate a user": "模拟用户",
|
||||
Data: "数据",
|
||||
Quotas: "配额",
|
||||
Roles: "角色",
|
||||
"Local data": "本地数据",
|
||||
"Form Definitions": "定义表单",
|
||||
|
||||
// ---------------------------------------------------------------------------- Scratchbook
|
||||
"Enable/Disable Scratchbook": "启用/禁用 Scratchbook",
|
||||
"Show/Hide Scratchbook": "显示/隐藏 Scratchbook",
|
||||
|
||||
// ---------------------------------------------------------------------------- misc. MVC
|
||||
//"Tags" :
|
||||
//false,
|
||||
//"Annotation" :
|
||||
//false,
|
||||
//"Edit annotation" :
|
||||
//false,
|
||||
Tags: "标签",
|
||||
"Edit annotation": "编辑备注",
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ja: true,
|
||||
fr: true,
|
||||
zh: true
|
||||
});
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
import * as mod_toastr from "libs/toastr";
|
||||
import mod_group_model from "toolshed/groups/group-model";
|
||||
|
||||
// toolshed group detail view
|
||||
const GroupDetailView = Backbone.View.extend({
|
||||
el: "#groups_element",
|
||||
options: {},
|
||||
app: null,
|
||||
|
||||
initialize: function(options) {
|
||||
this.options = _.extend(this.options, options);
|
||||
this.app = window.globalTS.groups;
|
||||
|
||||
if (this.app.collection !== null) {
|
||||
this.model = this.app.collection.get(this.options.group_id);
|
||||
this.render();
|
||||
} else {
|
||||
this.fetchGroup();
|
||||
}
|
||||
},
|
||||
|
||||
fetchGroup: function(options) {
|
||||
const that = this;
|
||||
this.options = _.extend(this.options, options);
|
||||
this.model = new mod_group_model.Group({ id: this.options.group_id });
|
||||
this.model.fetch({
|
||||
success: function(model) {
|
||||
console.log("received data: ");
|
||||
console.log(model);
|
||||
that.render();
|
||||
},
|
||||
error: function(model, response) {
|
||||
if (typeof response.responseJSON !== "undefined") {
|
||||
mod_toastr.error(response.responseJSON.err_msg);
|
||||
} else {
|
||||
mod_toastr.error("An error occurred.");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const template = this.templateRow();
|
||||
this.$el.html(template({ group: this.model }));
|
||||
$("#center [data-toggle]").tooltip();
|
||||
$("#center").css("overflow", "auto");
|
||||
},
|
||||
|
||||
templateRow: function() {
|
||||
return _.template(
|
||||
[
|
||||
"<div>",
|
||||
'<h3><%= _.escape(group.get("name")) %></h3>',
|
||||
'<p class="" style="color:gray;">',
|
||||
'A group of <%= group.get("members").length %> members with <%= group.get("repositories").length %> repositories and a total of <%= group.get("total_downloads") %> combined repository clones.</p>',
|
||||
|
||||
"<h3>Members</h3>",
|
||||
'<table class="grid table table-condensed">',
|
||||
"<thead>",
|
||||
"<th>Name</th>",
|
||||
"<th>Repositories</th>",
|
||||
"<th>Registered</th>",
|
||||
"</thead>",
|
||||
"<tbody>",
|
||||
'<% _.each(group.get("members"), function(member) { %>',
|
||||
"<tr>",
|
||||
"<td>",
|
||||
"<%= _.escape(member.username) %>",
|
||||
"</td>",
|
||||
"<td>",
|
||||
'<a data-toggle="tooltip" data-placement="top" title="Repositories of <%= _.escape(member.username) %>" href="/repository/browse_repositories_by_user?user_id=<%= member.id %>&use_panels=true" id="<%= member.id %>"><%= member.user_repos_count %></a>',
|
||||
"</td>",
|
||||
"<td>",
|
||||
"<%= member.time_created %>",
|
||||
"</td>",
|
||||
"</tr>",
|
||||
"<% }); %>",
|
||||
"</tbody>",
|
||||
"</table>",
|
||||
|
||||
"<h3>Repositories</h3>",
|
||||
'<table class="grid table table-condensed">',
|
||||
"<thead>",
|
||||
"<th>Name</th>",
|
||||
"<th>Description</th>",
|
||||
"<th>Clones</th>",
|
||||
"<th>Owner</th>",
|
||||
"<th>Categories</th>",
|
||||
"<th>Created</th>",
|
||||
"<th>Updated</th>",
|
||||
"<th>Rating</th>",
|
||||
"<th>Verified</th>",
|
||||
"</thead>",
|
||||
"<tbody>",
|
||||
'<% _.each(group.get("repositories"), function(repo) { %>',
|
||||
"<tr>",
|
||||
"<td>",
|
||||
'<a data-toggle="tooltip" data-placement="top" title="Details of <%= _.escape(repo.name) %>" href="/view/<%= _.escape(repo.owner) %>/<%= _escape(repo.name) %>" id="<%= repo.id %>"><%= _.escape(repo.name) %></a>',
|
||||
"</td>",
|
||||
"<td>",
|
||||
"<%= _.escape(repo.description) %>",
|
||||
"</td>",
|
||||
"<td>",
|
||||
"<%= repo.times_downloaded %>",
|
||||
"</td>",
|
||||
"<td>",
|
||||
"<%= _.escape(repo.owner) %>",
|
||||
"</td>",
|
||||
"<td>",
|
||||
"<% _.each((repo.categories), function(cat) { %>",
|
||||
'<a data-toggle="tooltip" data-placement="top" title="Repositories in <%= cat.name %>" href="/repository/browse_repositories_in_category?id=<%= cat.id %>&use_panels=true"><%= cat.name %></a><br/>',
|
||||
// '<%= repo.categories %>',
|
||||
"<% }); %>",
|
||||
"</td>",
|
||||
'<td data-toggle="tooltip" data-placement="top" title="<%= repo.time_created_full %>">',
|
||||
"<%= repo.time_created %>",
|
||||
"</td>",
|
||||
'<td data-toggle="tooltip" data-placement="top" title="<%= repo.time_updated_full %>">',
|
||||
"<%= repo.time_updated %>",
|
||||
"</td>",
|
||||
"<td>",
|
||||
"<%= repo.ratings_mean %>",
|
||||
"</td>",
|
||||
"<td>",
|
||||
"<%= repo.approved %>",
|
||||
"</td>",
|
||||
"</tr>",
|
||||
"<% }); %>",
|
||||
"</tbody>",
|
||||
"</table>",
|
||||
"</div>"
|
||||
].join("")
|
||||
);
|
||||
}
|
||||
});
|
||||
export default {
|
||||
GroupDetailView: GroupDetailView
|
||||
};
|
||||
@@ -0,0 +1,128 @@
|
||||
import * as mod_toastr from "libs/toastr";
|
||||
import mod_group_model from "toolshed/groups/group-model";
|
||||
import mod_group_row from "toolshed/groups/group-listrow-view";
|
||||
const GroupListView = Backbone.View.extend({
|
||||
el: "#groups_element",
|
||||
defaults: {},
|
||||
|
||||
/**
|
||||
* Initialize and fetch the groups from server.
|
||||
* Async render afterwards.
|
||||
* @param {object} options an object with options
|
||||
*/
|
||||
initialize: function(options) {
|
||||
this.options = _.defaults(this.options || {}, this.defaults, options);
|
||||
const that = this;
|
||||
window.globalTS.groups.collection = new mod_group_model.Groups();
|
||||
window.globalTS.groups.collection.fetch({
|
||||
success: function(model) {
|
||||
console.log("received data: ");
|
||||
console.log(model);
|
||||
that.render();
|
||||
},
|
||||
error: function(model, response) {
|
||||
if (typeof response.responseJSON !== "undefined") {
|
||||
mod_toastr.error(response.responseJSON.err_msg);
|
||||
} else {
|
||||
mod_toastr.error("An error occurred.");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
fetch: function() {},
|
||||
|
||||
/**
|
||||
* Render the groups table from the object's own collection.
|
||||
*/
|
||||
render: function(options) {
|
||||
this.options = _.extend(this.options, options);
|
||||
$(".tooltip").hide();
|
||||
const template = this.templateGroupsList();
|
||||
this.$el.html(template({ length: window.globalTS.groups.collection.models.length }));
|
||||
this.renderRows(window.globalTS.groups.collection.models);
|
||||
$("#center [data-toggle]").tooltip();
|
||||
$("#center").css("overflow", "auto");
|
||||
},
|
||||
|
||||
/**
|
||||
* Render all given models as rows in the groups list
|
||||
* @param {array} groups_to_render array of group models to render
|
||||
*/
|
||||
renderRows: function(groups_to_render) {
|
||||
for (let i = 0; i < groups_to_render.length; i++) {
|
||||
const group = groups_to_render[i];
|
||||
this.renderOne({ group: group });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a view for the given model and add it to the groups view.
|
||||
* @param {Group} model of the view that will be rendered
|
||||
*/
|
||||
renderOne: function(options) {
|
||||
const rowView = new mod_group_row.GroupListRowView(options);
|
||||
this.$el.find("#group_list_body").append(rowView.el);
|
||||
},
|
||||
|
||||
/**
|
||||
* Table heading was clicked, update sorting preferences and re-render.
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
// sort_clicked : function(){
|
||||
// if (Galaxy.libraries.preferences.get('sort_order') === 'asc'){
|
||||
// Galaxy.libraries.preferences.set({'sort_order': 'desc'});
|
||||
// } else {
|
||||
// Galaxy.libraries.preferences.set({'sort_order': 'asc'});
|
||||
// }
|
||||
// this.render();
|
||||
// },
|
||||
|
||||
/**
|
||||
* Sort the underlying collection according to the parameters received.
|
||||
* Currently supports only sorting by name.
|
||||
*/
|
||||
// sortLibraries: function(){
|
||||
// if (Galaxy.libraries.preferences.get('sort_by') === 'name'){
|
||||
// if (Galaxy.libraries.preferences.get('sort_order') === 'asc'){
|
||||
// this.collection.sortByNameAsc();
|
||||
// } else if (Galaxy.libraries.preferences.get('sort_order') === 'desc'){
|
||||
// this.collection.sortByNameDesc();
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
// === TEMPLATES ====
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
|
||||
templateGroupsList: function() {
|
||||
const tmpl_array = [];
|
||||
|
||||
tmpl_array.push('<div id="groups">');
|
||||
tmpl_array.push("</div>");
|
||||
tmpl_array.push('<div class="groups_container table-responsive">');
|
||||
tmpl_array.push("<% if(length === 0) { %>");
|
||||
tmpl_array.push("<div>There are no groups yet.</div>");
|
||||
tmpl_array.push("<% } else{ %>");
|
||||
tmpl_array.push('<table class="grid table table-condensed">');
|
||||
tmpl_array.push(" <thead>");
|
||||
tmpl_array.push(" <th>Name</th>");
|
||||
// tmpl_array.push(' <th style="width:22%;">description</th>');
|
||||
tmpl_array.push(" <th>Members</th> ");
|
||||
tmpl_array.push(" <th>Repositories</th>");
|
||||
tmpl_array.push(" </thead>");
|
||||
tmpl_array.push(' <tbody id="group_list_body">');
|
||||
// group item views will attach here
|
||||
tmpl_array.push(" </tbody>");
|
||||
tmpl_array.push("</table>");
|
||||
tmpl_array.push("<% }%>");
|
||||
tmpl_array.push("</div>");
|
||||
|
||||
return _.template(tmpl_array.join(""));
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
GroupListView: GroupListView
|
||||
};
|
||||
+13
-17
@@ -1,36 +1,32 @@
|
||||
define([],
|
||||
function() {
|
||||
|
||||
// toolshed group row view
|
||||
var GroupListRowView = Backbone.View.extend({
|
||||
const GroupListRowView = Backbone.View.extend({
|
||||
events: {},
|
||||
|
||||
initialize : function( options ){
|
||||
this.render( options.group );
|
||||
initialize: function(options) {
|
||||
this.render(options.group);
|
||||
},
|
||||
|
||||
render: function( group ){
|
||||
var tmpl = this.templateRow();
|
||||
this.setElement(tmpl( { group:group } ));
|
||||
render: function(group) {
|
||||
const tmpl = this.templateRow();
|
||||
this.setElement(tmpl({ group: group }));
|
||||
this.$el.show();
|
||||
return this;
|
||||
},
|
||||
|
||||
templateRow: function() {
|
||||
return _.template([
|
||||
return _.template(
|
||||
[
|
||||
'<tr class="" data-id="<%- group.get("id") %>">',
|
||||
'<td><a href="groups#/<%= group.get("id") %>"><%= _.escape(group.get("name")) %></a></td>',
|
||||
// '<td>description</td>',
|
||||
'<td><%= group.get("total_members") %></td>',
|
||||
'<td><%= group.get("total_repos") %></td>',
|
||||
'</tr>'
|
||||
].join(''));
|
||||
}
|
||||
|
||||
"</tr>"
|
||||
].join("")
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
export default {
|
||||
GroupListRowView: GroupListRowView
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
// ============================================================================
|
||||
// TS GROUP RELATED MODELS
|
||||
|
||||
const Group = Backbone.Model.extend({
|
||||
urlRoot: `${Galaxy.root}api/groups`
|
||||
});
|
||||
|
||||
const Groups = Backbone.Collection.extend({
|
||||
url: `${Galaxy.root}api/groups`,
|
||||
|
||||
model: Group
|
||||
});
|
||||
|
||||
export default {
|
||||
Group: Group,
|
||||
Groups: Groups
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// === MAIN TOOLSHED GROUP MODULE ====
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
|
||||
import mod_group_list from "toolshed/groups/group-list-view";
|
||||
import mod_group_detail from "toolshed/groups/group-detail-view";
|
||||
|
||||
// ============================================================================
|
||||
// ROUTER
|
||||
const ToolshedRouter = Backbone.Router.extend({
|
||||
routes: {
|
||||
"": "groups",
|
||||
":group_id": "group_page"
|
||||
}
|
||||
});
|
||||
|
||||
const ToolshedGroups = Backbone.View.extend({
|
||||
groupListView: null,
|
||||
groupDetailView: null,
|
||||
collection: null,
|
||||
|
||||
initialize: function() {
|
||||
window.globalTS.groups = this;
|
||||
|
||||
this.ts_router = new ToolshedRouter();
|
||||
this.ts_router.on("route:groups", () => {
|
||||
window.globalTS.groups.groupListView = new mod_group_list.GroupListView();
|
||||
});
|
||||
|
||||
this.ts_router.on("route:group_page", group_id => {
|
||||
window.globalTS.groups.groupDetailView = new mod_group_detail.GroupDetailView({
|
||||
group_id: group_id
|
||||
});
|
||||
});
|
||||
|
||||
Backbone.history.start({ pushState: false });
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
ToolshedGroups: ToolshedGroups
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import _l from "utils/localization";
|
||||
import * as _ from "libs/underscore";
|
||||
import * as d3 from "libs/d3";
|
||||
import * as d3 from "d3";
|
||||
import { event as currentEvent } from "d3";
|
||||
import visualization from "viz/visualization";
|
||||
import mod_utils from "utils/utils";
|
||||
import config from "utils/config";
|
||||
@@ -193,7 +194,6 @@ var CircsterView = Backbone.View.extend({
|
||||
tracks_start_radii = d3.range(radius_start, min_dimension / 2, dataset_arc_height + track_gap);
|
||||
|
||||
// Map from track start to bounds.
|
||||
var self = this;
|
||||
return _.map(tracks_start_radii, radius => [radius, radius + dataset_arc_height]);
|
||||
},
|
||||
|
||||
@@ -221,8 +221,8 @@ var CircsterView = Backbone.View.extend({
|
||||
.call(
|
||||
d3.behavior.zoom().on("zoom", () => {
|
||||
// Do zoom, drag.
|
||||
var scale = d3.event.scale;
|
||||
svg.attr("transform", `translate(${d3.event.translate}) scale(${scale})`);
|
||||
var scale = currentEvent.scale;
|
||||
svg.attr("transform", `translate(${currentEvent.translate}) scale(${scale})`);
|
||||
|
||||
// Propagate scale changes to views.
|
||||
if (self.scale !== scale) {
|
||||
@@ -628,7 +628,6 @@ var CircsterTrackView = Backbone.View.extend({
|
||||
* default data bounds.
|
||||
*/
|
||||
_update_data_bounds: function(new_bounds) {
|
||||
var old_bounds = this.data_bounds;
|
||||
this.data_bounds =
|
||||
new_bounds || this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));
|
||||
this._transition_chrom_data();
|
||||
@@ -962,7 +961,6 @@ var CircsterQuantitativeTrackView = CircsterTrackView.extend({
|
||||
_data_bounds_ticks_fn: function() {
|
||||
// Closure vars.
|
||||
var self = this;
|
||||
visibleChroms = 0;
|
||||
|
||||
// Return function for locating ticks based on chrom arc data.
|
||||
return (
|
||||
@@ -1101,9 +1099,9 @@ var Circster = Backbone.View.extend({
|
||||
// load css
|
||||
mod_utils.cssLoadFile("static/style/circster.css");
|
||||
// -- Configure visualization --
|
||||
var genome = new visualization.Genome(galaxy_config.app.genome);
|
||||
var genome = new visualization.Genome(window.galaxy_config.app.genome);
|
||||
|
||||
var vis = new visualization.GenomeVisualization(galaxy_config.app.viz_config);
|
||||
var vis = new visualization.GenomeVisualization(window.galaxy_config.app.viz_config);
|
||||
|
||||
// Add Circster-specific config options.
|
||||
vis.get("config").add([
|
||||
@@ -1143,7 +1141,7 @@ var Circster = Backbone.View.extend({
|
||||
|
||||
// setup title
|
||||
$("#center .unified-panel-header-inner").append(
|
||||
`${galaxy_config.app.viz_config.title} ${galaxy_config.app.viz_config.dbkey}`
|
||||
`${window.galaxy_config.app.viz_config.title} ${window.galaxy_config.app.viz_config.dbkey}`
|
||||
);
|
||||
|
||||
// setup menu
|
||||
|
||||
@@ -2,13 +2,7 @@ import _l from "utils/localization";
|
||||
/**
|
||||
* Top-level trackster code, used for creating/loading visualizations and user interface elements.
|
||||
*/
|
||||
|
||||
// global variables
|
||||
var ui = null;
|
||||
var view = null;
|
||||
var browser_router = null;
|
||||
|
||||
// trackster viewer
|
||||
//import * as $ from 'jquery';
|
||||
import * as _ from "libs/underscore";
|
||||
import tracks from "viz/trackster/tracks";
|
||||
import visualization from "viz/visualization";
|
||||
@@ -25,6 +19,12 @@ import "libs/farbtastic";
|
||||
import "libs/jquery/jquery.form";
|
||||
import "libs/jquery/jquery.rating";
|
||||
import "ui/editable-text";
|
||||
|
||||
// trackster global variables
|
||||
var ui = null;
|
||||
var view = null;
|
||||
var browser_router = null;
|
||||
|
||||
/**
|
||||
* Base Object/Model for inhertiance.
|
||||
*/
|
||||
@@ -152,7 +152,7 @@ var TracksterUI = Base.extend({
|
||||
title: _l("Bookmarks"),
|
||||
on_click: function() {
|
||||
// HACK -- use style to determine if panel is hidden and hide/show accordingly.
|
||||
force_right_panel($("div#right").css("right") == "0px" ? "hide" : "show");
|
||||
window.force_right_panel($("div#right").css("right") == "0px" ? "hide" : "show");
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -250,7 +250,7 @@ var TracksterUI = Base.extend({
|
||||
// Create view.
|
||||
var self = this;
|
||||
|
||||
var view = new tracks.TracksterView(_.extend(view_config, { header: false }));
|
||||
view = new tracks.TracksterView(_.extend(view_config, { header: false }));
|
||||
|
||||
view.editor = true;
|
||||
$.when(view.load_chroms_deferred).then(chrom_info => {
|
||||
@@ -408,10 +408,10 @@ var TracksterView = Backbone.View.extend({
|
||||
});
|
||||
|
||||
// hide right panel
|
||||
force_right_panel("hide");
|
||||
window.force_right_panel("hide");
|
||||
|
||||
// check if id is available
|
||||
if (galaxy_config.app.id) {
|
||||
if (window.galaxy_config.app.id) {
|
||||
this.view_existing();
|
||||
} else if (query_string.get("dataset_id")) {
|
||||
this.choose_existing_or_new();
|
||||
@@ -483,7 +483,7 @@ var TracksterView = Backbone.View.extend({
|
||||
// view
|
||||
view_existing: function() {
|
||||
// get config
|
||||
var viz_config = galaxy_config.app.viz_config;
|
||||
var viz_config = window.galaxy_config.app.viz_config;
|
||||
|
||||
// view
|
||||
view = ui.create_visualization(
|
||||
@@ -533,8 +533,11 @@ var TracksterView = Backbone.View.extend({
|
||||
|
||||
// select default
|
||||
var dbkeys_in_genomes = response.map(r => r[1]);
|
||||
if (galaxy_config.app.default_dbkey && _.contains(dbkeys_in_genomes, galaxy_config.app.default_dbkey)) {
|
||||
$("#new-dbkey").val(galaxy_config.app.default_dbkey);
|
||||
if (
|
||||
window.galaxy_config.app.default_dbkey &&
|
||||
_.contains(dbkeys_in_genomes, window.galaxy_config.app.default_dbkey)
|
||||
) {
|
||||
$("#new-dbkey").val(window.galaxy_config.app.default_dbkey);
|
||||
}
|
||||
|
||||
// change focus
|
||||
@@ -588,7 +591,7 @@ var TracksterView = Backbone.View.extend({
|
||||
name: name,
|
||||
dbkey: dbkey
|
||||
},
|
||||
galaxy_config.app.gene_region
|
||||
window.galaxy_config.app.gene_region
|
||||
);
|
||||
|
||||
// initialize editor
|
||||
@@ -604,9 +607,9 @@ var TracksterView = Backbone.View.extend({
|
||||
$("#center .unified-panel-title").text(`${view.config.get_value("name")} (${view.dbkey})`);
|
||||
|
||||
// add dataset
|
||||
if (galaxy_config.app.add_dataset)
|
||||
if (window.galaxy_config.app.add_dataset)
|
||||
$.ajax({
|
||||
url: `${Galaxy.root}api/datasets/${galaxy_config.app.add_dataset}`,
|
||||
url: `${Galaxy.root}api/datasets/${window.galaxy_config.app.add_dataset}`,
|
||||
data: { hda_ldda: "hda", data_type: "track_config" },
|
||||
dataType: "json",
|
||||
success: function(track_data) {
|
||||
|
||||
@@ -221,7 +221,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
span.nametags {
|
||||
div.nametags {
|
||||
max-height:26px;
|
||||
overflow-y: auto;
|
||||
span.label {
|
||||
display: inline-block;
|
||||
margin-right: 2px;
|
||||
@@ -698,4 +700,4 @@
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ th.button_heading{
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
.toolbar-item{
|
||||
margin-left: 1em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
#libraries_element, #folder_items_element{
|
||||
@@ -112,7 +112,7 @@ th.button_heading{
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
.help-button{
|
||||
.right-float{
|
||||
float: right;
|
||||
}
|
||||
.pagination-sm{
|
||||
@@ -128,11 +128,6 @@ th.button_heading{
|
||||
.libimport-select-all{
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.library-modal-item{
|
||||
width:90%;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
.paginator-bottom{
|
||||
width: 27em;
|
||||
margin-left: auto;
|
||||
@@ -143,60 +138,26 @@ th.button_heading{
|
||||
}
|
||||
|
||||
// Extra style for Galaxy modal
|
||||
.modal-content #selected_history_content{
|
||||
ul{
|
||||
list-style-type: none;
|
||||
.modal-content{
|
||||
.library_selected_history_content{
|
||||
ul{
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
.library-collection-type-select, .library-collection-history-select{
|
||||
margin-left:auto;
|
||||
margin-right:auto;
|
||||
width:200px;
|
||||
min-width:200px;
|
||||
}
|
||||
.library-modal-item{
|
||||
width:90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
// Follows the style for the deprecated admin libraries interface
|
||||
#library-grid{
|
||||
ul{
|
||||
list-style: none;
|
||||
}
|
||||
span.expandLink{
|
||||
padding-left: 12px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background: url(../images/silk/resultset_next.png) no-repeat;
|
||||
}
|
||||
.folderRow.expanded span.expandLink{
|
||||
background: url(../images/silk/resultset_bottom.png) no-repeat;
|
||||
}
|
||||
.folderRow span.rowIcon{
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background: url(../images/silk/folder.png);
|
||||
}
|
||||
.libraryItem-error{
|
||||
margin-right: 2px;
|
||||
padding: 0 2px 0 2px;
|
||||
border: 1px solid @state-danger-border;
|
||||
background: @state-danger-bg;
|
||||
}
|
||||
.libraryItem-queued{
|
||||
margin-right: 2px;
|
||||
padding: 0 2px 0 2px;
|
||||
border: 1px solid @state-default-border;
|
||||
background: @state-default-bg;
|
||||
}
|
||||
.libraryItem-running{
|
||||
margin-right: 2px;
|
||||
padding: 0 2px 0 2px;
|
||||
border: 1px solid @state-running-border;
|
||||
background: @state-running-bg;
|
||||
}
|
||||
.libraryItem-upload{
|
||||
margin-right: 2px;
|
||||
padding: 0 2px 0 2px;
|
||||
border: 1px solid @state-upload-border;
|
||||
background: @state-upload-bg;
|
||||
}
|
||||
}
|
||||
.libraryTitle{
|
||||
th{
|
||||
text-align: left;
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Grunt task to fetch third-party libraries using bower and copy them to the proper location in client/.
|
||||
* @param {Object} grunt main grunt file
|
||||
* @return {Function} callback to build this task
|
||||
*/
|
||||
module.exports = function( grunt ){
|
||||
"use strict";
|
||||
|
||||
var dev_path = './galaxy/scripts',
|
||||
|
||||
// where to move fetched bower components into the build structure (libName: [ bower-location, libs-location ])
|
||||
libraryLocations = {
|
||||
'farbtastic': [ 'src/farbtastic.js', 'farbtastic.js' ],
|
||||
'bootstrap-tour': [ 'build/js/bootstrap-tour.js', 'bootstrap-tour.js' ],
|
||||
|
||||
// these need to be updated and tested
|
||||
//'jquery-form': [ 'jquery.form.js', 'jquery/jquery.form.js' ],
|
||||
//'jquery-autocomplete': [ 'src/jquery.autocomplete.js', 'jquery/jquery.autocomplete.js' ],
|
||||
//'select2': [ 'select2.js', 'jquery/select2.js' ],
|
||||
//'jStorage': [ 'jstorage.js', 'jquery/jstorage.js' ],
|
||||
//'dynatree': [ 'dist/jquery.dynatree.js', 'jquery/jquery.dynatree.js' ],
|
||||
//'jquery.event.drag-drop': [
|
||||
// [ 'event.drag/jquery.event.drag.js', 'jquery/jquery.event.drag.js' ],
|
||||
// [ 'event.drag/jquery.event.drop.js', 'jquery/jquery.event.drop.js' ]
|
||||
//],
|
||||
|
||||
// these are complicated by additional css/less
|
||||
//'toastr': [ 'toastr.js', 'toastr.js' ],
|
||||
//'wymeditor': [ 'dist/wymeditor/jquery.wymeditor.js', 'jquery/jquery.wymeditor.js' ],
|
||||
//'jstree': [ 'jstree.js', 'jquery/jstree.js' ],
|
||||
|
||||
// these have been customized by Galaxy
|
||||
//'bootstrap': [ 'dist/js/bootstrap.js', 'bootstrap.js' ],
|
||||
//'jquery-ui': [
|
||||
// // multiple components now
|
||||
// [ '', 'jquery/jquery-ui.js' ]
|
||||
//],
|
||||
|
||||
};
|
||||
|
||||
// call bower to install libraries and other external resources
|
||||
grunt.config( 'bower-install-simple', {
|
||||
options: {
|
||||
color: true
|
||||
},
|
||||
"prod": {
|
||||
options: {
|
||||
production: true
|
||||
}
|
||||
},
|
||||
"dev": {
|
||||
options: {
|
||||
production: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/** copy external libraries from bower components to scripts/libs */
|
||||
function copyLibs(){
|
||||
var lib_path = dev_path + '/libs/';
|
||||
for( var libName in libraryLocations ){
|
||||
if( libraryLocations.hasOwnProperty( libName ) ){
|
||||
|
||||
var bower_dir = 'bower_components',
|
||||
location = libraryLocations[ libName ],
|
||||
source = [ bower_dir, libName, location[0] ].join( '/' ),
|
||||
destination = lib_path + location[1];
|
||||
|
||||
grunt.log.writeln( source + ' -> ' + destination );
|
||||
grunt.file.copy( source, destination );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grunt.loadNpmTasks( 'grunt-bower-install-simple' );
|
||||
|
||||
grunt.registerTask( 'copy-libs', 'copy external libraries to src', copyLibs );
|
||||
grunt.registerTask( 'install-libs', 'fetch external libraries and copy to src',
|
||||
[ 'bower-install-simple:prod', 'copy-libs' ] );
|
||||
};
|
||||
@@ -1,123 +0,0 @@
|
||||
/**
|
||||
* Grunt task to compress/bundle static/scripts.
|
||||
* @param {Object} grunt main grunt file
|
||||
* @return {Function} callback to build this task
|
||||
*/
|
||||
module.exports = function( grunt ){
|
||||
"use strict";
|
||||
|
||||
var app = grunt.config.get( 'app' ),
|
||||
paths = grunt.config.get( 'paths' ),
|
||||
// uglify settings used when scripts are decompressed/not-minified
|
||||
decompressedSettings = {
|
||||
mangle : false,
|
||||
beautify : true,
|
||||
compress : {
|
||||
drop_debugger : false
|
||||
}
|
||||
},
|
||||
// uglify settings used when scripts are compressed/minified
|
||||
compressedSettings = {
|
||||
mangle : {
|
||||
screw_ie8 : true
|
||||
},
|
||||
compress : {
|
||||
// high compression options
|
||||
screw_ie8 : true,
|
||||
sequences: true,
|
||||
dead_code : true,
|
||||
drop_debugger : true,
|
||||
comparisons : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
}
|
||||
};
|
||||
|
||||
grunt.config( 'uglify', {
|
||||
target : {
|
||||
files: [{
|
||||
expand : true,
|
||||
cwd : paths.srcSymlink,
|
||||
// NOTE: do not use uglify in the apps dir (webpack will do that section)
|
||||
src : [ '**/*.js', '!apps/**/*.js' ],
|
||||
// src : '**/*.js',
|
||||
dest : paths.dist
|
||||
}],
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (grunt.option( 'develop' )){
|
||||
grunt.config( 'uglify.options', decompressedSettings );
|
||||
} else {
|
||||
grunt.config( 'uglify.target.options', {
|
||||
sourceMap : true,
|
||||
sourceMapName : function( path ){
|
||||
// rewrite name to have all source maps in 'static/maps'
|
||||
return path.replace( paths.dist, paths.maps ) + '.map';
|
||||
}
|
||||
});
|
||||
grunt.config( 'uglify.options', compressedSettings );
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- decompress for easier debugging
|
||||
grunt.registerTask( 'decompress', function(){
|
||||
grunt.log.writeln( "decompressing... (don't forget to call 'grunt' again before committing)" );
|
||||
grunt.config( 'uglify.options', decompressedSettings );
|
||||
grunt.config( 'uglify.target.options', {});
|
||||
grunt.task.run( 'uglify' );
|
||||
});
|
||||
// alias for symmetry
|
||||
grunt.registerTask( 'compress', [ 'uglify' ] );
|
||||
|
||||
// -------------------------------------------------------------------------- watch & copy,pack only those changed
|
||||
// use 'grunt watch' (from a new tab in your terminal) to have grunt re-copy changed files automatically
|
||||
grunt.config( 'watch', {
|
||||
watch: {
|
||||
// watch for changes in the src dir
|
||||
// NOTE: but not in the apps dir (which is only used by webpack)
|
||||
files: [ paths.srcSymlink + '/**', '!' + paths.srcSymlink + '/apps/**' ],
|
||||
tasks: [ 'uglify' ],
|
||||
options: {
|
||||
spawn: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// outer scope variable for the event handler and onChange fn - begin with empty hash
|
||||
var changedFiles = Object.create(null);
|
||||
|
||||
// when files are changed, set the copy src and packScripts target to the filenames of the updated files
|
||||
var onChange = grunt.util._.debounce(function() {
|
||||
grunt.log.writeln( 'onChange, changedFiles:', Object.keys( changedFiles ) );
|
||||
grunt.config( 'uglify.target.files', [{
|
||||
expand : true,
|
||||
cwd : paths.srcSymlink,
|
||||
src : Object.keys( changedFiles ),
|
||||
dest : paths.dist
|
||||
}]);
|
||||
changedFiles = Object.create(null);
|
||||
}, 200);
|
||||
|
||||
var addChangedFile = function( action, filepath ) {
|
||||
// store each filepath in a Files obj, the debounced fn above will use it as an aggregate list for copying
|
||||
// we need to take galaxy/scripts out of the filepath or it will be copied to the wrong loc
|
||||
filepath = filepath.replace( paths.srcSymlink + '/', '' );
|
||||
// grunt.log.writeln( 'on.watch, filepath:', filepath );
|
||||
changedFiles[ filepath ] = action;
|
||||
onChange();
|
||||
};
|
||||
grunt.event.on( 'watch', addChangedFile );
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
grunt.loadNpmTasks( 'grunt-contrib-watch' );
|
||||
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
|
||||
};
|
||||
@@ -1,146 +0,0 @@
|
||||
define([
|
||||
"libs/toastr",
|
||||
"toolshed/scripts/mvc/groups/group-model"
|
||||
],
|
||||
function(
|
||||
mod_toastr,
|
||||
mod_group_model
|
||||
) {
|
||||
|
||||
// toolshed group detail view
|
||||
var GroupDetailView = Backbone.View.extend({
|
||||
el: "#groups_element",
|
||||
options: {},
|
||||
app: null,
|
||||
|
||||
initialize : function( options ){
|
||||
this.options = _.extend( this.options, options );
|
||||
this.app = window.globalTS.groups;
|
||||
|
||||
if ( this.app.collection !== null ){
|
||||
this.model = this.app.collection.get( this.options.group_id );
|
||||
this.render();
|
||||
} else {
|
||||
this.fetchGroup();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
fetchGroup: function( options ){
|
||||
var that = this;
|
||||
this.options = _.extend( this.options, options );
|
||||
this.model = new mod_group_model.Group( { id: this.options.group_id } );
|
||||
this.model.fetch({
|
||||
success: function( model ){
|
||||
console.log( 'received data: ' );
|
||||
console.log( model );
|
||||
that.render();
|
||||
},
|
||||
error: function( model, response ){
|
||||
if ( typeof response.responseJSON !== "undefined" ){
|
||||
mod_toastr.error( response.responseJSON.err_msg );
|
||||
} else {
|
||||
mod_toastr.error( 'An error occurred.' );
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function(){
|
||||
var template = this.templateRow();
|
||||
this.$el.html( template( { group: this.model } ) );
|
||||
$( "#center [data-toggle]" ).tooltip();
|
||||
$( "#center" ).css( 'overflow','auto' );
|
||||
},
|
||||
|
||||
templateRow: function() {
|
||||
return _.template([
|
||||
'<div>',
|
||||
'<h3><%= _.escape(group.get("name")) %></h3>',
|
||||
'<p class="" style="color:gray;">',
|
||||
'A group of <%= group.get("members").length %> members with <%= group.get("repositories").length %> repositories and a total of <%= group.get("total_downloads") %> combined repository clones.</p>',
|
||||
|
||||
'<h3>Members</h3>',
|
||||
'<table class="grid table table-condensed">',
|
||||
'<thead>',
|
||||
'<th>Name</th>',
|
||||
'<th>Repositories</th>',
|
||||
'<th>Registered</th>',
|
||||
'</thead>',
|
||||
'<tbody>',
|
||||
'<% _.each(group.get("members"), function(member) { %>',
|
||||
'<tr>',
|
||||
'<td>',
|
||||
'<%= _.escape(member.username) %>',
|
||||
'</td>',
|
||||
'<td>',
|
||||
'<a data-toggle="tooltip" data-placement="top" title="Repositories of <%= _.escape(member.username) %>" href="/repository/browse_repositories_by_user?user_id=<%= member.id %>&use_panels=true" id="<%= member.id %>"><%= member.user_repos_count %></a>',
|
||||
'</td>',
|
||||
'<td>',
|
||||
'<%= member.time_created %>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<% }); %>',
|
||||
'</tbody>',
|
||||
'</table>',
|
||||
|
||||
'<h3>Repositories</h3>',
|
||||
'<table class="grid table table-condensed">',
|
||||
'<thead>',
|
||||
'<th>Name</th>',
|
||||
'<th>Description</th>',
|
||||
'<th>Clones</th>',
|
||||
'<th>Owner</th>',
|
||||
'<th>Categories</th>',
|
||||
'<th>Created</th>',
|
||||
'<th>Updated</th>',
|
||||
'<th>Rating</th>',
|
||||
'<th>Verified</th>',
|
||||
'</thead>',
|
||||
'<tbody>',
|
||||
'<% _.each(group.get("repositories"), function(repo) { %>',
|
||||
'<tr>',
|
||||
'<td>',
|
||||
'<a data-toggle="tooltip" data-placement="top" title="Details of <%= _.escape(repo.name) %>" href="/view/<%= _.escape(repo.owner) %>/<%= _escape(repo.name) %>" id="<%= repo.id %>"><%= _.escape(repo.name) %></a>',
|
||||
'</td>',
|
||||
'<td>',
|
||||
'<%= _.escape(repo.description) %>',
|
||||
'</td>',
|
||||
'<td>',
|
||||
'<%= repo.times_downloaded %>',
|
||||
'</td>',
|
||||
'<td>',
|
||||
'<%= _.escape(repo.owner) %>',
|
||||
'</td>',
|
||||
'<td>',
|
||||
'<% _.each((repo.categories), function(cat) { %>',
|
||||
'<a data-toggle="tooltip" data-placement="top" title="Repositories in <%= cat.name %>" href="/repository/browse_repositories_in_category?id=<%= cat.id %>&use_panels=true"><%= cat.name %></a><br/>',
|
||||
// '<%= repo.categories %>',
|
||||
'<% }); %>',
|
||||
'</td>',
|
||||
'<td data-toggle="tooltip" data-placement="top" title="<%= repo.time_created_full %>">',
|
||||
'<%= repo.time_created %>',
|
||||
'</td>',
|
||||
'<td data-toggle="tooltip" data-placement="top" title="<%= repo.time_updated_full %>">',
|
||||
'<%= repo.time_updated %>',
|
||||
'</td>',
|
||||
'<td>',
|
||||
'<%= repo.ratings_mean %>',
|
||||
'</td>',
|
||||
'<td>',
|
||||
'<%= repo.approved %>',
|
||||
'</td>',
|
||||
'</tr>',
|
||||
'<% }); %>',
|
||||
'</tbody>',
|
||||
'</table>',
|
||||
'</div>'
|
||||
].join(''));
|
||||
}
|
||||
});
|
||||
return {
|
||||
GroupDetailView: GroupDetailView
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
define([
|
||||
"libs/toastr",
|
||||
"toolshed/scripts/mvc/groups/group-model",
|
||||
"toolshed/scripts/mvc/groups/group-listrow-view"
|
||||
|
||||
], function(
|
||||
mod_toastr,
|
||||
mod_group_model,
|
||||
mod_group_row
|
||||
){
|
||||
|
||||
var GroupListView = Backbone.View.extend({
|
||||
el: '#groups_element',
|
||||
defaults: {},
|
||||
|
||||
/**
|
||||
* Initialize and fetch the groups from server.
|
||||
* Async render afterwards.
|
||||
* @param {object} options an object with options
|
||||
*/
|
||||
initialize : function( options ){
|
||||
this.options = _.defaults( this.options || {}, this.defaults, options );
|
||||
var that = this;
|
||||
window.globalTS.groups.collection = new mod_group_model.Groups();
|
||||
window.globalTS.groups.collection.fetch({
|
||||
success: function( model ){
|
||||
console.log( 'received data: ' );
|
||||
console.log( model );
|
||||
that.render();
|
||||
},
|
||||
error: function( model, response ){
|
||||
if ( typeof response.responseJSON !== "undefined" ){
|
||||
mod_toastr.error( response.responseJSON.err_msg );
|
||||
} else {
|
||||
mod_toastr.error( 'An error occurred.' );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
fetch: function(){
|
||||
},
|
||||
|
||||
/**
|
||||
* Render the groups table from the object's own collection.
|
||||
*/
|
||||
render: function ( options ) {
|
||||
this.options = _.extend( this.options, options );
|
||||
$( ".tooltip" ).hide();
|
||||
var template = this.templateGroupsList();
|
||||
this.$el.html( template( { length: window.globalTS.groups.collection.models.length } ) );
|
||||
this.renderRows( window.globalTS.groups.collection.models );
|
||||
$( "#center [data-toggle]" ).tooltip();
|
||||
$( "#center" ).css( 'overflow','auto' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Render all given models as rows in the groups list
|
||||
* @param {array} groups_to_render array of group models to render
|
||||
*/
|
||||
renderRows: function( groups_to_render ){
|
||||
for ( var i = 0; i < groups_to_render.length; i++ ) {
|
||||
var group = groups_to_render[i];
|
||||
this.renderOne( { group: group } )
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a view for the given model and add it to the groups view.
|
||||
* @param {Group} model of the view that will be rendered
|
||||
*/
|
||||
renderOne: function( options ){
|
||||
var rowView = new mod_group_row.GroupListRowView( options );
|
||||
this.$el.find( '#group_list_body' ).append( rowView.el );
|
||||
},
|
||||
|
||||
/**
|
||||
* Table heading was clicked, update sorting preferences and re-render.
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
// sort_clicked : function(){
|
||||
// if (Galaxy.libraries.preferences.get('sort_order') === 'asc'){
|
||||
// Galaxy.libraries.preferences.set({'sort_order': 'desc'});
|
||||
// } else {
|
||||
// Galaxy.libraries.preferences.set({'sort_order': 'asc'});
|
||||
// }
|
||||
// this.render();
|
||||
// },
|
||||
|
||||
/**
|
||||
* Sort the underlying collection according to the parameters received.
|
||||
* Currently supports only sorting by name.
|
||||
*/
|
||||
// sortLibraries: function(){
|
||||
// if (Galaxy.libraries.preferences.get('sort_by') === 'name'){
|
||||
// if (Galaxy.libraries.preferences.get('sort_order') === 'asc'){
|
||||
// this.collection.sortByNameAsc();
|
||||
// } else if (Galaxy.libraries.preferences.get('sort_order') === 'desc'){
|
||||
// this.collection.sortByNameDesc();
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
// === TEMPLATES ====
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
|
||||
templateGroupsList: function(){
|
||||
var tmpl_array = [];
|
||||
|
||||
tmpl_array.push('<div id="groups">');
|
||||
tmpl_array.push('</div>');
|
||||
tmpl_array.push('<div class="groups_container table-responsive">');
|
||||
tmpl_array.push('<% if(length === 0) { %>');
|
||||
tmpl_array.push('<div>There are no groups yet.</div>');
|
||||
tmpl_array.push('<% } else{ %>');
|
||||
tmpl_array.push('<table class="grid table table-condensed">');
|
||||
tmpl_array.push(' <thead>');
|
||||
tmpl_array.push(' <th>Name</th>');
|
||||
// tmpl_array.push(' <th style="width:22%;">description</th>');
|
||||
tmpl_array.push(' <th>Members</th> ');
|
||||
tmpl_array.push(' <th>Repositories</th>');
|
||||
tmpl_array.push(' </thead>');
|
||||
tmpl_array.push(' <tbody id="group_list_body">');
|
||||
// group item views will attach here
|
||||
tmpl_array.push(' </tbody>');
|
||||
tmpl_array.push('</table>');
|
||||
tmpl_array.push('<% }%>');
|
||||
tmpl_array.push('</div>');
|
||||
|
||||
return _.template(tmpl_array.join(''));
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
return {
|
||||
GroupListView: GroupListView
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
define([], function() {
|
||||
|
||||
// ============================================================================
|
||||
// TS GROUP RELATED MODELS
|
||||
|
||||
var Group = Backbone.Model.extend({
|
||||
urlRoot: Galaxy.root + 'api/groups',
|
||||
});
|
||||
|
||||
var Groups = Backbone.Collection.extend({
|
||||
url: Galaxy.root + 'api/groups',
|
||||
|
||||
model: Group,
|
||||
|
||||
});
|
||||
|
||||
return {
|
||||
Group: Group,
|
||||
Groups: Groups
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,51 +0,0 @@
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
// === MAIN TOOLSHED GROUP MODULE ====
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
|
||||
define([
|
||||
'toolshed/scripts/mvc/groups/group-list-view',
|
||||
'toolshed/scripts/mvc/groups/group-detail-view',
|
||||
'toolshed/scripts/mvc/groups/group-model'
|
||||
],
|
||||
function(
|
||||
mod_group_list,
|
||||
mod_group_detail,
|
||||
mod_group_model
|
||||
) {
|
||||
|
||||
// ============================================================================
|
||||
// ROUTER
|
||||
var ToolshedRouter = Backbone.Router.extend({
|
||||
routes: {
|
||||
"" : "groups",
|
||||
":group_id" : "group_page"
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var ToolshedGroups = Backbone.View.extend({
|
||||
groupListView: null,
|
||||
groupDetailView: null,
|
||||
collection: null,
|
||||
|
||||
initialize : function(){
|
||||
window.globalTS.groups = this;
|
||||
|
||||
this.ts_router = new ToolshedRouter();
|
||||
this.ts_router.on( 'route:groups', function() {
|
||||
window.globalTS.groups.groupListView = new mod_group_list.GroupListView();
|
||||
});
|
||||
|
||||
this.ts_router.on( 'route:group_page', function( group_id ) {
|
||||
window.globalTS.groups.groupDetailView = new mod_group_detail.GroupDetailView( { group_id: group_id } );
|
||||
});
|
||||
|
||||
Backbone.history.start({pushState: false});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
ToolshedGroups: ToolshedGroups
|
||||
};
|
||||
|
||||
});
|
||||
@@ -920,6 +920,11 @@ use_interactive = True
|
||||
# create symlinks to them).
|
||||
#user_library_import_symlink_whitelist = None
|
||||
|
||||
# In conjunction or alternatively, Galaxy can restrict user library imports to
|
||||
# those files that the user can read (by checking basic unix permissions).
|
||||
# For this to work, the username has to match the username on the filesystem.
|
||||
#user_library_import_check_permissions = False
|
||||
|
||||
# Allow admins to paste filesystem paths during upload. For libraries this
|
||||
# adds an option to the admin library upload tool allowing admins to paste
|
||||
# filesystem paths to files and directories in a box, and these paths will be
|
||||
|
||||
@@ -8,6 +8,11 @@ import os.path
|
||||
from markupsafe import escape
|
||||
|
||||
from galaxy import util
|
||||
from galaxy.exceptions import (
|
||||
AdminRequiredException,
|
||||
ConfigDoesNotAllowException,
|
||||
RequestParameterInvalidException,
|
||||
)
|
||||
from galaxy.tools.actions import upload_common
|
||||
from galaxy.tools.parameters import populate_state
|
||||
from galaxy.util.path import (
|
||||
@@ -19,6 +24,47 @@ from galaxy.util.path import (
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def validate_server_directory_upload(trans, server_dir):
|
||||
if server_dir in [None, 'None', '']:
|
||||
raise RequestParameterInvalidException("Invalid or unspecified server_dir parameter")
|
||||
|
||||
if trans.user_is_admin():
|
||||
import_dir = trans.app.config.library_import_dir
|
||||
import_dir_desc = 'library_import_dir'
|
||||
if not import_dir:
|
||||
raise ConfigDoesNotAllowException('"library_import_dir" is not set in the Galaxy configuration')
|
||||
else:
|
||||
import_dir = trans.app.config.user_library_import_dir
|
||||
if not import_dir:
|
||||
raise ConfigDoesNotAllowException('"user_library_import_dir" is not set in the Galaxy configuration')
|
||||
if server_dir != trans.user.email:
|
||||
import_dir = os.path.join(import_dir, trans.user.email)
|
||||
import_dir_desc = 'user_library_import_dir'
|
||||
|
||||
full_dir = os.path.join(import_dir, server_dir)
|
||||
unsafe = None
|
||||
if safe_relpath(server_dir):
|
||||
username = trans.user.username if trans.app.config.user_library_import_check_permissions else None
|
||||
if import_dir_desc == 'user_library_import_dir' and safe_contains(import_dir, full_dir, whitelist=trans.app.config.user_library_import_symlink_whitelist, username=username):
|
||||
for unsafe in unsafe_walk(full_dir, whitelist=[import_dir] + trans.app.config.user_library_import_symlink_whitelist):
|
||||
log.error('User attempted to import a path that resolves to a path outside of their import dir: %s -> %s', unsafe, os.path.realpath(unsafe))
|
||||
else:
|
||||
log.error('User attempted to import a directory path that resolves to a path outside of their import dir: %s -> %s', server_dir, os.path.realpath(full_dir))
|
||||
unsafe = True
|
||||
if unsafe:
|
||||
raise RequestParameterInvalidException("Invalid server_dir specified")
|
||||
|
||||
return full_dir, import_dir_desc
|
||||
|
||||
|
||||
def validate_path_upload(trans):
|
||||
if not trans.app.config.allow_library_path_paste:
|
||||
raise ConfigDoesNotAllowException('"allow_path_paste" is not set to True in the Galaxy configuration file')
|
||||
|
||||
if not trans.user_is_admin():
|
||||
raise AdminRequiredException('Uploading files via filesystem paths can only be performed by administrators')
|
||||
|
||||
|
||||
class LibraryActions(object):
|
||||
"""
|
||||
Mixin for controllers that provide library functionality.
|
||||
@@ -42,37 +88,11 @@ class LibraryActions(object):
|
||||
upload_option = kwd.get('upload_option', 'upload_file')
|
||||
response_code = 200
|
||||
if upload_option == 'upload_directory':
|
||||
if server_dir in [None, 'None', '']:
|
||||
response_code = 400
|
||||
if trans.user_is_admin():
|
||||
import_dir = trans.app.config.library_import_dir
|
||||
import_dir_desc = 'library_import_dir'
|
||||
else:
|
||||
import_dir = trans.app.config.user_library_import_dir
|
||||
if server_dir != trans.user.email:
|
||||
import_dir = os.path.join(import_dir, trans.user.email)
|
||||
import_dir_desc = 'user_library_import_dir'
|
||||
full_dir = os.path.join(import_dir, server_dir)
|
||||
unsafe = None
|
||||
if safe_relpath(server_dir):
|
||||
if import_dir_desc == 'user_library_import_dir' and safe_contains(import_dir, full_dir, whitelist=trans.app.config.user_library_import_symlink_whitelist):
|
||||
for unsafe in unsafe_walk(full_dir, whitelist=[import_dir] + trans.app.config.user_library_import_symlink_whitelist):
|
||||
log.error('User attempted to import a path that resolves to a path outside of their import dir: %s -> %s', unsafe, os.path.realpath(unsafe))
|
||||
else:
|
||||
log.error('User attempted to import a directory path that resolves to a path outside of their import dir: %s -> %s', server_dir, os.path.realpath(full_dir))
|
||||
unsafe = True
|
||||
if unsafe:
|
||||
response_code = 403
|
||||
message = 'Invalid server_dir'
|
||||
if import_dir:
|
||||
message = 'Select a directory'
|
||||
else:
|
||||
response_code = 403
|
||||
message = '"%s" is not defined in the Galaxy configuration file' % import_dir_desc
|
||||
full_dir, import_dir_desc = validate_server_directory_upload(trans, server_dir)
|
||||
message = 'Select a directory'
|
||||
elif upload_option == 'upload_paths':
|
||||
if not trans.app.config.allow_library_path_paste:
|
||||
response_code = 403
|
||||
message = '"allow_library_path_paste" is not defined in the Galaxy configuration file'
|
||||
# Library API already checked this - following check isn't actually needed.
|
||||
validate_path_upload(trans)
|
||||
# Some error handling should be added to this method.
|
||||
try:
|
||||
# FIXME: instead of passing params here ( which have been processed by util.Params(), the original kwd
|
||||
@@ -118,6 +138,43 @@ class LibraryActions(object):
|
||||
uploaded_datasets.append(self._make_library_uploaded_dataset(trans, params, name, file, 'server_dir', library_bunch))
|
||||
return uploaded_datasets, 200, None
|
||||
|
||||
def _get_server_dir_files(self, params, full_dir, import_dir_desc):
|
||||
files = []
|
||||
try:
|
||||
for entry in os.listdir(full_dir):
|
||||
# Only import regular files
|
||||
path = os.path.join(full_dir, entry)
|
||||
link_data_only = params.get('link_data_only', 'copy_files')
|
||||
if os.path.islink(full_dir) and link_data_only == 'link_to_files':
|
||||
# If we're linking instead of copying and the
|
||||
# sub-"directory" in the import dir is actually a symlink,
|
||||
# dereference the symlink, but not any of its contents.
|
||||
link_path = os.readlink(full_dir)
|
||||
if os.path.isabs(link_path):
|
||||
path = os.path.join(link_path, entry)
|
||||
else:
|
||||
path = os.path.abspath(os.path.join(link_path, entry))
|
||||
elif os.path.islink(path) and os.path.isfile(path) and link_data_only == 'link_to_files':
|
||||
# If we're linking instead of copying and the "file" in the
|
||||
# sub-directory of the import dir is actually a symlink,
|
||||
# dereference the symlink (one dereference only, Vasili).
|
||||
link_path = os.readlink(path)
|
||||
if os.path.isabs(link_path):
|
||||
path = link_path
|
||||
else:
|
||||
path = os.path.abspath(os.path.join(os.path.dirname(path), link_path))
|
||||
if os.path.isfile(path):
|
||||
files.append(path)
|
||||
except Exception as e:
|
||||
message = "Unable to get file list for configured %s, error: %s" % (import_dir_desc, str(e))
|
||||
response_code = 500
|
||||
return None, response_code, message
|
||||
if not files:
|
||||
message = "The directory '%s' contains no valid files" % full_dir
|
||||
response_code = 400
|
||||
return None, response_code, message
|
||||
return files, None, None
|
||||
|
||||
def _get_path_paste_uploaded_datasets(self, trans, params, library_bunch, response_code, message):
|
||||
preserve_dirs = util.string_as_bool(params.get('preserve_dirs', False))
|
||||
uploaded_datasets = []
|
||||
|
||||
@@ -426,6 +426,7 @@ class Configuration(object):
|
||||
self.library_import_dir = kwargs.get('library_import_dir', None)
|
||||
self.user_library_import_dir = kwargs.get('user_library_import_dir', None)
|
||||
self.user_library_import_symlink_whitelist = listify(kwargs.get('user_library_import_symlink_whitelist', []), do_strip=True)
|
||||
self.user_library_import_check_permissions = string_as_bool(kwargs.get('user_library_import_check_permissions', False))
|
||||
# Searching data libraries
|
||||
self.ftp_upload_dir = kwargs.get('ftp_upload_dir', None)
|
||||
self.ftp_upload_dir_identifier = kwargs.get('ftp_upload_dir_identifier', 'email') # attribute on user - email, username, id, etc...
|
||||
|
||||
@@ -530,7 +530,7 @@ def build_isolated_environment(
|
||||
# - https://github.com/galaxyproject/galaxy/issues/3635
|
||||
# - https://github.com/conda/conda/issues/2035
|
||||
offline_works = (conda_context.conda_version < LooseVersion("4.3")) or \
|
||||
(conda_context.conda_version >= LooseVersion("4.3.18"))
|
||||
(conda_context.conda_version >= LooseVersion("4.4"))
|
||||
if offline_works:
|
||||
create_args.extend(["--offline"])
|
||||
else:
|
||||
|
||||
@@ -4,16 +4,20 @@ from __future__ import absolute_import
|
||||
|
||||
import errno
|
||||
import imp
|
||||
import logging
|
||||
from functools import partial
|
||||
from grp import getgrgid
|
||||
from itertools import starmap
|
||||
from operator import getitem
|
||||
from os import (
|
||||
extsep,
|
||||
makedirs,
|
||||
walk,
|
||||
stat,
|
||||
walk
|
||||
)
|
||||
from os.path import (
|
||||
abspath,
|
||||
dirname,
|
||||
exists,
|
||||
isabs,
|
||||
join,
|
||||
@@ -21,10 +25,13 @@ from os.path import (
|
||||
pardir,
|
||||
realpath,
|
||||
relpath,
|
||||
sep as separator,
|
||||
)
|
||||
from pwd import getpwuid
|
||||
|
||||
from six import iteritems, string_types
|
||||
from six.moves import filterfalse, map, zip
|
||||
from six.moves import map, zip
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def safe_contains(prefix, path, whitelist=None):
|
||||
@@ -82,7 +89,7 @@ def safe_relpath(path):
|
||||
return not (isabs(path) or normpath(path).startswith(pardir))
|
||||
|
||||
|
||||
def unsafe_walk(path, whitelist=None):
|
||||
def unsafe_walk(path, whitelist=None, username=None):
|
||||
"""Walk a path and ensure that none of its contents are symlinks outside the path.
|
||||
|
||||
It is assumed that ``path`` itself has already been validated e.g. with :func:`safe_relpath` or
|
||||
@@ -92,10 +99,72 @@ def unsafe_walk(path, whitelist=None):
|
||||
:param path: a directory to check for unsafe contents
|
||||
:type whitelist: list of strings
|
||||
:param whitelist: list of additional paths under which contents may be located
|
||||
:rtype: iterator
|
||||
:returns: Iterator of "bad" files found under ``path``
|
||||
:rtype: list of strings
|
||||
:returns: A list of "bad" files found under ``path``
|
||||
"""
|
||||
return filterfalse(partial(safe_contains, path, whitelist=whitelist), __walk(abspath(path)))
|
||||
unsafe_paths = []
|
||||
for walked_path in __walk(abspath(path)):
|
||||
is_safe = safe_contains(path, walked_path, whitelist=whitelist)
|
||||
if username and is_safe:
|
||||
is_safe = full_path_permission_for_user(path, walked_path, username=username, skip_prefix=True)
|
||||
if not is_safe:
|
||||
unsafe_paths.append(walked_path)
|
||||
return unsafe_paths
|
||||
|
||||
|
||||
def __path_permission_for_user(path, username):
|
||||
"""
|
||||
:type path: string
|
||||
:param path: a directory or file to check
|
||||
:type username: string
|
||||
:param username: a username matching the systems username
|
||||
"""
|
||||
group_id_of_file = stat(path).st_gid
|
||||
file_owner = getpwuid(stat(path).st_uid)
|
||||
group_members = getgrgid(group_id_of_file).gr_mem
|
||||
|
||||
oct_mode = oct(stat(path).st_mode)
|
||||
owner_permissions = int(oct_mode[-3])
|
||||
group_permissions = int(oct_mode[-2])
|
||||
other_permissions = int(oct_mode[-1])
|
||||
if other_permissions >= 4 or \
|
||||
(file_owner == username and owner_permissions >= 4) or \
|
||||
(username in group_members and group_permissions >= 4):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def full_path_permission_for_user(prefix, path, username, skip_prefix=False):
|
||||
"""
|
||||
Assuming username is identical to the os username, this checks that the
|
||||
given user can read the specified path by checking the file permission
|
||||
and each parent directory permission.
|
||||
|
||||
:type prefix: string
|
||||
:param prefix: a directory under which ``path`` is to be checked
|
||||
:type path: string
|
||||
:param path: a filename to check
|
||||
:type username: string
|
||||
:param username: a username matching the systems username
|
||||
:type skip_prefix: bool
|
||||
:param skip_prefix: skip the given prefix from being checked for permissions
|
||||
|
||||
"""
|
||||
full_path = realpath(join(prefix, path))
|
||||
top_path = realpath(prefix) if skip_prefix else None
|
||||
can_read = __path_permission_for_user(full_path, username)
|
||||
if can_read:
|
||||
depth = 0
|
||||
max_depth = full_path.count(separator)
|
||||
parent_path = dirname(full_path)
|
||||
while can_read and depth != max_depth:
|
||||
if parent_path in [separator, top_path]:
|
||||
break
|
||||
if not __path_permission_for_user(parent_path, username):
|
||||
can_read = False
|
||||
depth += 1
|
||||
parent_path = dirname(parent_path)
|
||||
return can_read
|
||||
|
||||
|
||||
def joinext(root, ext):
|
||||
|
||||
@@ -12,9 +12,8 @@ from galaxy import (
|
||||
exceptions,
|
||||
managers,
|
||||
util,
|
||||
web
|
||||
)
|
||||
from galaxy.actions.library import LibraryActions
|
||||
from galaxy.actions.library import LibraryActions, validate_path_upload
|
||||
from galaxy.managers.collections_util import (
|
||||
api_payload_to_create_params,
|
||||
dictify_dataset_collection_instance
|
||||
@@ -158,7 +157,7 @@ class LibraryContentsController(BaseAPIController, UsesLibraryMixin, UsesLibrary
|
||||
rval['parent_library_id'] = trans.security.encode_id(rval['parent_library_id'])
|
||||
return rval
|
||||
|
||||
@web.expose_api
|
||||
@expose_api
|
||||
def create(self, trans, library_id, payload, **kwd):
|
||||
"""
|
||||
create( self, trans, library_id, payload, **kwd )
|
||||
@@ -314,12 +313,8 @@ class LibraryContentsController(BaseAPIController, UsesLibraryMixin, UsesLibrary
|
||||
if folder and last_used_build in ['None', None, '?']:
|
||||
last_used_build = folder.genome_build
|
||||
error = False
|
||||
if upload_option == 'upload_paths' and not trans.app.config.allow_library_path_paste:
|
||||
error = True
|
||||
message = '"allow_library_path_paste" is not defined in the Galaxy configuration file'
|
||||
elif upload_option == 'upload_paths' and not is_admin:
|
||||
error = True
|
||||
message = 'Uploading files via filesystem paths can only be performed by administrators'
|
||||
if upload_option == 'upload_paths':
|
||||
validate_path_upload(trans) # Duplicate check made in _upload_dataset.
|
||||
elif upload_option not in ('upload_file', 'upload_directory', 'upload_paths'):
|
||||
error = True
|
||||
message = 'Invalid upload_option'
|
||||
@@ -373,7 +368,7 @@ class LibraryContentsController(BaseAPIController, UsesLibraryMixin, UsesLibrary
|
||||
# for cross type comparisions, ie "True" == True
|
||||
yield prefix, ("%s" % (meta)).encode("utf8", errors='replace')
|
||||
|
||||
@web.expose_api
|
||||
@expose_api
|
||||
def update(self, trans, id, library_id, payload, **kwd):
|
||||
"""
|
||||
update( self, trans, id, library_id, payload, **kwd )
|
||||
@@ -411,7 +406,7 @@ class LibraryContentsController(BaseAPIController, UsesLibraryMixin, UsesLibrary
|
||||
else:
|
||||
raise HTTPBadRequest('Malformed library content id ( %s ) specified, unable to decode.' % str(content_id))
|
||||
|
||||
@web.expose_api
|
||||
@expose_api
|
||||
def delete(self, trans, library_id, id, **kwd):
|
||||
"""
|
||||
delete( self, trans, library_id, id, **kwd )
|
||||
|
||||
@@ -25,7 +25,7 @@ from galaxy.managers import (
|
||||
)
|
||||
from galaxy.tools.actions import upload_common
|
||||
from galaxy.tools.parameters import populate_state
|
||||
from galaxy.util.path import safe_contains, safe_relpath, unsafe_walk
|
||||
from galaxy.util.path import full_path_permission_for_user, safe_contains, safe_relpath, unsafe_walk
|
||||
from galaxy.util.streamball import StreamBall
|
||||
from galaxy.web import (
|
||||
_future_expose_api as expose_api,
|
||||
@@ -432,20 +432,30 @@ class LibraryDatasetsController(BaseAPIController, UsesVisualizationMixin, Libra
|
||||
path = os.path.join(import_base_dir, path)
|
||||
elif source in ['userdir_file', 'userdir_folder']:
|
||||
unsafe = None
|
||||
username = trans.user.username if trans.app.config.user_library_import_check_permissions else None
|
||||
user_login = trans.user.email
|
||||
user_base_dir = trans.app.config.user_library_import_dir
|
||||
if user_base_dir is None:
|
||||
raise exceptions.ConfigDoesNotAllowException('The configuration of this Galaxy instance does not allow upload from user directories.')
|
||||
full_dir = os.path.join(user_base_dir, user_login)
|
||||
|
||||
if not safe_contains(full_dir, path, whitelist=trans.app.config.user_library_import_symlink_whitelist):
|
||||
# the path is a symlink outside the user dir
|
||||
path = os.path.join(full_dir, path)
|
||||
log.error('User attempted to import a path that resolves to a path outside of their import dir: %s -> %s', path, os.path.realpath(path))
|
||||
raise exceptions.RequestParameterInvalidException('The given path is invalid.')
|
||||
if trans.app.config.user_library_import_check_permissions and not full_path_permission_for_user(full_dir, path, username):
|
||||
log.error('User attempted to import a path that resolves to a path outside of their import dir: '
|
||||
'%s -> %s and cannot be read by them.', path, os.path.realpath(path))
|
||||
raise exceptions.RequestParameterInvalidException('The given path is invalid.')
|
||||
path = os.path.join(full_dir, path)
|
||||
for unsafe in unsafe_walk(path, whitelist=[full_dir] + trans.app.config.user_library_import_symlink_whitelist):
|
||||
for unsafe in unsafe_walk(path, whitelist=[full_dir] + trans.app.config.user_library_import_symlink_whitelist, username=username):
|
||||
# the path is a dir and contains files that symlink outside the user dir
|
||||
log.error('User attempted to import a directory containing a path that resolves to a path outside of their import dir: %s -> %s', unsafe, os.path.realpath(unsafe))
|
||||
error = 'User attempted to import a path that resolves to a path outside of their import dir: %s -> %s', \
|
||||
path, os.path.realpath(path)
|
||||
if trans.app.config.user_library_import_check_permissions:
|
||||
error += ' or is not readable for them.'
|
||||
log.error(error)
|
||||
if unsafe:
|
||||
raise exceptions.RequestParameterInvalidException('The given path is invalid.')
|
||||
if not os.path.exists(path):
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
define("galaxy",["exports","libs/underscore","libs/backbone","mvc/base-mvc","mvc/user/user-model","utils/metrics-logger","utils/add-logging","utils/localization"],function(e,t,o,a,r,n,l,i){"use strict";function g(e){return e&&e.__esModule?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t.default=e,t}function c(e,t){return this._init(e||{},t||{})}Object.defineProperty(e,"__esModule",{value:!0});var u=s(t),p=s(o),f=g(a),d=g(r),y=g(n),b=g(l),v=g(i);(0,b.default)(c,"GalaxyApp");var m="galaxy:debug:namespaces",_=!1;try{_="true"==localStorage.getItem("galaxy:debug")}catch(e){console.log((0,v.default)("localStorage not available for debug flag retrieval"))}c.prototype._init=function(e,t){var o=this;return u.extend(o,p.Events),_&&(o.logger=console,console.debug("debugging galaxy:","options:",e,"bootstrapped:",t)),o._processOptions(e),o.root=e.root||"/",o.params=e.params||{},o.session_csrf_token=e.session_csrf_token||null,o._initConfig(e.config||{}),o._patchGalaxy(window.Galaxy),o._initLogger(o.options.loggerOptions||{}),o.debug("GalaxyApp.options: ",o.options),o.debug("GalaxyApp.config: ",o.config),o.debug("GalaxyApp.logger: ",o.logger),o._initLocale(),o.debug("GalaxyApp.localize: ",o.localize),o.config=e.config||{},o.debug("GalaxyApp.config: ",o.config),o._initUser(e.user||{}),o.debug("GalaxyApp.user: ",o.user),o._setUpListeners(),o.trigger("ready",o),o},c.prototype.defaultOptions={patchExisting:!0,root:"/",session_csrf_token:null},c.prototype._processOptions=function(e){var t=this,o=t.defaultOptions;t.options={};for(var a in o)o.hasOwnProperty(a)&&(t.options[a]=e.hasOwnProperty(a)?e[a]:o[a]);return t},c.prototype._initConfig=function(e){var t=this;return t.config=e,t.config.debug=_||t.config.debug,t},c.prototype._patchGalaxy=function(e){var t=this;if(t.options.patchExisting&&e)for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])},c.prototype._initLogger=function(e){var t=this;if(t.config.debug){e.consoleLogger=e.consoleLogger||console,e.consoleLevel=e.consoleLevel||y.default.MetricsLogger.ALL;try{e.consoleNamespaceWhitelist=localStorage.getItem(m).split(",")}catch(e){}try{e.consoleFlattenMessages="true"==localStorage.getItem("galaxy:debug:flatten")}catch(e){}console.log(e.consoleFlattenMessages)}return t.logger=new y.default.MetricsLogger(e),t.emit={},["log","debug","info","warn","error","metric"].map(function(e){t.emit[e]=function(o){t.logger.emit(e,arguments[0],Array.prototype.slice.call(arguments,1))}}),t.config.debug&&(f.default.LoggableMixin.logger=t.logger),t},c.prototype._initLocale=function(e){var t=this;return t.debug("_initLocale:",e),t.localize=v.default,window._l=t.localize,t},c.prototype._initUser=function(e){var t=this;return t.debug("_initUser:",e),t.user=new d.default.User(e),t.user.logger=t.logger,t},c.prototype._setUpListeners=function(){var e=this;return e.lastAjax={},$(document).bind("ajaxSend",function(t,o,a){var r=a.data;try{r=JSON.parse(r)}catch(e){}e.lastAjax={url:location.href.slice(0,-1)+a.url,data:r}}),e},c.prototype.debugging=function(e){var t=this;try{if(void 0===e)return"true"===localStorage.getItem("galaxy:debug");if(e)return localStorage.setItem("galaxy:debug",!0),!0;localStorage.removeItem("galaxy:debug"),t.debuggingNamespaces(null)}catch(e){console.log((0,v.default)("localStorage not available for debug flag retrieval"))}return!1},c.prototype.debuggingNamespaces=function(e){var t=this;try{if(void 0===e){var o=localStorage.getItem(m);return"string"==typeof o?o.split(","):[]}null===e?localStorage.removeItem(m):localStorage.setItem(m,e);var a=t.debuggingNamespaces();return t.logger&&(t.logger.options.consoleNamespaceWhitelist=a),a}catch(e){console.log((0,v.default)("localStorage not available for debug namespace retrieval"))}},c.prototype.toString=function(){return"GalaxyApp("+(this.user?this.user.get("email")||"(anonymous)":"uninitialized")+")"},e.default={GalaxyApp:c}});
|
||||
define("galaxy",["exports","libs/underscore","libs/backbone","mvc/base-mvc","mvc/user/user-model","utils/metrics-logger","utils/add-logging","utils/localization"],function(e,t,o,a,r,n,l,i){"use strict";function g(e){return e&&e.__esModule?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t.default=e,t}function c(e,t){return this._init(e||{},t||{})}Object.defineProperty(e,"__esModule",{value:!0});var u=s(t),p=s(o),f=g(a),d=g(r),y=g(n),b=g(l),v=g(i);(0,b.default)(c,"GalaxyApp");var m="galaxy:debug:namespaces",_=!1;try{_="true"==localStorage.getItem("galaxy:debug")}catch(e){console.log((0,v.default)("localStorage not available for debug flag retrieval"))}c.prototype._init=function(e,t){var o=this;return u.extend(o,p.Events),_&&(o.logger=console,console.debug("debugging galaxy:","options:",e,"bootstrapped:",t)),o._processOptions(e),o.root=e.root||"/",o.params=e.params||{},o.session_csrf_token=e.session_csrf_token||null,o._initConfig(e.config||{}),o._patchGalaxy(window.Galaxy),o._initLogger(o.options.loggerOptions||{}),o.debug("GalaxyApp.options: ",o.options),o.debug("GalaxyApp.config: ",o.config),o.debug("GalaxyApp.logger: ",o.logger),o._initLocale(),o.debug("GalaxyApp.localize: ",o.localize),o.config=e.config||{},o.debug("GalaxyApp.config: ",o.config),o._initUser(e.user||{}),o.debug("GalaxyApp.user: ",o.user),o._setUpListeners(),o.trigger("ready",o),o},c.prototype.defaultOptions={patchExisting:!0,root:"/",session_csrf_token:null},c.prototype._processOptions=function(e){var t=this,o=t.defaultOptions;t.options={};for(var a in o)o.hasOwnProperty(a)&&(t.options[a]=e.hasOwnProperty(a)?e[a]:o[a]);return t},c.prototype._initConfig=function(e){var t=this;return t.config=e,t.config.debug=_||t.config.debug,t},c.prototype._patchGalaxy=function(e){var t=this;if(t.options.patchExisting&&e)for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])},c.prototype._initLogger=function(e){var t=this;if(t.config.debug){e.consoleLogger=e.consoleLogger||console,e.consoleLevel=e.consoleLevel||y.default.MetricsLogger.ALL;try{e.consoleNamespaceWhitelist=localStorage.getItem(m).split(",")}catch(e){}try{e.consoleFlattenMessages="true"==localStorage.getItem("galaxy:debug:flatten")}catch(e){}console.log(e.consoleFlattenMessages)}return t.logger=new y.default.MetricsLogger(e),t.emit={},["log","debug","info","warn","error","metric"].map(function(e){t.emit[e]=function(o){t.logger.emit(e,arguments[0],Array.prototype.slice.call(arguments,1))}}),t.config.debug&&(f.default.LoggableMixin.logger=t.logger),t},c.prototype._initLocale=function(e){var t=this;return t.debug("_initLocale:",e),t.localize=v.default,window._l=t.localize,t},c.prototype._initUser=function(e){var t=this;return t.debug("_initUser:",e),t.user=new d.default.User(e),t.user.logger=t.logger,t},c.prototype._setUpListeners=function(){var e=this;return e.lastAjax={},$(document).bind("ajaxSend",function(t,o,a){var r=a.data;try{r=JSON.parse(r)}catch(e){}e.lastAjax={url:location.href.slice(0,-1)+a.url,data:r}}),e},c.prototype.debugging=function(e){var t=this;try{if(void 0===e)return"true"===localStorage.getItem("galaxy:debug");if(e)return localStorage.setItem("galaxy:debug",!0),!0;localStorage.removeItem("galaxy:debug"),t.debuggingNamespaces(null)}catch(e){console.log((0,v.default)("localStorage not available for debug flag retrieval"))}return!1},c.prototype.debuggingNamespaces=function(e){var t=this;try{if(void 0===e){var o=localStorage.getItem(m);return"string"==typeof o?o.split(","):[]}null===e?localStorage.removeItem(m):localStorage.setItem(m,e);var a=t.debuggingNamespaces();return t.logger&&(t.logger.options.consoleNamespaceWhitelist=a),a}catch(e){console.log((0,v.default)("localStorage not available for debug namespace retrieval"))}},c.prototype.toString=function(){return"GalaxyApp("+(this.user?this.user.get("email")||"(anonymous)":"uninitialized")+")"},window.Galaxy=window.Galaxy||new c,e.default={GalaxyApp:c}});
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
define("layout/router",["exports","jquery","utils/query-string-parsing","mvc/ui/ui-misc"],function(e,t,i,a){"use strict";function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0});var u=s(t),n=s(i),r=s(a),o=u.default,c=Backbone.Router.extend({initialize:function(e,t){this.page=e,this.options=t},push:function(e,t){(t=t||{}).__identifer=Math.random().toString(36).substr(2),o.isEmptyObject(t)||(e+=-1==e.indexOf("?")?"?":"&",e+=o.param(t,!0)),Galaxy.params=t,this.navigate(e,{trigger:!0})},execute:function(e,t,i){Galaxy.debug("router execute:",e,t,i);var a=n.default.parse(t.pop());t.push(a),e&&(this.authenticate(t,i)?e.apply(this,t):this.access_denied())},authenticate:function(e,t){return!0},access_denied:function(){this.page.display(new r.default.Message({status:"danger",message:"You must be logged in with proper credentials to make this request.",persistent:!0}))}});e.default=c});
|
||||
define("layout/router",["exports","jquery","utils/query-string-parsing","mvc/ui/ui-misc"],function(e,t,i,a){"use strict";function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0});var u=s(t),n=s(i),r=s(a),o=u.default,d=Backbone.Router.extend({initialize:function(e,t){this.page=e,this.options=t},push:function(e,t){(t=t||{}).__identifer=Math.random().toString(36).substr(2),e+=-1==e.indexOf("?")?"?":"&",e+=o.param(t,!0),Galaxy.params=t,this.navigate(e,{trigger:!0})},execute:function(e,t,i){Galaxy.debug("router execute:",e,t,i);var a=n.default.parse(t.pop());t.push(a),e&&(this.authenticate(t,i)?e.apply(this,t):this.access_denied())},authenticate:function(e,t){return!0},access_denied:function(){this.page.display(new r.default.Message({status:"danger",message:"You must be logged in with proper credentials to make this request.",persistent:!0}))}});e.default=d});
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
define("mvc/history/history-item-li",["exports"],function(e){"use strict";function n(e){return 0==e.indexOf("name:")?'<span class="label label-info">'+_.escape(e.slice(5))+"</span>":""}Object.defineProperty(e,"__esModule",{value:!0}),e.default={nametagTemplate:function(e){return'<span class="nametags">'+_.sortBy(_.uniq(e.tags)).map(n).join("")+"</span>"}}});
|
||||
define("mvc/history/history-item-li",["exports"],function(e){"use strict";function n(e){return'<span class="label label-info">'+_.escape(e.slice(5))+"</span>"}Object.defineProperty(e,"__esModule",{value:!0}),e.default={nametagTemplate:function(e){var t=_.filter(_.uniq(e.tags),function(e){return 0===e.indexOf("name:")}),a=_.sortBy(t).map(n);return'\n <div class="nametags" title="'+t.length+' nametags">\n '+a.join("")+"\n </div>"}}});
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
define("mvc/ui/ui-modal",["exports"],function(t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=t.View=Backbone.View.extend({className:"ui-modal",optionsDefault:{container:"body",title:"ui-modal",cls:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null,title_separator:!0},buttonList:{},initialize:function(t){this.options=_.defaults(t||{},this.optionsDefault),$(this.options.container).prepend(this.el),t&&this.render()},show:function(t){if(t&&(this.options=_.defaults(t,this.optionsDefault),this.render()),!this.visible&&(this.visible=!0,this.$el.fadeIn("fast"),this.options.closing_events)){var i=this;$(document).on("keyup.ui-modal",function(t){27==t.keyCode&&i.hide(!0)}),this.$backdrop.on("click",function(){i.hide(!0)})}},hide:function(t){this.visible=!1,this.$el.fadeOut("fast"),this.options.closing_callback&&this.options.closing_callback(t),$(document).off("keyup.ui-modal"),this.$backdrop.off("click")},render:function(){var t=this;if(this.$el.html(this._template()),this.$header=this.$(".modal-header"),this.$dialog=this.$(".modal-dialog"),this.$body=this.$(".modal-body"),this.$footer=this.$(".modal-footer"),this.$backdrop=this.$(".modal-backdrop"),this.$buttons=this.$(".buttons"),"progress"==this.options.body&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"/></div>')),this.$el.removeClass().addClass("modal").addClass(this.options.cls),this.$header.find(".title").html(this.options.title),this.$body.html(this.options.body),this.$buttons.empty(),this.buttonList={},this.options.buttons){var i=0;$.each(this.options.buttons,function(s,o){var e=$("<button/>").attr("id","button-"+i++).text(s).click(o);t.$buttons.append(e).append(" "),t.buttonList[s]=e})}else this.$footer.hide();this.$backdrop[this.options.backdrop&&"addClass"||"removeClass"]("in"),this.$header[!this.options.title_separator&&"addClass"||"removeClass"]("no-separator"),this.$body.removeAttr("style"),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width)},getButton:function(t){return this.buttonList[t]},enableButton:function(t){this.getButton(t).prop("disabled",!1)},disableButton:function(t){this.getButton(t).prop("disabled",!0)},showButton:function(t){this.getButton(t).show()},hideButton:function(t){this.getButton(t).hide()},scrollTop:function(){return this.$body.scrollTop()},_template:function(){return'<div class="modal-backdrop fade"/><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h4 class="title"/></div><div class="modal-body"/><div class="modal-footer"><div class="buttons"/></div></div></div>'}});t.default={View:i}});
|
||||
define("mvc/ui/ui-modal",["exports"],function(t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=t.View=Backbone.View.extend({className:"ui-modal",optionsDefault:{container:"body",title:"ui-modal",cls:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null,title_separator:!0},buttonList:{},initialize:function(t){this.options=_.defaults(t||{},this.optionsDefault),$(this.options.container).prepend(this.el),t&&this.render()},show:function(t){var i=this;t&&(this.options=_.defaults(t,this.optionsDefault),this.render()),this.visible||(this.visible=!0,this.$el.fadeIn("fast")),this.options.closing_events&&($(document).on("keyup.ui-modal",function(t){27==t.keyCode&&i.hide(!0)}),this.$backdrop.on("click",function(){i.hide(!0)}))},hide:function(t){this.visible=!1,this.$el.fadeOut("fast"),this.options.closing_callback&&this.options.closing_callback(t),$(document).off("keyup.ui-modal"),this.$backdrop.off("click")},render:function(){var t=this;if(this.$el.html(this._template()),this.$header=this.$(".modal-header"),this.$dialog=this.$(".modal-dialog"),this.$body=this.$(".modal-body"),this.$footer=this.$(".modal-footer"),this.$backdrop=this.$(".modal-backdrop"),this.$buttons=this.$(".buttons"),"progress"==this.options.body&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"/></div>')),this.$el.removeClass().addClass("modal").addClass(this.options.cls),this.$header.find(".title").html(this.options.title),this.$body.html(this.options.body),this.$buttons.empty(),this.buttonList={},this.options.buttons){var i=0;$.each(this.options.buttons,function(s,o){var e=$("<button/>").attr("id","button-"+i++).text(s).click(o);t.$buttons.append(e).append(" "),t.buttonList[s]=e})}else this.$footer.hide();this.$backdrop[this.options.backdrop&&"addClass"||"removeClass"]("in"),this.$header[!this.options.title_separator&&"addClass"||"removeClass"]("no-separator"),this.$body.removeAttr("style"),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width)},getButton:function(t){return this.buttonList[t]},enableButton:function(t){this.getButton(t).prop("disabled",!1)},disableButton:function(t){this.getButton(t).prop("disabled",!0)},showButton:function(t){this.getButton(t).show()},hideButton:function(t){this.getButton(t).hide()},scrollTop:function(){return this.$body.scrollTop()},_template:function(){return'<div class="modal-backdrop fade"/><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h4 class="title"/></div><div class="modal-body"/><div class="modal-footer"><div class="buttons"/></div></div></div>'}});t.default={View:i}});
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
define("mvc/ui/ui-select-library",["exports","utils/utils","mvc/ui/ui-misc","mvc/ui/ui-table","mvc/ui/ui-list"],function(e,t,i,a,l){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0});n(t);var s=n(i),r=(n(a),n(l)),c=Backbone.Collection.extend({url:Galaxy.root+"api/libraries?deleted=false"}),o=Backbone.Collection.extend({initialize:function(){var e=this;this.config=new Backbone.Model({library_id:null}),this.config.on("change",function(){e.fetch({reset:!0})})},url:function(){return Galaxy.root+"api/libraries/"+this.config.get("library_id")+"/contents"}}),u=Backbone.View.extend({initialize:function(e){var t=this;this.libraries=new c,this.datasets=new o,this.options=e,this.library_select=new s.default.Select.View({onchange:function(e){t.datasets.config.set("library_id",e)}}),this.dataset_list=new r.default.View({name:"dataset",optional:e.optional,multiple:e.multiple,onchange:function(){t.trigger("change")}}),this.libraries.on("reset",function(){var e=[];t.libraries.each(function(t){e.push({value:t.id,label:t.get("name")})}),t.library_select.update(e)}),this.datasets.on("reset",function(){var e=[];null!==t.library_select.text()&&t.datasets.each(function(t){"file"===t.get("type")&&e.push({value:t.id,label:t.get("name")})}),t.dataset_list.update(e)}),this.on("change",function(){e.onchange&&e.onchange(t.value())}),this.setElement(this._template()),this.$(".library-select").append(this.library_select.$el),this.$el.append(this.dataset_list.$el),this.libraries.fetch({reset:!0,success:function(){t.library_select.trigger("change"),void 0!==t.options.value&&t.value(t.options.value)}})},value:function(e){return this.dataset_list.value(e)},_template:function(){return'<div class="ui-select-library"><div class="library ui-margin-bottom"><span class="library-title">Select Library</span><span class="library-select"/></div></div>'}});e.default={View:u}});
|
||||
define("mvc/ui/ui-select-library",["exports","mvc/ui/ui-misc","mvc/ui/ui-list"],function(e,t,i){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(t),l=a(i),s=Backbone.Collection.extend({url:Galaxy.root+"api/libraries?deleted=false"}),r=Backbone.Collection.extend({initialize:function(){var e=this;this.config=new Backbone.Model({library_id:null}),this.config.on("change",function(){e.fetch({reset:!0})})},url:function(){return Galaxy.root+"api/libraries/"+this.config.get("library_id")+"/contents"}}),c=Backbone.View.extend({initialize:function(e){var t=this;this.libraries=new s,this.datasets=new r,this.options=e,this.library_select=new n.default.Select.View({onchange:function(e){t.datasets.config.set("library_id",e)}}),this.dataset_list=new l.default.View({name:"dataset",optional:e.optional,multiple:e.multiple,onchange:function(){t.trigger("change")}}),this.libraries.on("reset",function(){var e=[];t.libraries.each(function(t){e.push({value:t.id,label:t.get("name")})}),t.library_select.update(e)}),this.datasets.on("reset",function(){var e=[];null!==t.library_select.text()&&t.datasets.each(function(t){"file"===t.get("type")&&e.push({value:t.id,label:t.get("name")})}),t.dataset_list.update(e)}),this.on("change",function(){e.onchange&&e.onchange(t.value())}),this.setElement(this._template()),this.$(".library-select").append(this.library_select.$el),this.$el.append(this.dataset_list.$el),this.libraries.fetch({reset:!0,success:function(){t.library_select.trigger("change"),void 0!==t.options.value&&t.value(t.options.value)}})},value:function(e){return this.dataset_list.value(e)},_template:function(){return'<div class="ui-select-library"><div class="library ui-margin-bottom"><span class="library-title">Select Library</span><span class="library-select"/></div></div>'}});e.default={View:c}});
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
define("toolshed/groups/group-detail-view",["exports","libs/toastr","toolshed/groups/group-model"],function(e,t,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t.default=e,t}(t),i=function(e){return e&&e.__esModule?e:{default:e}}(o),a=Backbone.View.extend({el:"#groups_element",options:{},app:null,initialize:function(e){this.options=_.extend(this.options,e),this.app=window.globalTS.groups,null!==this.app.collection?(this.model=this.app.collection.get(this.options.group_id),this.render()):this.fetchGroup()},fetchGroup:function(e){var t=this;this.options=_.extend(this.options,e),this.model=new i.default.Group({id:this.options.group_id}),this.model.fetch({success:function(e){console.log("received data: "),console.log(e),t.render()},error:function(e,t){void 0!==t.responseJSON?r.error(t.responseJSON.err_msg):r.error("An error occurred.")}})},render:function(){var e=this.templateRow();this.$el.html(e({group:this.model})),$("#center [data-toggle]").tooltip(),$("#center").css("overflow","auto")},templateRow:function(){return _.template(["<div>",'<h3><%= _.escape(group.get("name")) %></h3>','<p class="" style="color:gray;">','A group of <%= group.get("members").length %> members with <%= group.get("repositories").length %> repositories and a total of <%= group.get("total_downloads") %> combined repository clones.</p>',"<h3>Members</h3>",'<table class="grid table table-condensed">',"<thead>","<th>Name</th>","<th>Repositories</th>","<th>Registered</th>","</thead>","<tbody>",'<% _.each(group.get("members"), function(member) { %>',"<tr>","<td>","<%= _.escape(member.username) %>","</td>","<td>",'<a data-toggle="tooltip" data-placement="top" title="Repositories of <%= _.escape(member.username) %>" href="/repository/browse_repositories_by_user?user_id=<%= member.id %>&use_panels=true" id="<%= member.id %>"><%= member.user_repos_count %></a>',"</td>","<td>","<%= member.time_created %>","</td>","</tr>","<% }); %>","</tbody>","</table>","<h3>Repositories</h3>",'<table class="grid table table-condensed">',"<thead>","<th>Name</th>","<th>Description</th>","<th>Clones</th>","<th>Owner</th>","<th>Categories</th>","<th>Created</th>","<th>Updated</th>","<th>Rating</th>","<th>Verified</th>","</thead>","<tbody>",'<% _.each(group.get("repositories"), function(repo) { %>',"<tr>","<td>",'<a data-toggle="tooltip" data-placement="top" title="Details of <%= _.escape(repo.name) %>" href="/view/<%= _.escape(repo.owner) %>/<%= _escape(repo.name) %>" id="<%= repo.id %>"><%= _.escape(repo.name) %></a>',"</td>","<td>","<%= _.escape(repo.description) %>","</td>","<td>","<%= repo.times_downloaded %>","</td>","<td>","<%= _.escape(repo.owner) %>","</td>","<td>","<% _.each((repo.categories), function(cat) { %>",'<a data-toggle="tooltip" data-placement="top" title="Repositories in <%= cat.name %>" href="/repository/browse_repositories_in_category?id=<%= cat.id %>&use_panels=true"><%= cat.name %></a><br/>',"<% }); %>","</td>",'<td data-toggle="tooltip" data-placement="top" title="<%= repo.time_created_full %>">',"<%= repo.time_created %>","</td>",'<td data-toggle="tooltip" data-placement="top" title="<%= repo.time_updated_full %>">',"<%= repo.time_updated %>","</td>","<td>","<%= repo.ratings_mean %>","</td>","<td>","<%= repo.approved %>","</td>","</tr>","<% }); %>","</tbody>","</table>","</div>"].join(""))}});e.default={GroupDetailView:a}});
|
||||
@@ -0,0 +1 @@
|
||||
define("toolshed/groups/group-list-view",["exports","libs/toastr","toolshed/groups/group-model","toolshed/groups/group-listrow-view"],function(e,o,t,s){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0});var i=function(e){if(e&&e.__esModule)return e;var o={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(o[t]=e[t]);return o.default=e,o}(o),n=r(t),l=r(s),u=Backbone.View.extend({el:"#groups_element",defaults:{},initialize:function(e){this.options=_.defaults(this.options||{},this.defaults,e);var o=this;window.globalTS.groups.collection=new n.default.Groups,window.globalTS.groups.collection.fetch({success:function(e){console.log("received data: "),console.log(e),o.render()},error:function(e,o){void 0!==o.responseJSON?i.error(o.responseJSON.err_msg):i.error("An error occurred.")}})},fetch:function(){},render:function(e){this.options=_.extend(this.options,e),$(".tooltip").hide();var o=this.templateGroupsList();this.$el.html(o({length:window.globalTS.groups.collection.models.length})),this.renderRows(window.globalTS.groups.collection.models),$("#center [data-toggle]").tooltip(),$("#center").css("overflow","auto")},renderRows:function(e){for(var o=0;o<e.length;o++){var t=e[o];this.renderOne({group:t})}},renderOne:function(e){var o=new l.default.GroupListRowView(e);this.$el.find("#group_list_body").append(o.el)},templateGroupsList:function(){var e=[];return e.push('<div id="groups">'),e.push("</div>"),e.push('<div class="groups_container table-responsive">'),e.push("<% if(length === 0) { %>"),e.push("<div>There are no groups yet.</div>"),e.push("<% } else{ %>"),e.push('<table class="grid table table-condensed">'),e.push(" <thead>"),e.push(" <th>Name</th>"),e.push(" <th>Members</th> "),e.push(" <th>Repositories</th>"),e.push(" </thead>"),e.push(' <tbody id="group_list_body">'),e.push(" </tbody>"),e.push("</table>"),e.push("<% }%>"),e.push("</div>"),_.template(e.join(""))}});e.default={GroupListView:u}});
|
||||
@@ -0,0 +1 @@
|
||||
define("toolshed/groups/group-listrow-view",["exports"],function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t=Backbone.View.extend({events:{},initialize:function(e){this.render(e.group)},render:function(e){var t=this.templateRow();return this.setElement(t({group:e})),this.$el.show(),this},templateRow:function(){return _.template(['<tr class="" data-id="<%- group.get("id") %>">','<td><a href="groups#/<%= group.get("id") %>"><%= _.escape(group.get("name")) %></a></td>','<td><%= group.get("total_members") %></td>','<td><%= group.get("total_repos") %></td>',"</tr>"].join(""))}});e.default={GroupListRowView:t}});
|
||||
@@ -0,0 +1 @@
|
||||
define("toolshed/groups/group-model",["exports"],function(o){"use strict";Object.defineProperty(o,"__esModule",{value:!0});var e=Backbone.Model.extend({urlRoot:Galaxy.root+"api/groups"}),r=Backbone.Collection.extend({url:Galaxy.root+"api/groups",model:e});o.default={Group:e,Groups:r}});
|
||||
@@ -0,0 +1 @@
|
||||
define("toolshed/toolshed.groups",["exports","toolshed/groups/group-list-view","toolshed/groups/group-detail-view"],function(o,e,t){"use strict";function u(o){return o&&o.__esModule?o:{default:o}}Object.defineProperty(o,"__esModule",{value:!0});var i=u(e),r=u(t),s=Backbone.Router.extend({routes:{"":"groups",":group_id":"group_page"}}),l=Backbone.View.extend({groupListView:null,groupDetailView:null,collection:null,initialize:function(){window.globalTS.groups=this,this.ts_router=new s,this.ts_router.on("route:groups",function(){window.globalTS.groups.groupListView=new i.default.GroupListView}),this.ts_router.on("route:group_page",function(o){window.globalTS.groups.groupDetailView=new r.default.GroupDetailView({group_id:o})}),Backbone.history.start({pushState:!1})}});o.default={ToolshedGroups:l}});
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
a{text-decoration:underline}label{font-weight:normal}.library_style_container{width:95%;margin:auto;margin-top:2em;overflow:auto !important}.library_style_container .fa{font-size:12px}.library_style_container .fa-globe,.library_style_container .fa-shield,.library_style_container .fa-key,.library_style_container .fa-ban{font-size:initial;margin-left:.6em}.library_style_container .libraryRow{background-color:#ebd9b2}.library_style_container .datasetHighlighted{background-color:#f9f9f9}.library_style_container .libraryItemDeleted-True{font-style:italic}.library_style_container div.libraryItemBody{padding:4px 4px 2px 4px}.library_style_container li.folderRow,.library_style_container li.datasetRow{border-top:solid 1px #c6bfa8}.library_style_container li.folderRow:hover,.library_style_container li.datasetRow:hover{background-color:#f9f9f9}.library_style_container td.right-center{vertical-align:middle !important;text-align:right}.library_style_container .library-genome-select{max-width:350px}.library_style_container .library-extension-select{max-width:140px}.library_style_container .library_table td{border-top:1px solid #5f6990 !important}.library_style_container .library_table th{border-bottom:2px solid #5f6990 !important}.library_style_container .library_table a{color:#0A143D}.library_style_container .library_table a:hover{color:maroon}.library_style_container tr.light td{background-color:white;color:black}.library_style_container tr.light:hover td{background-color:#f5e8cc}.library_style_container tr.dark td{background-color:#d6b161;color:white}.library_style_container tr.dark:hover td{background-color:#ebd4a4;color:white}.library_style_container a.dark{color:white}.library_style_container .dataset_table tr,.library_style_container .dataset_table th,.library_style_container .dataset_table td{border:none}.library_style_container .dataset_table .dataset-first-column{width:30%}.library_style_container th.button_heading{width:2em}.library_style_container .bigdrop.select2-container .select2-results{max-height:300px}.library_style_container .bigdrop .select2-results{max-height:300px}.library_style_container .select2-container-multi{width:100%}.library_style_container .roles-selection{width:66%}.library_style_container #library_toolbar{margin-bottom:.5em}.library_style_container #library_toolbar span{margin-right:.2em}.library_style_container #library_toolbar .toolbar-item{margin-left:1em}.library_style_container #libraries_element button,.library_style_container #folder_items_element button{margin-left:.5em}.library_style_container .help-button{float:right}.library_style_container .pagination-sm{height:15px}.library_style_container .library-paginator{margin-left:2em}.library_style_container .import-type-switch{text-decoration:underline}.library_style_container .libimport-select-none,.library_style_container .libimport-select-all{margin-left:.5em}.library_style_container .library-modal-item{width:90%;margin-left:1em;margin-right:1em}.library_style_container .paginator-bottom{width:27em;margin-left:auto;margin-right:auto;margin-top:2em;margin-bottom:2em}.modal-content #selected_history_content ul{list-style-type:none}#library-grid ul{list-style:none}#library-grid span.expandLink{padding-left:12px;display:inline-block;vertical-align:middle;background:url(../images/silk/resultset_next.png) no-repeat}#library-grid .folderRow.expanded span.expandLink{background:url(../images/silk/resultset_bottom.png) no-repeat}#library-grid .folderRow span.rowIcon{float:left;margin-right:5px;width:16px;height:16px;display:inline-block;vertical-align:middle;background:url(../images/silk/folder.png)}#library-grid .libraryItem-error{margin-right:2px;padding:0 2px 0 2px;border:1px solid #dd1b15;background:#f9c7c5}#library-grid .libraryItem-queued{margin-right:2px;padding:0 2px 0 2px;border:1px solid #bfbfbf;background:#eee}#library-grid .libraryItem-running{margin-right:2px;padding:0 2px 0 2px;border:1px solid #AAAA66;background:#FFFFCC}#library-grid .libraryItem-upload{margin-right:2px;padding:0 2px 0 2px;border:1px solid #119ac2;background:#a8e5f7}.libraryTitle th{text-align:left}.libraryTitle .rowTitle{padding:2px}
|
||||
a{text-decoration:underline}label{font-weight:normal}.library_style_container{width:95%;margin:auto;margin-top:2em;overflow:auto !important}.library_style_container .fa{font-size:12px}.library_style_container .fa-globe,.library_style_container .fa-shield,.library_style_container .fa-key,.library_style_container .fa-ban{font-size:initial;margin-left:.6em}.library_style_container .libraryRow{background-color:#ebd9b2}.library_style_container .datasetHighlighted{background-color:#f9f9f9}.library_style_container .libraryItemDeleted-True{font-style:italic}.library_style_container div.libraryItemBody{padding:4px 4px 2px 4px}.library_style_container li.folderRow,.library_style_container li.datasetRow{border-top:solid 1px #c6bfa8}.library_style_container li.folderRow:hover,.library_style_container li.datasetRow:hover{background-color:#f9f9f9}.library_style_container td.right-center{vertical-align:middle !important;text-align:right}.library_style_container .library-genome-select{max-width:350px}.library_style_container .library-extension-select{max-width:140px}.library_style_container .library_table td{border-top:1px solid #5f6990 !important}.library_style_container .library_table th{border-bottom:2px solid #5f6990 !important}.library_style_container .library_table a{color:#0A143D}.library_style_container .library_table a:hover{color:maroon}.library_style_container tr.light td{background-color:white;color:black}.library_style_container tr.light:hover td{background-color:#f5e8cc}.library_style_container tr.dark td{background-color:#d6b161;color:white}.library_style_container tr.dark:hover td{background-color:#ebd4a4;color:white}.library_style_container a.dark{color:white}.library_style_container .dataset_table tr,.library_style_container .dataset_table th,.library_style_container .dataset_table td{border:none}.library_style_container .dataset_table .dataset-first-column{width:30%}.library_style_container th.button_heading{width:2em}.library_style_container .bigdrop.select2-container .select2-results{max-height:300px}.library_style_container .bigdrop .select2-results{max-height:300px}.library_style_container .select2-container-multi{width:100%}.library_style_container .roles-selection{width:66%}.library_style_container #library_toolbar{margin-bottom:.5em}.library_style_container #library_toolbar span{margin-right:.2em}.library_style_container #library_toolbar .toolbar-item{margin-left:.5em}.library_style_container #libraries_element button,.library_style_container #folder_items_element button{margin-left:.5em}.library_style_container .right-float{float:right}.library_style_container .pagination-sm{height:15px}.library_style_container .library-paginator{margin-left:2em}.library_style_container .import-type-switch{text-decoration:underline}.library_style_container .libimport-select-none,.library_style_container .libimport-select-all{margin-left:.5em}.library_style_container .paginator-bottom{width:27em;margin-left:auto;margin-right:auto;margin-top:2em;margin-bottom:2em}.modal-content .library_selected_history_content ul{list-style-type:none}.modal-content .library-collection-type-select,.modal-content .library-collection-history-select{margin-left:auto;margin-right:auto;width:200px;min-width:200px}.modal-content .library-modal-item{width:90%;margin-left:auto;margin-right:auto;margin-top:1.5em}.libraryTitle th{text-align:left}.libraryTitle .rowTitle{padding:2px}
|
||||
@@ -61,6 +61,7 @@
|
||||
## TODO: remove when all libs are required directly in modules
|
||||
'bundled/libs.bundled',
|
||||
'libs/require',
|
||||
'bundled/extended.bundled'
|
||||
)}
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
## TODO: remove when all libs are required directly in modules
|
||||
'bundled/libs.bundled',
|
||||
'libs/require',
|
||||
'bundled/extended.bundled'
|
||||
)}
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -98,13 +99,13 @@
|
||||
|
||||
%if self.has_left_panel:
|
||||
var lp = new panels.LeftPanel({ el: '#left' });
|
||||
force_left_panel = function( x ) { lp.force_panel( x ) };
|
||||
window.force_left_panel = function( x ) { lp.force_panel( x ) };
|
||||
%endif
|
||||
|
||||
%if self.has_right_panel:
|
||||
var rp = new panels.RightPanel({ el: '#right' });
|
||||
window.handle_minwidth_hint = function( x ) { rp.handle_minwidth_hint( x ) };
|
||||
force_right_panel = function( x ) { rp.force_panel( x ) };
|
||||
window.force_right_panel = function( x ) { rp.force_panel( x ) };
|
||||
%endif
|
||||
|
||||
%if t.webapp.name == 'galaxy' and app.config.ga_code:
|
||||
|
||||
@@ -24,19 +24,16 @@ ${ h.dumps( dictionary, indent=( 2 if trans.debug else 0 ) ) }
|
||||
## 1) bootstrap kwargs (as above), 2) build Galaxy global var, 3) load 'app' by AMD (optional)
|
||||
${ self.bootstrap( **kwargs ) }
|
||||
<script type="text/javascript">
|
||||
require([ 'require', 'galaxy' ], function( require, galaxy ){
|
||||
//TODO: global...
|
||||
window.Galaxy = new galaxy.default.GalaxyApp({
|
||||
root : '${h.url_for( "/" )}',
|
||||
config : ${ render_json( get_config_dict() )},
|
||||
user : ${ render_json( get_user_dict() )},
|
||||
session_csrf_token : '${ trans.session_csrf_token }'
|
||||
}, window.bootstrapped );
|
||||
window.Galaxy = new window.bundleEntries.GalaxyApp.GalaxyApp({
|
||||
root : '${h.url_for( "/" )}',
|
||||
config : ${ render_json( get_config_dict() )},
|
||||
user : ${ render_json( get_user_dict() )},
|
||||
session_csrf_token : '${ trans.session_csrf_token }'
|
||||
}, window.bootstrapped );
|
||||
|
||||
%if app:
|
||||
require([ '${app}' ]);
|
||||
%endif
|
||||
});
|
||||
%if app:
|
||||
require([ '${app}' ]);
|
||||
%endif
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -64,10 +64,8 @@
|
||||
|
||||
## load javascript
|
||||
<script type="text/javascript">
|
||||
require(['legacy/grid/grid-view'], function(GridView) {
|
||||
$(function() {
|
||||
var gridView = new GridView.default( ${ h.dumps( self.get_grid_config( embedded=embedded, insert=insert ) ) } );
|
||||
});
|
||||
$(function() {
|
||||
var gridView = new window.bundleEntries.LegacyGridView( ${ h.dumps( self.get_grid_config( embedded=embedded, insert=insert ) ) } );
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
${h.js("bundled/extended.bundled")}
|
||||
</%def>
|
||||
|
||||
<%def name="late_javascripts()">
|
||||
|
||||
@@ -5,31 +5,24 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
${h.js("bundled/extended.bundled")}
|
||||
|
||||
## If data is chunkable, use JavaScript for display.
|
||||
%if item.datatype.CHUNKABLE:
|
||||
|
||||
<script type="text/javascript">
|
||||
require(['mvc/dataset/data'], function(data) {
|
||||
//
|
||||
// Use tabular data display progressively by deleting data from page body
|
||||
// and then showing dataset view.
|
||||
//
|
||||
$('.page-body').children().remove();
|
||||
|
||||
data.default.createTabularDatasetChunkedView({
|
||||
// TODO: encode id.
|
||||
dataset_config:
|
||||
_.extend( ${h.dumps( item.to_dict() )}, {
|
||||
chunk_url: "${h.url_for( controller='/dataset', action='display',
|
||||
dataset_id=trans.security.encode_id( item.id ))}",
|
||||
first_data_chunk: ${first_chunk}
|
||||
}),
|
||||
parent_elt: $('.page-body')
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
// Use tabular data display progressively by deleting data from page body
|
||||
// and then showing dataset view.
|
||||
var dataset_config = _.extend( ${h.dumps( item.to_dict() )}, {
|
||||
chunk_url: "${h.url_for( controller='/dataset', action='display', dataset_id=trans.security.encode_id( item.id ))}",
|
||||
first_data_chunk: ${first_chunk}});
|
||||
$('.page-body').children().remove();
|
||||
window.bundleEntries.createTabularDatasetChunkedView({
|
||||
dataset_config: dataset_config,
|
||||
parent_elt: $('.page-body')
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</script>
|
||||
%endif
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
${h.js("bundled/extended.bundled")}
|
||||
|
||||
<script type="text/javascript">
|
||||
require([ 'mvc/dataset/data' ], function( data ) {
|
||||
data.default.createTabularDatasetChunkedView({
|
||||
$(function(){
|
||||
bundleEntries.createTabularDatasetChunkedView({
|
||||
dataset_config : _.extend( ${ h.dumps( trans.security.encode_dict_ids( dataset.to_dict() ) )}, {
|
||||
first_data_chunk: ${ chunk }
|
||||
}),
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
|
||||
// extra configuration global
|
||||
var galaxy_config = ${ h.dumps( self.galaxy_config ) };
|
||||
window.galaxy_config = galaxy_config;
|
||||
</script>
|
||||
|
||||
${h.js(
|
||||
@@ -146,14 +147,14 @@
|
||||
## configure left panel
|
||||
%if self.galaxy_config['left_panel']:
|
||||
var lp = new panels.LeftPanel({ el: '#left' });
|
||||
force_left_panel = function( x ) { lp.force_panel( x ) };
|
||||
window.force_left_panel = function( x ) { lp.force_panel( x ) };
|
||||
%endif
|
||||
|
||||
## configure right panel
|
||||
%if self.galaxy_config['right_panel']:
|
||||
var rp = new panels.RightPanel({ el: '#right' });
|
||||
window.handle_minwidth_hint = function( x ) { rp.handle_minwidth_hint( x ) };
|
||||
force_right_panel = function( x ) { rp.force_panel( x ) };
|
||||
window.force_right_panel = function( x ) { rp.force_panel( x ) };
|
||||
%endif
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
@@ -47,18 +47,8 @@
|
||||
.css( 'height', '100%' )
|
||||
.addClass( 'flex-vertical-container' );
|
||||
|
||||
require.config({
|
||||
baseUrl : "${h.url_for( '/static/scripts' )}",
|
||||
urlArgs: 'v=${app.server_starttime}'
|
||||
})([
|
||||
'mvc/history/history-view-annotated',
|
||||
'mvc/history/copy-dialog',
|
||||
], function( panelMod, historyCopyDialog ){
|
||||
// history module is already in the dpn chain from the panel. We can re-scope it here.
|
||||
var HISTORY = require( 'mvc/history/history-model' );
|
||||
var HISTORY_CONTENTS = require( 'mvc/history/history-contents' );
|
||||
|
||||
var HistoryContentsWithAnnotations = HISTORY_CONTENTS.default.HistoryContents.extend({
|
||||
$(function(){
|
||||
var HistoryContentsWithAnnotations = window.bundleEntries.HistoryContents.extend({
|
||||
_buildFetchData : function( options ){
|
||||
console.log( '_buildFetchData:' );
|
||||
options = options || {};
|
||||
@@ -66,10 +56,10 @@
|
||||
options.view = 'summary';
|
||||
options.keys = 'annotation,tags';
|
||||
}
|
||||
return HISTORY_CONTENTS.default.HistoryContents.prototype._buildFetchData.call( this, options );
|
||||
return window.bundleEntries.HistoryContents.prototype._buildFetchData.call( this, options );
|
||||
}
|
||||
});
|
||||
var HistoryWithAnnotations = HISTORY.default.History.extend({
|
||||
var HistoryWithAnnotations = window.bundleEntries.History.extend({
|
||||
contentsClass : HistoryContentsWithAnnotations
|
||||
});
|
||||
|
||||
@@ -78,16 +68,16 @@
|
||||
});
|
||||
|
||||
$( '.history-copy-link' ).click( function( ev ){
|
||||
historyCopyDialog.default( historyModel, { useImport: true, allowAll: false })
|
||||
window.bundleEntries.HistoryCopyDialog( historyModel, { useImport: true, allowAll: false })
|
||||
.done( function(){
|
||||
var mainWindow = ( window && ( window !== window.parent ) )? window.top : window;
|
||||
mainWindow.location.href = Galaxy.root;
|
||||
});
|
||||
});
|
||||
|
||||
window.historyView = new panelMod.default.AnnotatedHistoryView({
|
||||
window.historyView = new window.bundleEntries.HistoryViewAnnotated.AnnotatedHistoryView({
|
||||
el : $( "#history-" + historyJSON.id ),
|
||||
className : panelMod.default.AnnotatedHistoryView.prototype.className + ' wide',
|
||||
className : window.bundleEntries.HistoryViewAnnotated.AnnotatedHistoryView.prototype.className + ' wide',
|
||||
model : historyModel,
|
||||
show_deleted : false,
|
||||
show_hidden : false,
|
||||
|
||||
@@ -141,22 +141,21 @@
|
||||
hda_dicts.append( hda_dict )
|
||||
%>
|
||||
${parent.javascripts()}
|
||||
${h.js("bundled/extended.bundled")}
|
||||
|
||||
## load edit views for each of the hdas
|
||||
<script type="text/javascript">
|
||||
define( 'display-structured', function(){
|
||||
require([ 'mvc/history/hda-li-edit', 'mvc/history/hda-model' ], function( hdaEdit, hdaModel ){
|
||||
var hdaJSON = ${ h.dumps( hda_dicts, indent=( 2 if trans.debug else 0 ) ) };
|
||||
var hdaJSON = ${ h.dumps( hda_dicts, indent=( 2 if trans.debug else 0 ) ) };
|
||||
|
||||
window.hdas = hdaJSON.map( function( hda ){
|
||||
return new hdaEdit.default.HDAListItemEdit({
|
||||
model : new hdaModel.default.HistoryDatasetAssociation( hda ),
|
||||
el : $( '#hda-' + hda.id ),
|
||||
linkTarget : '_self',
|
||||
purgeAllowed : Galaxy.config.allow_user_dataset_purge,
|
||||
logger : Galaxy.logger
|
||||
}).render( 0 );
|
||||
});
|
||||
window.hdas = hdaJSON.map( function( hda ){
|
||||
return new window.bundleEntries.HDAListItemEdit.HDAListItemEdit({
|
||||
model : new window.bundleEntries.HDAModel.HistoryDatasetAssociation( hda ),
|
||||
el : $( '#hda-' + hda.id ),
|
||||
linkTarget : '_self',
|
||||
purgeAllowed : Galaxy.config.allow_user_dataset_purge,
|
||||
logger : Galaxy.logger
|
||||
}).render( 0 );
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -40,99 +40,87 @@
|
||||
// In order to handle this, find this script and cache the previous node (the div above).
|
||||
// (Since we need thisScript to be locally scoped or it will get overwritten, enclose in self-calling function)
|
||||
(function(){
|
||||
var scripts = document.getElementsByTagName( 'script' ),
|
||||
var scripts = document.getElementsByTagName( 'script' );
|
||||
// this is executed immediately, so the last script will be this script
|
||||
thisScript = scripts[ scripts.length - 1 ],
|
||||
$embeddedHistory = $( thisScript ).prev();
|
||||
var thisScript = scripts[ scripts.length - 1 ];
|
||||
var $embeddedHistory = $( thisScript ).prev();
|
||||
|
||||
require.config({
|
||||
baseUrl: "${h.url_for( '/static/scripts' )}",
|
||||
urlArgs: 'v=${app.server_starttime}'
|
||||
});
|
||||
require([
|
||||
'mvc/history/history-view-annotated',
|
||||
'mvc/history/copy-dialog'
|
||||
], function( viewMod, historyCopyDialog ){
|
||||
var $embeddedHistory = $( thisScript ).prev();
|
||||
$embeddedHistory.find( '.item-content' ).addClass( 'flex-vertical-container' );
|
||||
var $embeddedHistory = $( thisScript ).prev();
|
||||
$embeddedHistory.find( '.item-content' ).addClass( 'flex-vertical-container' );
|
||||
|
||||
$(function(){
|
||||
var HISTORY = require( 'mvc/history/history-model' );
|
||||
var HISTORY_CONTENTS = require( 'mvc/history/history-contents' );
|
||||
$(function(){
|
||||
var HistoryContentsWithAnnotations = window.bundleEntries.HistoryContents.extend({
|
||||
_buildFetchData : function( options ){
|
||||
console.log( '_buildFetchData:' );
|
||||
options = options || {};
|
||||
if( !options.keys && !options.view ){
|
||||
options.view = 'summary';
|
||||
options.keys = 'annotation,tags';
|
||||
}
|
||||
return window.bundleEntries.HistoryContents.prototype._buildFetchData.call( this, options );
|
||||
}
|
||||
});
|
||||
var HistoryWithAnnotations = window.bundleEntries.History.extend({
|
||||
contentsClass : HistoryContentsWithAnnotations
|
||||
});
|
||||
|
||||
var HistoryContentsWithAnnotations = HISTORY_CONTENTS.default.HistoryContents.extend({
|
||||
_buildFetchData : function( options ){
|
||||
console.log( '_buildFetchData:' );
|
||||
options = options || {};
|
||||
if( !options.keys && !options.view ){
|
||||
options.view = 'summary';
|
||||
options.keys = 'annotation,tags';
|
||||
}
|
||||
return HISTORY_CONTENTS.default.HistoryContents.prototype._buildFetchData.call( this, options );
|
||||
var historyJSON = ${h.dumps( history_dict )};
|
||||
var historyModel = new HistoryWithAnnotations( historyJSON, null, {
|
||||
order : 'hid-asc',
|
||||
});
|
||||
|
||||
var historyView = new window.bundleEntries.HistoryViewAnnotated.AnnotatedHistoryView({
|
||||
el : $embeddedHistory.find( ".history-panel" ),
|
||||
className : window.bundleEntries.HistoryViewAnnotated.AnnotatedHistoryView.prototype.className + ' wide',
|
||||
model : historyModel
|
||||
});
|
||||
|
||||
historyView.trigger( 'loading' );
|
||||
historyModel.fetchContents({ silent: true })
|
||||
.fail( function(){ alert( 'Galaxy history failed to load' ); })
|
||||
.done( function(){
|
||||
historyView.trigger( 'loading-done' );
|
||||
historyView.render();
|
||||
});
|
||||
|
||||
function toggleExpanded( ev ){
|
||||
ev.preventDefault();
|
||||
$embeddedHistory.find( '.expand-content-btn' ).toggleClass( 'toggle-expand' ).toggleClass( 'toggle' );
|
||||
$embeddedHistory.find( ".summary-content" ).slideToggle( "fast" );
|
||||
$embeddedHistory.find( ".annotation" ).slideToggle( "fast" );
|
||||
$embeddedHistory.find( ".expanded-content" ).slideToggle( "fast" );
|
||||
}
|
||||
|
||||
$embeddedHistory.find( '.expand-content-btn' ).click( toggleExpanded );
|
||||
$embeddedHistory.find( '.toggle-embed' ).click( toggleExpanded );
|
||||
|
||||
function showConfirmationModal( name ){
|
||||
var body = [
|
||||
'<div class="donemessagelarge">',
|
||||
_l( 'History imported' ), ': ', _.escape( historyModel.get( 'name' ) ),
|
||||
'</div>'
|
||||
].join('');
|
||||
Galaxy.modal.show({
|
||||
title : _l( 'Success!' ),
|
||||
body : $( body ),
|
||||
buttons : {
|
||||
'Return to the published page' : function(){
|
||||
Galaxy.modal.hide();
|
||||
},
|
||||
'Start using the history' : function(){
|
||||
window.location = Galaxy.root;
|
||||
},
|
||||
}
|
||||
});
|
||||
var HistoryWithAnnotations = HISTORY.default.History.extend({
|
||||
contentsClass : HistoryContentsWithAnnotations
|
||||
});
|
||||
Galaxy.modal.$( '.modal-header' ).hide();
|
||||
Galaxy.modal.$( '.modal-body' ).css( 'padding-bottom', 0 );
|
||||
Galaxy.modal.$( '.modal-footer' ).css({ border : 0, 'padding-top': 0 });
|
||||
}
|
||||
|
||||
var historyJSON = ${h.dumps( history_dict )};
|
||||
var historyModel = new HistoryWithAnnotations( historyJSON, null, {
|
||||
order : 'hid-asc',
|
||||
});
|
||||
|
||||
var historyView = new viewMod.default.AnnotatedHistoryView({
|
||||
el : $embeddedHistory.find( ".history-panel" ),
|
||||
className : viewMod.default.AnnotatedHistoryView.prototype.className + ' wide',
|
||||
model : historyModel
|
||||
});
|
||||
|
||||
historyView.trigger( 'loading' );
|
||||
historyModel.fetchContents({ silent: true })
|
||||
.fail( function(){ alert( 'Galaxy history failed to load' ); })
|
||||
.done( function(){
|
||||
historyView.trigger( 'loading-done' );
|
||||
historyView.render();
|
||||
});
|
||||
|
||||
function toggleExpanded( ev ){
|
||||
ev.preventDefault();
|
||||
$embeddedHistory.find( '.expand-content-btn' ).toggleClass( 'toggle-expand' ).toggleClass( 'toggle' );
|
||||
$embeddedHistory.find( ".summary-content" ).slideToggle( "fast" );
|
||||
$embeddedHistory.find( ".annotation" ).slideToggle( "fast" );
|
||||
$embeddedHistory.find( ".expanded-content" ).slideToggle( "fast" );
|
||||
}
|
||||
|
||||
$embeddedHistory.find( '.expand-content-btn' ).click( toggleExpanded );
|
||||
$embeddedHistory.find( '.toggle-embed' ).click( toggleExpanded );
|
||||
|
||||
function showConfirmationModal( name ){
|
||||
var body = [
|
||||
'<div class="donemessagelarge">',
|
||||
_l( 'History imported' ), ': ', _.escape( historyModel.get( 'name' ) ),
|
||||
'</div>'
|
||||
].join('');
|
||||
Galaxy.modal.show({
|
||||
title : _l( 'Success!' ),
|
||||
body : $( body ),
|
||||
buttons : {
|
||||
'Return to the published page' : function(){
|
||||
Galaxy.modal.hide();
|
||||
},
|
||||
'Start using the history' : function(){
|
||||
window.location = Galaxy.root;
|
||||
},
|
||||
}
|
||||
});
|
||||
Galaxy.modal.$( '.modal-header' ).hide();
|
||||
Galaxy.modal.$( '.modal-body' ).css( 'padding-bottom', 0 );
|
||||
Galaxy.modal.$( '.modal-footer' ).css({ border : 0, 'padding-top': 0 });
|
||||
}
|
||||
|
||||
$embeddedHistory.find( '.import' ).click( function( ev ){
|
||||
var dialogOptions = { useImport: true, allowAll: false, autoClose: false };
|
||||
historyCopyDialog.default( historyModel, dialogOptions ).done( showConfirmationModal );
|
||||
})
|
||||
});
|
||||
$embeddedHistory.find( '.import' ).click( function( ev ){
|
||||
var dialogOptions = { useImport: true, allowAll: false, autoClose: false };
|
||||
window.bundleEntries.HistoryCopyDialog( historyModel, dialogOptions ).done( showConfirmationModal );
|
||||
})
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
</%def>
|
||||
|
||||
## -----------------------------------------------------------------------------
|
||||
<%def name="javascripts()">
|
||||
${ parent.javascripts() }
|
||||
${h.js("bundled/extended.bundled")}
|
||||
</%def>
|
||||
|
||||
<%def name="stylesheets()">
|
||||
${ parent.stylesheets() }
|
||||
|
||||
@@ -68,26 +73,18 @@ ${ parent.stylesheets() }
|
||||
<%def name="javascript_app()">
|
||||
<script type="text/javascript">
|
||||
define( 'app', function(){
|
||||
require([
|
||||
'mvc/history/history-model',
|
||||
'mvc/history/history-structure-view'
|
||||
], function( HISTORY, StructureView ){
|
||||
console.debug(HISTORY);
|
||||
console.debug(StructureView);
|
||||
var historyModel = new HISTORY.default.History( bootstrapped.history, bootstrapped.contents );
|
||||
console.debug("Got here?");
|
||||
window.historymodel = historyModel;
|
||||
window.jobs = bootstrapped.jobs;
|
||||
window.tools = bootstrapped.tools;
|
||||
var historyModel = new window.bundleEntries.History( bootstrapped.history, bootstrapped.contents );
|
||||
window.historymodel = historyModel;
|
||||
window.jobs = bootstrapped.jobs;
|
||||
window.tools = bootstrapped.tools;
|
||||
|
||||
var structure = new StructureView.default({
|
||||
model : historyModel,
|
||||
jobs : bootstrapped.jobs,
|
||||
tools : bootstrapped.tools
|
||||
});
|
||||
window.structure = structure;
|
||||
structure.render().$el.appendTo( 'body' );
|
||||
var structure = new window.bundleEntries.StructureView({
|
||||
model : historyModel,
|
||||
jobs : bootstrapped.jobs,
|
||||
tools : bootstrapped.tools
|
||||
});
|
||||
window.structure = structure;
|
||||
structure.render().$el.appendTo( 'body' );
|
||||
});
|
||||
</script>
|
||||
${ galaxy_client.load( app='app', historyId=historyId, history=history, contents=contents, jobs=jobs, tools=tools ) }
|
||||
|
||||
@@ -102,109 +102,22 @@ a.btn {
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
// use_panels effects where the the center_panel() is rendered:
|
||||
// w/o it renders to the body, w/ it renders to #center - we need to adjust a few things for scrolling to work
|
||||
var hasMasthead = ${ 'true' if use_panels else 'false' },
|
||||
userIsOwner = ${ 'true' if user_is_owner else 'false' },
|
||||
isCurrent = ${ 'true' if history_is_current else 'false' },
|
||||
historyJSON = ${ h.dumps( history ) },
|
||||
viewToUse = ( userIsOwner )?
|
||||
//TODO: change class names
|
||||
({ location: 'mvc/history/history-view-edit', className: 'HistoryViewEdit' }):
|
||||
({ location: 'mvc/history/history-view', className: 'HistoryView' });
|
||||
|
||||
require.config({
|
||||
baseUrl : "${h.url_for( '/static/scripts' )}",
|
||||
paths : {
|
||||
'jquery' : 'libs/jquery/jquery'
|
||||
},
|
||||
urlArgs: 'v=${app.server_starttime}'
|
||||
})([
|
||||
'mvc/user/user-model',
|
||||
viewToUse.location,
|
||||
'mvc/history/copy-dialog',
|
||||
'utils/localization',
|
||||
'ui/mode-button'
|
||||
], function( user, viewMod, historyCopyDialog, _l ){
|
||||
+(function setUpBehaviors(){
|
||||
$( '#toggle-deleted' ).modeButton({
|
||||
initialMode : "${ 'showing_deleted' if show_deleted else 'not_showing_deleted' }",
|
||||
modes: [
|
||||
{ mode: 'showing_deleted', html: _l( 'Exclude deleted' ) },
|
||||
{ mode: 'not_showing_deleted', html: _l( 'Include deleted' ) }
|
||||
]
|
||||
});
|
||||
|
||||
$( '#toggle-hidden' ).modeButton({
|
||||
initialMode : "${ 'showing_hidden' if show_hidden else 'not_showing_hidden' }",
|
||||
modes: [
|
||||
{ mode: 'showing_hidden', html: _l( 'Exclude hidden' ) },
|
||||
{ mode: 'not_showing_hidden', html: _l( 'Include hidden' ) }
|
||||
]
|
||||
});
|
||||
|
||||
$( '#switch' ).click( function( ev ){
|
||||
//##HACK:ity hack hack
|
||||
//##TODO: remove when out of iframe
|
||||
var hview = Galaxy.currHistoryPanel
|
||||
|| ( top.Galaxy && top.Galaxy.currHistoryPanel )? top.Galaxy.currHistoryPanel : null;
|
||||
if( hview ){
|
||||
hview.switchToHistory( "${ history[ 'id' ] }" );
|
||||
} else {
|
||||
window.location = "${ switch_to_url }";
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
$(function(){
|
||||
if( hasMasthead ){
|
||||
$( '#center' ).addClass( 'flex-vertical-container' );
|
||||
}
|
||||
var viewClass = viewMod.default[ viewToUse.className ],
|
||||
// history module is already in the dpn chain from the view. We can re-scope it here.
|
||||
HISTORY = require( 'mvc/history/history-model' ),
|
||||
historyModel = new HISTORY.default.History( historyJSON );
|
||||
|
||||
// attach the copy dialog to the import button now that we have a history
|
||||
$( '#import' ).click( function( ev ){
|
||||
historyCopyDialog.default( historyModel, {
|
||||
useImport : true,
|
||||
// use default datasets option to match the toggle-deleted button
|
||||
allDatasets : $( '#toggle-deleted' ).modeButton( 'getMode' ).mode === 'showing_deleted',
|
||||
}).done( function(){
|
||||
if( window === window.parent ){
|
||||
window.location = Galaxy.root;
|
||||
} else if( Galaxy.currHistoryPanel ){
|
||||
Galaxy.currHistoryPanel.loadCurrentHistory();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.historyView = new viewClass({
|
||||
el : $( "#history-" + historyJSON.id ),
|
||||
className : viewClass.prototype.className + ' wide',
|
||||
$scrollContainer: hasMasthead? function(){ return this.$el.parent(); } : undefined,
|
||||
model : historyModel,
|
||||
show_deleted : ${show_deleted_json},
|
||||
show_hidden : ${show_hidden_json},
|
||||
purgeAllowed : Galaxy.config.allow_user_dataset_purge,
|
||||
});
|
||||
historyView.trigger( 'loading' );
|
||||
historyModel.fetchContents({ silent: true })
|
||||
.fail( function(){ alert( 'Galaxy history failed to load' ); })
|
||||
.done( function(){
|
||||
historyView.trigger( 'loading-done' );
|
||||
historyView.render();
|
||||
});
|
||||
|
||||
$( '#toggle-deleted' ).on( 'click', function(){
|
||||
historyView.toggleShowDeleted();
|
||||
});
|
||||
$( '#toggle-hidden' ).on( 'click', function(){
|
||||
historyView.toggleShowHidden();
|
||||
});
|
||||
});
|
||||
$(function(){
|
||||
options = {
|
||||
hasMasthead: ${ 'true' if use_panels else 'false' },
|
||||
userIsOwner: ${ 'true' if user_is_owner else 'false' },
|
||||
isCurrent: ${ 'true' if history_is_current else 'false' },
|
||||
historyJSON: ${ h.dumps( history ) },
|
||||
showDeletedJson: ${ show_deleted_json },
|
||||
showHiddenJson: ${ show_hidden_json },
|
||||
initialModeDeleted: "${ 'showing_deleted' if show_deleted else 'not_showing_deleted' }",
|
||||
initialModeHidden: "${ 'showing_hidden' if show_hidden else 'not_showing_hidden' }",
|
||||
allowUserDatasetPurge: ${ 'true' if trans.app.config.allow_user_dataset_purge else 'false' }
|
||||
};
|
||||
options.viewToUse = options.userIsOwner ?
|
||||
({ location: 'mvc/history/history-view-edit', className: 'HistoryViewEdit' }):
|
||||
({ location: 'mvc/history/history-view', className: 'HistoryView' });
|
||||
window.bundleEntries.history(options);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
<%inherit file="/webapps/galaxy/base_panels.mako"/>
|
||||
<%namespace file="/galaxy_client_app.mako" name="galaxy_client"/>
|
||||
|
||||
@@ -24,36 +23,16 @@
|
||||
|
||||
<%def name="javascript_app()">
|
||||
<script type="text/javascript">
|
||||
define( 'app', function(){
|
||||
require([
|
||||
'mvc/history/history-model',
|
||||
'mvc/history/multi-panel'
|
||||
], function( HISTORY_MODEL, MULTI_HISTORY ){
|
||||
$(function(){
|
||||
histories = new HISTORY_MODEL.default.HistoryCollection( [], {
|
||||
includeDeleted : bootstrapped.includingDeleted,
|
||||
order : bootstrapped.order,
|
||||
limitOnFirstFetch : bootstrapped.limit,
|
||||
limitPerFetch : bootstrapped.limit,
|
||||
// lastFetched : bootstrapped.limit,
|
||||
currentHistoryId : bootstrapped.current_history_id,
|
||||
});
|
||||
|
||||
multipanel = new MULTI_HISTORY.default.MultiPanelColumns({
|
||||
el : $( '#center' ).get(0),
|
||||
histories : histories,
|
||||
})
|
||||
histories.fetchFirst({ silent: true })
|
||||
.done( function(){
|
||||
multipanel.createColumns();
|
||||
multipanel.render( 0 );
|
||||
});
|
||||
});
|
||||
define( 'app', function(){
|
||||
bundleEntries.multiHistory(bootstrapped);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
${ galaxy_client.load( app='app', current_history_id=current_history_id,
|
||||
includingDeleted=include_deleted_histories, order=order, limit=limit ) }
|
||||
##${ galaxy_client.load( app='app', histories=histories,
|
||||
## includingDeleted=include_deleted_histories, order=order, limit=limit ) }
|
||||
|
||||
${galaxy_client.load(
|
||||
app='app',
|
||||
current_history_id=current_history_id,
|
||||
includingDeleted=include_deleted_histories,
|
||||
order=order,
|
||||
limit=limit
|
||||
)}
|
||||
</%def>
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
iframe_base_path = "${h.url_for('/static/wymeditor/iframe/galaxy')}/",
|
||||
save_url = "${h.url_for(controller='page', action='save' )}";
|
||||
|
||||
require(['galaxy.pages'], function(Pages){
|
||||
Pages.default();
|
||||
$(function(){
|
||||
bundleEntries.pages()
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
|
||||
<%def name="stylesheets()">
|
||||
${parent.stylesheets()}
|
||||
${h.css(
|
||||
"trackster"
|
||||
)}
|
||||
${h.css("trackster")}
|
||||
|
||||
## Style changes needed for display.
|
||||
<style type="text/css">
|
||||
@@ -53,56 +51,44 @@
|
||||
<div id="${trans.security.encode_id( visualization.id )}" class="unified-panel-body" style="overflow:none;top:0px;"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
require.config({
|
||||
baseUrl: "${h.url_for('/static/scripts') }",
|
||||
shim: {
|
||||
"libs/underscore": { exports: "_" },
|
||||
"libs/backbone": { exports: "Backbone" },
|
||||
},
|
||||
urlArgs: 'v=${app.server_starttime}'
|
||||
});
|
||||
require( ["viz/trackster"], function(trackster) {
|
||||
// FIXME: deliberate global required for now due to requireJS integration.
|
||||
view = null;
|
||||
|
||||
// FIXME: deliberate global required for now due to requireJS integration.
|
||||
view = null;
|
||||
var ui = new (window.bundleEntries.Trackster.TracksterUI)( "${h.url_for('/')}" );
|
||||
var container_element = $("#${trans.security.encode_id( visualization.id )}");
|
||||
|
||||
var ui = new (trackster.default.TracksterUI)( "${h.url_for('/')}" )
|
||||
container_element = $("#${trans.security.encode_id( visualization.id )}");
|
||||
$(function() {
|
||||
var is_embedded = (container_element.parents(".item-content").length > 0);
|
||||
|
||||
$(function() {
|
||||
var is_embedded = (container_element.parents(".item-content").length > 0);
|
||||
// HTML setup.
|
||||
if (is_embedded) {
|
||||
container_element.css( { "position": "relative" } );
|
||||
} else { // Viewing just one shared viz
|
||||
$("#right-border").click(function() { view.resize_window(); });
|
||||
}
|
||||
|
||||
// HTML setup.
|
||||
if (is_embedded) {
|
||||
container_element.css( { "position": "relative" } );
|
||||
} else { // Viewing just one shared viz
|
||||
$("#right-border").click(function() { view.resize_window(); });
|
||||
}
|
||||
// Create visualization.
|
||||
var callback;
|
||||
%if 'viewport' in config:
|
||||
var callback = function() { view.change_chrom( '${config['viewport']['chrom']}', ${config['viewport']['start']}, ${config['viewport']['end']} ); }
|
||||
%endif
|
||||
view = ui.create_visualization( {
|
||||
container: container_element,
|
||||
name: "${config.get('title') | h}",
|
||||
vis_id: "${config.get('vis_id')}",
|
||||
dbkey: "${config.get('dbkey')}"
|
||||
},
|
||||
${ h.dumps( config.get( 'viewport', dict() ) ) },
|
||||
${ h.dumps( config['tracks'] ) },
|
||||
${ h.dumps( config.get('bookmarks') ) }
|
||||
);
|
||||
|
||||
// Create visualization.
|
||||
var callback;
|
||||
%if 'viewport' in config:
|
||||
var callback = function() { view.change_chrom( '${config['viewport']['chrom']}', ${config['viewport']['start']}, ${config['viewport']['end']} ); }
|
||||
%endif
|
||||
view = ui.create_visualization( {
|
||||
container: container_element,
|
||||
name: "${config.get('title') | h}",
|
||||
vis_id: "${config.get('vis_id')}",
|
||||
dbkey: "${config.get('dbkey')}"
|
||||
},
|
||||
${ h.dumps( config.get( 'viewport', dict() ) ) },
|
||||
${ h.dumps( config['tracks'] ) },
|
||||
${ h.dumps( config.get('bookmarks') ) }
|
||||
);
|
||||
|
||||
// Set up keyboard navigation.
|
||||
ui.init_keyboard_nav(view);
|
||||
|
||||
// HACK: set viewport height because it cannot be set automatically. Currently, max height for embedded
|
||||
// elts is 25em, so use 20em.
|
||||
view.viewport_container.height("20em");
|
||||
});
|
||||
// Set up keyboard navigation.
|
||||
ui.init_keyboard_nav(view);
|
||||
|
||||
// HACK: set viewport height because it cannot be set automatically. Currently, max height for embedded
|
||||
// elts is 25em, so use 20em.
|
||||
view.viewport_container.height("20em");
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -138,41 +138,23 @@
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
${h.js( "libs/require" )}
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
require.config({
|
||||
baseUrl: "${h.url_for('/static/scripts')}",
|
||||
shim: {
|
||||
"libs/underscore": { exports: "_" },
|
||||
"libs/d3": { exports: "d3" }
|
||||
},
|
||||
urlArgs: 'v=${app.server_starttime}'
|
||||
});
|
||||
$(function(){
|
||||
var config = ${ h.dumps( config )};
|
||||
var data = ${h.dumps(data['data'])};
|
||||
|
||||
require(["viz/phyloviz"], function(phyloviz_mod) {
|
||||
|
||||
function initPhyloViz(data, config) {
|
||||
var phyloviz;
|
||||
|
||||
// -- Initialization code |-->
|
||||
phyloviz = new phyloviz_mod.default.PhylovizView({
|
||||
data : data,
|
||||
layout : "Linear",
|
||||
config : config
|
||||
});
|
||||
|
||||
// -- Render viz. --
|
||||
phyloviz.render();
|
||||
|
||||
};
|
||||
|
||||
$(function firstVizLoad(){ // calls when viz is loaded for the first time
|
||||
var config = ${ h.dumps( config )};
|
||||
var data = ${h.dumps(data['data'])};
|
||||
initPhyloViz(data, config);
|
||||
// -- Initialization code |-->
|
||||
var phyloviz = new bundleEntries.phyloviz({
|
||||
data : data,
|
||||
layout : "Linear",
|
||||
config : config
|
||||
});
|
||||
|
||||
// -- Render viz. --
|
||||
phyloviz.render();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -109,31 +109,13 @@
|
||||
${h.js( "libs/jquery/jquery-ui" )}
|
||||
|
||||
<script type="text/javascript">
|
||||
// require.config({
|
||||
// baseUrl: "${h.url_for('/static/scripts') }",
|
||||
// shim: {
|
||||
// "libs/underscore": { exports: "_" },
|
||||
// "libs/backbone": {
|
||||
// deps: [ 'jquery', 'libs/underscore' ],
|
||||
// exports: "Backbone"
|
||||
// },
|
||||
// "libs/d3": { exports: "d3" },
|
||||
// },
|
||||
// // cache buster based on templated server (re)start time
|
||||
// urlArgs: 'v=${app.server_starttime}'
|
||||
// });
|
||||
|
||||
require(["viz/sweepster"], function(sweepster) {
|
||||
|
||||
var viz;
|
||||
$(function() {
|
||||
// -- Viz set up. --
|
||||
var viz = new sweepster.default.SweepsterVisualization(
|
||||
${ h.dumps( config )}
|
||||
);
|
||||
var viz_view = new sweepster.default.SweepsterVisualizationView({ model: viz });
|
||||
viz_view.render();
|
||||
});
|
||||
$(function() {
|
||||
// -- Viz set up. --
|
||||
var viz = new window.bundleEntries.SweepsterVisualization(
|
||||
${ h.dumps( config )}
|
||||
);
|
||||
var viz_view = new window.bundleEntries.SweepsterVisualizationView({ model: viz });
|
||||
viz_view.render();
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
${parent.javascripts()}
|
||||
|
||||
<script type="text/javascript">
|
||||
require(['reports/run_stats'], function(run_stats){
|
||||
run_stats.create_chart(${jf_hr_data}, "jf_hr_chart", "hours", "Jobs Finished per Hour");
|
||||
run_stats.create_chart(${jf_dy_data}, "jf_dy_chart", "days", "Jobs Finished per Day");
|
||||
run_stats.create_chart(${jc_hr_data}, "jc_hr_chart", "hours", "Jobs Created per Hour");
|
||||
run_stats.create_chart(${jc_dy_data}, "jc_dy_chart", "days", "Jobs Created per Day");
|
||||
run_stats.create_histogram(${et_hr_data}, "et_hr_chart", "Job Run Times (past day)");
|
||||
run_stats.create_histogram(${et_dy_data}, "et_dy_chart", "Job Run Time (past 30 days)");
|
||||
$(function(){
|
||||
window.bundleEntries.run_stats.create_chart(${jf_hr_data}, "jf_hr_chart", "hours", "Jobs Finished per Hour");
|
||||
window.bundleEntries.run_stats.create_chart(${jf_dy_data}, "jf_dy_chart", "days", "Jobs Finished per Day");
|
||||
window.bundleEntries.run_stats.create_chart(${jc_hr_data}, "jc_hr_chart", "hours", "Jobs Created per Hour");
|
||||
window.bundleEntries.run_stats.create_chart(${jc_dy_data}, "jc_dy_chart", "days", "Jobs Created per Day");
|
||||
window.bundleEntries.run_stats.create_histogram(${et_hr_data}, "et_hr_chart", "Job Run Times (past day)");
|
||||
window.bundleEntries.run_stats.create_histogram(${et_dy_data}, "et_dy_chart", "Job Run Time (past 30 days)");
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
@@ -41,14 +41,7 @@
|
||||
<script type="text/javascript">
|
||||
window.globalTS = new Object();
|
||||
$( function(){
|
||||
require.config({
|
||||
paths: {
|
||||
'toolshed': '../toolshed'
|
||||
}
|
||||
});
|
||||
require([ '${config.get( "app" ).get( "jscript" )}' ], function( groups ){
|
||||
app = new groups.default.ToolshedGroups();
|
||||
});
|
||||
new window.bundleEntries.ToolshedGroups.ToolshedGroups();
|
||||
});
|
||||
</script>
|
||||
<div id="groups_element" style="width: 95%; margin:auto; margin-top:2em; "></div>
|
||||
|
||||
@@ -29,7 +29,7 @@ class ConfigurationApiTestCase(api.ApiTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ConfigurationApiTestCase, self).setUp()
|
||||
self.library_populator = LibraryPopulator(self)
|
||||
self.library_populator = LibraryPopulator(self.galaxy_interactor)
|
||||
|
||||
def test_normal_user_configuration(self):
|
||||
config = self._get_configuration()
|
||||
|
||||
@@ -22,7 +22,7 @@ class HistoryContentsApiTestCase(api.ApiTestCase, TestsDatasets):
|
||||
self.history_id = self._new_history()
|
||||
self.dataset_populator = DatasetPopulator(self.galaxy_interactor)
|
||||
self.dataset_collection_populator = DatasetCollectionPopulator(self.galaxy_interactor)
|
||||
self.library_populator = LibraryPopulator(self)
|
||||
self.library_populator = LibraryPopulator(self.galaxy_interactor)
|
||||
|
||||
def test_index_hda_summary(self):
|
||||
hda1 = self._new_dataset(self.history_id)
|
||||
|
||||
@@ -13,7 +13,7 @@ class LibrariesApiTestCase(api.ApiTestCase, TestsDatasets):
|
||||
super(LibrariesApiTestCase, self).setUp()
|
||||
self.dataset_populator = DatasetPopulator(self.galaxy_interactor)
|
||||
self.dataset_collection_populator = DatasetCollectionPopulator(self.galaxy_interactor)
|
||||
self.library_populator = LibraryPopulator(self)
|
||||
self.library_populator = LibraryPopulator(self.galaxy_interactor)
|
||||
|
||||
def test_create(self):
|
||||
data = dict(name="CreateTestLibrary")
|
||||
|
||||
@@ -259,7 +259,7 @@ class ToolsTestCase(api.ApiTestCase):
|
||||
@skip_without_tool("library_data")
|
||||
def test_library_data_param(self):
|
||||
with self.dataset_populator.test_history() as history_id:
|
||||
ld = LibraryPopulator(self).new_library_dataset("lda_test_library")
|
||||
ld = LibraryPopulator(self.galaxy_interactor).new_library_dataset("lda_test_library")
|
||||
inputs = {
|
||||
"library_dataset": ld["ldda_id"],
|
||||
"library_dataset_multiple": [ld["ldda_id"], ld["ldda_id"]]
|
||||
|
||||
+25
-13
@@ -461,9 +461,8 @@ class WorkflowPopulator(BaseWorkflowPopulator, ImporterGalaxyInterface):
|
||||
|
||||
class LibraryPopulator(object):
|
||||
|
||||
def __init__(self, api_test_case):
|
||||
self.api_test_case = api_test_case
|
||||
self.galaxy_interactor = api_test_case.galaxy_interactor
|
||||
def __init__(self, galaxy_interactor):
|
||||
self.galaxy_interactor = galaxy_interactor
|
||||
|
||||
def new_private_library(self, name):
|
||||
library = self.new_library(name)
|
||||
@@ -500,44 +499,57 @@ class LibraryPopulator(object):
|
||||
|
||||
def user_private_role_id(self):
|
||||
user_email = self.user_email()
|
||||
roles_response = self.api_test_case.galaxy_interactor.get("roles", admin=True)
|
||||
roles_response = self.galaxy_interactor.get("roles", admin=True)
|
||||
users_roles = [r for r in roles_response.json() if r["name"] == user_email]
|
||||
assert len(users_roles) == 1
|
||||
return users_roles[0]["id"]
|
||||
|
||||
def create_dataset_request(self, library, **kwds):
|
||||
upload_option = kwds.get("upload_option", "upload_file")
|
||||
create_data = {
|
||||
"folder_id": kwds.get("folder_id", library["root_folder_id"]),
|
||||
"create_type": "file",
|
||||
"files_0|NAME": kwds.get("name", "NewFile"),
|
||||
"upload_option": kwds.get("upload_option", "upload_file"),
|
||||
"upload_option": upload_option,
|
||||
"file_type": kwds.get("file_type", "auto"),
|
||||
"db_key": kwds.get("db_key", "?"),
|
||||
}
|
||||
files = {
|
||||
"files_0|file_data": kwds.get("file", StringIO(kwds.get("contents", "TestData"))),
|
||||
}
|
||||
|
||||
if upload_option == "upload_file":
|
||||
files = {
|
||||
"files_0|file_data": kwds.get("file", StringIO(kwds.get("contents", "TestData"))),
|
||||
}
|
||||
elif upload_option == "upload_paths":
|
||||
create_data["filesystem_paths"] = kwds["paths"]
|
||||
files = {}
|
||||
elif upload_option == "upload_directory":
|
||||
create_data["server_dir"] = kwds["server_dir"]
|
||||
files = {}
|
||||
|
||||
return create_data, files
|
||||
|
||||
def new_library_dataset(self, name, **create_dataset_kwds):
|
||||
library = self.new_private_library(name)
|
||||
payload, files = self.create_dataset_request(library, **create_dataset_kwds)
|
||||
url_rel = "libraries/%s/contents" % (library["id"])
|
||||
dataset = self.api_test_case.galaxy_interactor.post(url_rel, payload, files=files).json()[0]
|
||||
dataset = self.raw_library_contents_create(library["id"], payload, files=files).json()[0]
|
||||
|
||||
def show():
|
||||
return self.api_test_case.galaxy_interactor.get("libraries/%s/contents/%s" % (library["id"], dataset["id"]))
|
||||
return self.galaxy_interactor.get("libraries/%s/contents/%s" % (library["id"], dataset["id"]))
|
||||
|
||||
wait_on_state(show, timeout=DEFAULT_TIMEOUT)
|
||||
return show().json()
|
||||
|
||||
def raw_library_contents_create(self, library_id, payload, files={}):
|
||||
url_rel = "libraries/%s/contents" % library_id
|
||||
return self.galaxy_interactor.post(url_rel, payload, files=files)
|
||||
|
||||
def show_ldda(self, library_id, library_dataset_id):
|
||||
return self.api_test_case.galaxy_interactor.get("libraries/%s/contents/%s" % (library_id, library_dataset_id))
|
||||
return self.galaxy_interactor.get("libraries/%s/contents/%s" % (library_id, library_dataset_id))
|
||||
|
||||
def new_library_dataset_in_private_library(self, library_name="private_dataset", wait=True):
|
||||
library = self.new_private_library(library_name)
|
||||
payload, files = self.create_dataset_request(library, file_type="txt", contents="create_test")
|
||||
create_response = self.api_test_case.galaxy_interactor.post("libraries/%s/contents" % library["id"], payload, files=files)
|
||||
create_response = self.galaxy_interactor.post("libraries/%s/contents" % library["id"], payload, files=files)
|
||||
api_asserts.assert_status_code_is(create_response, 200)
|
||||
library_datasets = create_response.json()
|
||||
assert len(library_datasets) == 1
|
||||
|
||||
@@ -612,6 +612,11 @@ class NavigatesGalaxy(HasDriver):
|
||||
self.components.masthead.libraries.wait_for_and_click()
|
||||
self.components.libraries.selector.wait_for_visible()
|
||||
|
||||
def libraries_open_with_name(self, name):
|
||||
self.libraries_open()
|
||||
self.libraries_index_search_for(name)
|
||||
self.libraries_index_table_elements()[0].find_element_by_css_selector("td a").click()
|
||||
|
||||
@retry_during_transitions
|
||||
def libraries_index_table_elements(self):
|
||||
container = self.wait_for_selector_visible(".library_container")
|
||||
@@ -657,8 +662,7 @@ class NavigatesGalaxy(HasDriver):
|
||||
self.driver.execute_script("$(arguments[0]).keyup();", search_box)
|
||||
|
||||
def libraries_folder_create(self, name):
|
||||
create_folder_button = self.wait_for_selector_clickable("#toolbtn_create_folder")
|
||||
create_folder_button.click()
|
||||
self.components.libraries.folder.add_folder.wait_for_and_click()
|
||||
|
||||
name_text_box = self.wait_for_selector_clickable("input[name='Name']")
|
||||
name_text_box.send_keys(name)
|
||||
@@ -681,6 +685,26 @@ class NavigatesGalaxy(HasDriver):
|
||||
self.wait_for_visible(self.navigation.libraries.folder.selectors.add_items_menu)
|
||||
self.wait_for_and_click(self.navigation.libraries.folder.labels.from_path)
|
||||
|
||||
def libraries_dataset_import_from_history_select(self, to_select_items):
|
||||
self.wait_for_visible(self.navigation.libraries.folder.selectors.import_history_content)
|
||||
history_elements = self.find_elements(self.navigation.libraries.folder.selectors.import_history_contents_items)
|
||||
for to_select_item in to_select_items:
|
||||
found = False
|
||||
for history_element in history_elements:
|
||||
if to_select_item in history_element.text:
|
||||
history_element.find_element_by_css_selector("input").click()
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
raise Exception("Failed to find history item [%s] to select" % to_select_item)
|
||||
|
||||
def libraries_dataset_import_from_history_click_ok(self, wait=True):
|
||||
self.wait_for_and_click(self.navigation.libraries.folder.selectors.import_datasets_ok_button)
|
||||
if wait:
|
||||
# Let the progress bar disappear...
|
||||
self.wait_for_absent_or_hidden(self.navigation.libraries.folder.selectors.import_progress_bar)
|
||||
|
||||
def libraries_table_elements(self):
|
||||
tbody_element = self.wait_for_selector_visible("#folder_list_body")
|
||||
return tbody_element.find_elements_by_css_selector("tr")[1:]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user