mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge branch 'dev' into bam_unsorted
This commit is contained in:
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
|
||||
if command -v ack-grep >/dev/null; then
|
||||
ACK=ack-grep
|
||||
else
|
||||
ACK=ack
|
||||
fi
|
||||
|
||||
export ACK_OPTIONS=" --type python \
|
||||
--ignore-dir=.git/ \
|
||||
--ignore-dir=.tox/ \
|
||||
--ignore-dir=.venv/ \
|
||||
--ignore-dir=client/node_modules/ \
|
||||
--ignore-dir=database/ \
|
||||
--ignore-dir=doc/build/ \
|
||||
--ignore-dir=eggs/ \
|
||||
--ignore-dir=static/maps/ \
|
||||
--ignore-dir=static/scripts/"
|
||||
|
||||
PYTHON2_ONLY_MODULES="__builtin__ _winreg BaseHTTPServer CGIHTTPServer \
|
||||
ConfigParser Cookie cookielib copy_reg cPickle cStringIO Dialog dummy_thread \
|
||||
FileDialog gdbm htmlentitydefs HTMLParser httplib Queue robotparser \
|
||||
ScrolledText SimpleDialog SimpleHTTPServer SimpleXMLRPCServer SocketServer \
|
||||
StringIO thread Tix tkColorChooser tkCommonDialog Tkconstants Tkdnd tkFont \
|
||||
Tkinter tkFileDialog tkMessageBox tkSimpleDialog ttk urllib urllib2 urlparse \
|
||||
xmlrpclib"
|
||||
|
||||
ret=0
|
||||
for mod in $PYTHON2_ONLY_MODULES; do
|
||||
$ACK "^import $mod(\n|\.)|^from $mod import "
|
||||
if [ $? -eq 0 ]; then ret=1; fi
|
||||
done
|
||||
|
||||
exit $ret
|
||||
@@ -10,7 +10,7 @@ bash run.sh --daemon && \
|
||||
sleep 1
|
||||
i=$((i + 1))
|
||||
done
|
||||
kill -9 "$(cat paster.pid)"
|
||||
kill -9 "$(cat galaxy.pid)"
|
||||
echo "exit code:$EXIT_CODE, showing startup log:"
|
||||
cat paster.log
|
||||
cat galaxy.log
|
||||
exit $EXIT_CODE
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
client/galaxy/style/source_material/circle.py
|
||||
contrib/
|
||||
cron/
|
||||
doc/parse_gx_xsd.py
|
||||
doc/patch.py
|
||||
lib/galaxy/actions/
|
||||
lib/galaxy/auth/
|
||||
lib/galaxy/config.py
|
||||
lib/galaxy/containers/
|
||||
lib/galaxy/dataset_collections/
|
||||
lib/galaxy/datatypes/
|
||||
lib/galaxy/dependencies/
|
||||
lib/galaxy/eggs/
|
||||
lib/galaxy/exceptions/
|
||||
lib/galaxy/external_services/
|
||||
lib/galaxy/forms/
|
||||
lib/galaxy/jobs/
|
||||
lib/galaxy/managers/
|
||||
lib/galaxy/model/
|
||||
lib/galaxy/objectstore/
|
||||
lib/galaxy/openid/
|
||||
lib/galaxy/quota/
|
||||
lib/galaxy/sample_tracking/
|
||||
lib/galaxy/security/
|
||||
lib/galaxy/tags/
|
||||
lib/galaxy/tools/
|
||||
lib/galaxy/tours/
|
||||
lib/galaxy/util/
|
||||
lib/galaxy/visualization/
|
||||
lib/galaxy/web/base/
|
||||
lib/galaxy/web/buildapp.py
|
||||
lib/galaxy/web/framework/base.py
|
||||
lib/galaxy/web/framework/decorators.py
|
||||
lib/galaxy/web/framework/helpers/grids.py
|
||||
lib/galaxy/web/framework/__init__.py
|
||||
lib/galaxy/web/framework/middleware/error.py
|
||||
lib/galaxy/web/framework/middleware/static.py
|
||||
lib/galaxy/web/framework/middleware/statsd.py
|
||||
lib/galaxy/web/framework/webapp.py
|
||||
lib/galaxy/web/__init__.py
|
||||
lib/galaxy/webapps/galaxy/api/histories.py
|
||||
lib/galaxy/webapps/galaxy/api/library_datasets.py
|
||||
lib/galaxy/webapps/galaxy/api/tours.py
|
||||
lib/galaxy/webapps/galaxy/api/users.py
|
||||
lib/galaxy/webapps/galaxy/api/workflows.py
|
||||
lib/galaxy/webapps/galaxy/buildapp.py
|
||||
lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
|
||||
lib/galaxy/webapps/galaxy/controllers/external_services.py
|
||||
lib/galaxy/webapps/galaxy/controllers/forms.py
|
||||
lib/galaxy/webapps/galaxy/controllers/history.py
|
||||
lib/galaxy/webapps/galaxy/controllers/library_common.py
|
||||
lib/galaxy/webapps/galaxy/controllers/search.py
|
||||
lib/galaxy/webapps/galaxy/controllers/userskeys.py
|
||||
lib/galaxy/webapps/reports/config.py
|
||||
lib/galaxy/webapps/reports/controllers/tools.py
|
||||
lib/galaxy/webapps/reports/__init__.py
|
||||
lib/galaxy/webapps/tool_shed/config.py
|
||||
lib/galaxy/webapps/tool_shed/controllers/groups.py
|
||||
lib/galaxy/webapps/tool_shed/controllers/user.py
|
||||
lib/galaxy/webapps/tool_shed/framework/middleware/remoteuser.py
|
||||
lib/galaxy/webapps/tool_shed/__init__.py
|
||||
lib/galaxy/webapps/tool_shed/model/__init__.py
|
||||
lib/galaxy/webapps/tool_shed/search/repo_search.py
|
||||
lib/galaxy/webapps/tool_shed/util/ratings_util.py
|
||||
lib/galaxy/webhooks/
|
||||
lib/galaxy/work/
|
||||
lib/galaxy/workflow/
|
||||
lib/galaxy_ext/
|
||||
lib/log_tempfile.py
|
||||
lib/mimeparse.py
|
||||
lib/psyco_full.py
|
||||
lib/tool_shed/
|
||||
scripts/api/
|
||||
scripts/auth/
|
||||
scripts/bootstrap_history.py
|
||||
scripts/build_toolbox.py
|
||||
scripts/check_eggs.py
|
||||
scripts/check_galaxy.py
|
||||
scripts/check_python.py
|
||||
scripts/cleanup_datasets/
|
||||
scripts/communication/
|
||||
scripts/data_libraries/build_whoosh_index.py
|
||||
scripts/db_shell.py
|
||||
scripts/drmaa_external_runner.py
|
||||
scripts/metagenomics/
|
||||
scripts/microbes/BeautifulSoup.py
|
||||
scripts/microbes/harvest_bacteria.py
|
||||
scripts/secret_decoder_ring.py
|
||||
scripts/tool_shed/api/common.py
|
||||
scripts/tool_shed/build_ts_whoosh_index.py
|
||||
scripts/tool_shed/deprecate_repositories_without_metadata.py
|
||||
test/
|
||||
tool_list.py
|
||||
tools/
|
||||
@@ -74,6 +74,7 @@ config/plugins/interactive_environments/**/*.ini
|
||||
!config/plugins
|
||||
static/welcome.html.*
|
||||
static/welcome.html
|
||||
static/client_build_hash.txt
|
||||
|
||||
# Tool data.
|
||||
tool-data/annotation_profiler_options.xml
|
||||
|
||||
+11
-5
@@ -9,18 +9,24 @@ env:
|
||||
- TOX_ENV=py27-unit
|
||||
- TOX_ENV=qunit
|
||||
- TOX_ENV=first_startup
|
||||
- TOX_ENV=validate-test-tools
|
||||
- TOX_ENV=py27-lint-docstring-include-list
|
||||
- TOX_ENV=check-python-dependencies
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env: TOX_ENV=validate-test-tools
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libxml2-utils
|
||||
- env: TOX_ENV=check_py3_compatibility
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ack-grep
|
||||
allow_failures:
|
||||
- env: TOX_ENV=check-python-dependencies
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libxml2-utils
|
||||
|
||||
install:
|
||||
- pip install tox
|
||||
|
||||
@@ -18,6 +18,7 @@ SLIDESHOW_DIR=$(DOC_SOURCE_DIR)/slideshow
|
||||
OPEN_RESOURCE=bash -c 'open $$0 || xdg-open $$0'
|
||||
SLIDESHOW_TO_PDF?=bash -c 'docker run --rm -v `pwd`:/cwd astefanutti/decktape /cwd/$$0 /cwd/`dirname $$0`/`basename -s .html $$0`.pdf'
|
||||
CLIENT_COMMIT_WARNING="Please remember to 'make client-production' when finished developing, before a commit!"
|
||||
YARN := $(shell command -v yarn 2> /dev/null)
|
||||
|
||||
all: help
|
||||
@echo "This makefile is used for building Galaxy's JS client, documentation, and drive the release process. A sensible all target is not implemented."
|
||||
@@ -127,7 +128,13 @@ update-and-commit-dependencies: ## update and commit linting + dev dependencies
|
||||
sh lib/galaxy/dependencies/pipfiles/update.sh -c
|
||||
|
||||
node-deps: ## Install NodeJS dependencies.
|
||||
ifndef YARN
|
||||
@echo "Could not find yarn, which is required to build the Galaxy client.\nTo install yarn, please visit \033[0;34mhttps://yarnpkg.com/en/docs/install\033[0m for instructions, and package information for all platforms.\n"
|
||||
false;
|
||||
else
|
||||
cd client && yarn install --check-files
|
||||
endif
|
||||
|
||||
|
||||
client: node-deps ## Rebuild client-side artifacts for local development.
|
||||
cd client && yarn run build
|
||||
|
||||
+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"]);
|
||||
};
|
||||
|
||||
+9
-11
@@ -3,13 +3,21 @@ Client Build System
|
||||
|
||||
Installs, stages, and builds the client-side scripts necessary for running the
|
||||
Galaxy webapp. There's no need to use this system unless you are modifying or
|
||||
developing client-side scripts.
|
||||
developing client-side scripts, or are running the development branch of
|
||||
Galaxy.
|
||||
|
||||
The base dependencies you will need are Node.js and Yarn. On OSX the easiest
|
||||
way to get set up is using homebrew and the command `brew install nodejs yarn`.
|
||||
More information including instructions for other platforms is available at
|
||||
nodejs.org and yarnpkg.com.
|
||||
|
||||
The Galaxy client build has necessarily grown more complex in the past several
|
||||
years, but we're still trying to keep things as simple as possible for
|
||||
developers (everyone, really). If you're having any trouble with building the
|
||||
client after following the instructions below please create an issue on Github
|
||||
or reach out for help directly on Gitter at
|
||||
https://gitter.im/galaxyproject/Lobby.
|
||||
|
||||
|
||||
Complete Client Build
|
||||
================================================
|
||||
@@ -66,13 +74,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
|
||||
|
||||
@@ -5,13 +5,13 @@ import GalaxyApp from "galaxy";
|
||||
import AdminPanel from "./panels/admin-panel";
|
||||
import FormWrapper from "mvc/form/form-wrapper";
|
||||
import GridView from "mvc/grid/grid-view";
|
||||
import Ui from "mvc/ui/ui-misc";
|
||||
import QueryStringParsing from "utils/query-string-parsing";
|
||||
import Router from "layout/router";
|
||||
import Utils from "utils/utils";
|
||||
import Page from "layout/page";
|
||||
import Vue from "libs/vue";
|
||||
import UserAPIKeys from "components/UserAPIKeys.vue";
|
||||
import UserAPIKeys from "components/admin/UserAPIKeys.vue";
|
||||
import DataTables from "components/admin/DataTables.vue";
|
||||
import Vue from "vue";
|
||||
|
||||
window.app = function app(options, bootstrapped) {
|
||||
window.Galaxy = new GalaxyApp.GalaxyApp(options, bootstrapped);
|
||||
@@ -28,10 +28,11 @@ window.app = function app(options, bootstrapped) {
|
||||
"(/)admin(/)repositories": "show_repositories",
|
||||
"(/)admin(/)forms": "show_forms",
|
||||
"(/)admin(/)form(/)(:form_id)": "show_form",
|
||||
"(/)admin/api_keys": "show_user_api_keys"
|
||||
"(/)admin/api_keys": "show_user_api_keys",
|
||||
"(/)admin/data_tables": "show_data_tables"
|
||||
},
|
||||
|
||||
authenticate: function(args, name) {
|
||||
authenticate: function() {
|
||||
return Galaxy.user && Galaxy.user.id && Galaxy.user.get("is_admin");
|
||||
},
|
||||
|
||||
@@ -39,8 +40,7 @@ window.app = function app(options, bootstrapped) {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}admin/users_list`,
|
||||
url_data: Galaxy.params,
|
||||
dict_format: true
|
||||
url_data: Galaxy.params
|
||||
})
|
||||
);
|
||||
},
|
||||
@@ -49,8 +49,7 @@ window.app = function app(options, bootstrapped) {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}admin/roles_list`,
|
||||
url_data: Galaxy.params,
|
||||
dict_format: true
|
||||
url_data: Galaxy.params
|
||||
})
|
||||
);
|
||||
},
|
||||
@@ -59,8 +58,7 @@ window.app = function app(options, bootstrapped) {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}admin/groups_list`,
|
||||
url_data: Galaxy.params,
|
||||
dict_format: true
|
||||
url_data: Galaxy.params
|
||||
})
|
||||
);
|
||||
},
|
||||
@@ -69,8 +67,7 @@ window.app = function app(options, bootstrapped) {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}admin_toolshed/browse_repositories`,
|
||||
url_data: Galaxy.params,
|
||||
dict_format: true
|
||||
url_data: Galaxy.params
|
||||
})
|
||||
);
|
||||
},
|
||||
@@ -79,8 +76,7 @@ window.app = function app(options, bootstrapped) {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}admin/tool_versions_list`,
|
||||
url_data: Galaxy.params,
|
||||
dict_format: true
|
||||
url_data: Galaxy.params
|
||||
})
|
||||
);
|
||||
},
|
||||
@@ -89,24 +85,28 @@ window.app = function app(options, bootstrapped) {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}admin/quotas_list`,
|
||||
url_data: Galaxy.params,
|
||||
dict_format: true
|
||||
url_data: Galaxy.params
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
show_user_api_keys: function() {
|
||||
var vuemount = document.createElement("div");
|
||||
this.page.display(vuemount);
|
||||
new Vue(UserAPIKeys).$mount(vuemount);
|
||||
var vueMount = document.createElement("div");
|
||||
this.page.display(vueMount);
|
||||
new Vue(UserAPIKeys).$mount(vueMount);
|
||||
},
|
||||
|
||||
show_data_tables: function() {
|
||||
var vueMount = document.createElement("div");
|
||||
this.page.display(vueMount);
|
||||
new Vue(DataTables).$mount(vueMount);
|
||||
},
|
||||
|
||||
show_forms: function() {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}forms/forms_list`,
|
||||
url_data: Galaxy.params,
|
||||
dict_format: true
|
||||
url_data: Galaxy.params
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@ import Ui from "mvc/ui/ui-misc";
|
||||
import DatasetError from "mvc/dataset/dataset-error";
|
||||
import DatasetEditAttributes from "mvc/dataset/dataset-edit-attributes";
|
||||
import Citations from "components/Citations.vue";
|
||||
import Vue from "libs/vue";
|
||||
import Vue from "vue";
|
||||
|
||||
/** define the 'Analyze Data'/analysis/main/home page for Galaxy
|
||||
* * has a masthead
|
||||
@@ -47,6 +47,7 @@ window.app = function app(options, bootstrapped) {
|
||||
"(/)tours(/)(:tour_id)": "show_tours",
|
||||
"(/)user(/)": "show_user",
|
||||
"(/)user(/)(:form_id)": "show_user_form",
|
||||
"(/)openids(/)list": "show_openids",
|
||||
"(/)pages(/)create(/)": "show_pages_create",
|
||||
"(/)pages(/)edit(/)": "show_pages_edit",
|
||||
"(/)pages(/)(:action_id)": "show_pages",
|
||||
@@ -115,8 +116,7 @@ window.app = function app(options, bootstrapped) {
|
||||
show_workflows_published: function() {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}workflow/list_published`,
|
||||
dict_format: true
|
||||
url_base: `${Galaxy.root}workflow/list_published`
|
||||
})
|
||||
);
|
||||
},
|
||||
@@ -157,11 +157,18 @@ window.app = function app(options, bootstrapped) {
|
||||
);
|
||||
},
|
||||
|
||||
show_openids: function() {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}user/openids_list`
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
show_datasets: function() {
|
||||
this.page.display(
|
||||
new GridView({
|
||||
url_base: `${Galaxy.root}dataset/list`,
|
||||
dict_format: true
|
||||
url_base: `${Galaxy.root}dataset/list`
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -22,7 +22,8 @@ var AdminPanel = Backbone.View.extend({
|
||||
},
|
||||
{
|
||||
title: _l("Data tables"),
|
||||
url: "admin/view_tool_data_tables"
|
||||
url: "admin/data_tables",
|
||||
target: "__use_router__"
|
||||
},
|
||||
{
|
||||
title: _l("Display applications"),
|
||||
|
||||
@@ -57,7 +57,10 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
formattedReferences: function() {
|
||||
return this.citations.reduce((a, b) => a.concat(`<p class="formatted-reference">${this.formattedReference(b)}</p>`), "");
|
||||
return this.citations.reduce(
|
||||
(a, b) => a.concat(`<p class="formatted-reference">${this.formattedReference(b)}</p>`),
|
||||
""
|
||||
);
|
||||
}
|
||||
},
|
||||
created: function() {
|
||||
@@ -187,16 +190,16 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.citations-formatted{
|
||||
.citations-formatted {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.citations-bibtex-text{
|
||||
.citations-bibtex-text {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.citation-padding{
|
||||
padding:5px 10px;
|
||||
.citation-padding {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -60,4 +60,4 @@ export default {
|
||||
.ui-message {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div v-if="message" :class="[status + 'message']">{{ message }}</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Message",
|
||||
props: {
|
||||
message: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: "done"
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">
|
||||
<slot name="title">{{ title }}</slot>
|
||||
</div>
|
||||
<div class="toolFormBody">
|
||||
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" width="100%">
|
||||
<slot name="columns">
|
||||
<th v-for="column in columns" bgcolor="#D8D8D8">{{ column.text }}</th>
|
||||
</slot>
|
||||
<slot name="rows">
|
||||
<template v-for="(row, index) in rows">
|
||||
<tr :class="[index % 2 === 0 ? 'tr' : 'odd_row']">
|
||||
<td v-for="column in columns">{{ row[column.dataIndex] }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
</slot>
|
||||
</table>
|
||||
<div v-if="isLoaded !== undefined && !isLoaded" :style="{ textAlign: 'center', padding: '7px 0' }">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
isLoaded: {
|
||||
type: Boolean
|
||||
},
|
||||
title: {
|
||||
type: String
|
||||
},
|
||||
columns: {
|
||||
type: Array
|
||||
},
|
||||
rows: {
|
||||
type: Array
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<table class="tabletip">
|
||||
<thead>
|
||||
<tr>
|
||||
<th :colspan="dataManagerColumns.length" style="font-size:120%">
|
||||
Data Manager: {{ dataManagerTableName }}
|
||||
<a class="icon-btn" href="javascript:void(0)"
|
||||
@click="handleReloadButtonClick"
|
||||
:title="`Reload ${dataManagerTableName} tool data table`"
|
||||
><span class="fa fa-refresh"></span></a>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th v-for="column in dataManagerColumns">{{ column }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-for="item in dataManagerItems">
|
||||
<tr>
|
||||
<td v-for="column in dataManagerColumns">{{ item[column] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
dataManagerTableName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
dataManagerColumns: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
dataManagerItems: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleReloadButtonClick(event) {
|
||||
this.$emit("reloaddatamanager", this.dataManagerTableName);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div>
|
||||
<message :message="message" :status="status"></message>
|
||||
<component
|
||||
:is="currentView"
|
||||
v-if="status !== 'error'"
|
||||
v-bind="currentProps"
|
||||
@changeview="showDataManager"
|
||||
@reloaddatamanager="reloadDataManager">
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import Message from "../Message.vue";
|
||||
import DataTablesGrid from "./DataTablesGrid.vue";
|
||||
import DataManagerGrid from "./DataManagerGrid.vue";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentView: "data-tables-grid",
|
||||
isLoaded: false,
|
||||
dataTables: [],
|
||||
dataManagerTableName: "",
|
||||
dataManagerColumns: [],
|
||||
dataManagerItems: [],
|
||||
message: "",
|
||||
status: ""
|
||||
};
|
||||
},
|
||||
|
||||
components: {
|
||||
message: Message,
|
||||
"data-tables-grid": DataTablesGrid,
|
||||
"data-manager-grid": DataManagerGrid
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentProps() {
|
||||
let props;
|
||||
|
||||
if (this.currentView === "data-tables-grid") {
|
||||
props = {
|
||||
isLoaded: this.isLoaded,
|
||||
rows: this.dataTables
|
||||
};
|
||||
} else {
|
||||
props = {
|
||||
dataManagerTableName: this.dataManagerTableName,
|
||||
dataManagerColumns: this.dataManagerColumns,
|
||||
dataManagerItems: this.dataManagerItems
|
||||
};
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
showDataManager(dataManagerTableName) {
|
||||
axios
|
||||
.get(`${Galaxy.root}data_manager/tool_data_table_items`, {
|
||||
params: {
|
||||
table_name: dataManagerTableName
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.message = response.data.message;
|
||||
this.status = response.data.status;
|
||||
|
||||
if (response.data.status !== "error" && response.data.status !== "warning") {
|
||||
this.dataManagerTableName = dataManagerTableName;
|
||||
this.dataManagerColumns = response.data.data.columns;
|
||||
this.dataManagerItems = response.data.data.items;
|
||||
this.currentView = "data-manager-grid";
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
},
|
||||
|
||||
reloadDataManager(dataManagerTableName) {
|
||||
axios
|
||||
.get(`${Galaxy.root}data_manager/reload_tool_data_table`, {
|
||||
params: {
|
||||
table_name: dataManagerTableName
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.message = response.data.message;
|
||||
this.status = response.data.status;
|
||||
|
||||
if (response.data.status !== "error" && response.data.status !== "warning") {
|
||||
this.dataManagerItems = response.data.data.items;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
axios
|
||||
.get(`${Galaxy.root}admin/data_tables_list`)
|
||||
.then(response => {
|
||||
this.isLoaded = true;
|
||||
this.dataTables = response.data.data;
|
||||
this.message = response.data.message;
|
||||
this.status = response.data.status;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<base-grid :is-loaded="isLoaded" :columns="columns">
|
||||
<template slot="title">
|
||||
Current data table registry contains {{ rows.length }} data tables
|
||||
</template>
|
||||
<template slot="rows" v-for="(row, index) in rows">
|
||||
<tr :class="[index % 2 === 0 ? 'tr' : 'odd_row']">
|
||||
<td><a href="javascript:void(0)" @click="handleTableNameClick">{{ row.name }}</a></td>
|
||||
<td>{{ row.filename }}</td>
|
||||
<td>{{ row.tool_data_path }}</td>
|
||||
<td>{{ row.errors }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
</base-grid>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseGrid from "./BaseGrid.vue";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
isLoaded: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
rows: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
columns: [
|
||||
{ text: "Name", dataIndex: "name" },
|
||||
{ text: "Filename", dataIndex: "filename" },
|
||||
{ text: "Tool data path", dataIndex: "tool_data_path" },
|
||||
{ text: "Errors", dataIndex: "errors" }
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
components: {
|
||||
"base-grid": BaseGrid
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleTableNameClick(event) {
|
||||
this.$emit("changeview", event.target.text);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -6,9 +6,7 @@
|
||||
export function append_notebook(url) {
|
||||
clear_main_area();
|
||||
$("#main").append(
|
||||
`<iframe frameBorder="0" seamless="seamless" style="width: 100%; height: 100%; overflow:hidden;" scrolling="no" src="${
|
||||
url
|
||||
}"></iframe>`
|
||||
`<iframe frameBorder="0" seamless="seamless" style="width: 100%; height: 100%; overflow:hidden;" scrolling="no" src="${url}"></iframe>`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,9 +19,7 @@ export function clear_main_area() {
|
||||
|
||||
export function display_spinner() {
|
||||
$("#main").append(
|
||||
`<img id="spinner" src="${
|
||||
galaxy_root
|
||||
}static/style/largespinner.gif" style="position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;">`
|
||||
`<img id="spinner" src="${galaxy_root}static/style/largespinner.gif" style="position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;">`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
@@ -154,11 +156,7 @@ WYMeditor.editor.prototype.dialog = function(dialogType, dialogFeatures, bodyHtm
|
||||
}
|
||||
show_modal(
|
||||
"Create Link",
|
||||
`<div><div><label id='link_attribute_label'>URL <span style='float: right; font-size: 90%'><a href='#' id='set_link_id'>Create in-page anchor</a></span></label><br><input type='text' class='wym_href' value='${
|
||||
curURL
|
||||
}' size='40' /></div><div><label>Title</label><br><input type='text' class='wym_title' value='${
|
||||
curTitle
|
||||
}' size='40' /></div><div>`,
|
||||
`<div><div><label id='link_attribute_label'>URL <span style='float: right; font-size: 90%'><a href='#' id='set_link_id'>Create in-page anchor</a></span></label><br><input type='text' class='wym_href' value='${curURL}' size='40' /></div><div><label>Title</label><br><input type='text' class='wym_title' value='${curTitle}' size='40' /></div><div>`,
|
||||
{
|
||||
"Make link": function() {
|
||||
// Get URL, name/title.
|
||||
@@ -332,7 +330,6 @@ WYMeditor.editor.prototype.dialog = function(dialogType, dialogFeatures, bodyHtm
|
||||
|
||||
var grid = new GridView({
|
||||
url_base: item_info.list_ajax_url,
|
||||
dict_format: true,
|
||||
embedded: true
|
||||
});
|
||||
Galaxy.modal.show({
|
||||
@@ -426,7 +423,6 @@ WYMeditor.editor.prototype.dialog = function(dialogType, dialogFeatures, bodyHtm
|
||||
|
||||
var grid = new GridView({
|
||||
url_base: item_info.list_ajax_url,
|
||||
dict_format: true,
|
||||
embedded: true
|
||||
});
|
||||
Galaxy.modal.show({
|
||||
@@ -493,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 );
|
||||
|
||||
@@ -154,9 +154,9 @@ function show_in_overlay(options) {
|
||||
closeButton: true,
|
||||
title: " ",
|
||||
body: $(
|
||||
`<div style='margin: -5px;'><iframe style='margin: 0; padding: 0;' src='${options.url}' width='${
|
||||
width
|
||||
}' height='${height}' scrolling='${scroll}' frameborder='0'></iframe></div>`
|
||||
`<div style='margin: -5px;'><iframe style='margin: 0; padding: 0;' src='${
|
||||
options.url
|
||||
}' width='${width}' height='${height}' scrolling='${scroll}' frameborder='0'></iframe></div>`
|
||||
)
|
||||
});
|
||||
modal.show({ backdrop: true });
|
||||
|
||||
@@ -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 });
|
||||
},
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// legacy grid model, used by reports and toolshed
|
||||
export default Backbone.Model.extend({
|
||||
defaults: {
|
||||
url_base: "",
|
||||
async: false,
|
||||
async_ops: [],
|
||||
categorical_filters: [],
|
||||
filters: {},
|
||||
sort_key: null,
|
||||
show_item_checkboxes: false,
|
||||
advanced_search: false,
|
||||
cur_page: 1,
|
||||
num_pages: 1,
|
||||
operation: undefined,
|
||||
item_ids: undefined
|
||||
},
|
||||
|
||||
/**
|
||||
* Return true if operation can be done asynchronously.
|
||||
*/
|
||||
can_async_op: function(op) {
|
||||
return _.indexOf(this.attributes.async_ops, op) !== -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add filtering criterion.
|
||||
*/
|
||||
add_filter: function(key, value, append) {
|
||||
// Update URL arg with new condition.
|
||||
if (append) {
|
||||
// Update or append value.
|
||||
var cur_val = this.attributes.filters[key];
|
||||
|
||||
var new_val;
|
||||
if (cur_val === null || cur_val === undefined) {
|
||||
new_val = value;
|
||||
} else if (typeof cur_val == "string") {
|
||||
if (cur_val == "All" || cur_val == value) {
|
||||
new_val = value;
|
||||
} else {
|
||||
// Replace string with array.
|
||||
var values = [];
|
||||
values[0] = cur_val;
|
||||
values[1] = value;
|
||||
new_val = values;
|
||||
}
|
||||
} else {
|
||||
// Current value is an array.
|
||||
new_val = cur_val;
|
||||
if (new_val.indexOf(value) === -1) {
|
||||
new_val.push(value);
|
||||
}
|
||||
}
|
||||
this.attributes.filters[key] = new_val;
|
||||
} else {
|
||||
// Replace value.
|
||||
this.attributes.filters[key] = value;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove filtering criterion.
|
||||
*/
|
||||
remove_filter: function(key, condition) {
|
||||
var cur_val = this.attributes.filters[key];
|
||||
if (cur_val === null || cur_val === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof cur_val === "string") {
|
||||
// overwrite/remove condition.
|
||||
this.attributes.filters[key] = "";
|
||||
} else {
|
||||
// filter contains an array of conditions.
|
||||
var condition_index = _.indexOf(cur_val, condition);
|
||||
if (condition_index !== -1) {
|
||||
cur_val[condition_index] = "";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns URL data for obtaining a new grid.
|
||||
*/
|
||||
get_url_data: function() {
|
||||
var url_data = {
|
||||
async: this.attributes.async,
|
||||
sort: this.attributes.sort_key,
|
||||
page: this.attributes.cur_page,
|
||||
show_item_checkboxes: this.attributes.show_item_checkboxes,
|
||||
advanced_search: this.attributes.advanced_search
|
||||
};
|
||||
|
||||
// Add operation, item_ids only if they have values.
|
||||
if (this.attributes.operation) {
|
||||
url_data.operation = this.attributes.operation;
|
||||
}
|
||||
if (this.attributes.item_ids) {
|
||||
url_data.id = this.attributes.item_ids;
|
||||
}
|
||||
|
||||
// Add filter arguments to data, placing "f-" in front of all arguments.
|
||||
var self = this;
|
||||
_.each(_.pairs(self.attributes.filters), k => {
|
||||
url_data[`f-${k[0]}`] = k[1];
|
||||
});
|
||||
return url_data;
|
||||
},
|
||||
|
||||
// Return URL for obtaining a new grid
|
||||
get_url: function(args) {
|
||||
return `${this.get("url_base")}?${$.param(this.get_url_data())}&${$.param(args)}`;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,547 @@
|
||||
// dependencies
|
||||
import Utils from "utils/utils";
|
||||
// grid view templates
|
||||
export default {
|
||||
// template
|
||||
grid: function(options) {
|
||||
var tmpl = "";
|
||||
if (options.embedded) {
|
||||
tmpl = this.grid_header(options) + this.grid_table(options);
|
||||
} else {
|
||||
tmpl = `<div class="loading-elt-overlay"></div><table><tr><td width="75%">${this.grid_header(
|
||||
options
|
||||
)}</td><td></td><td></td></tr><tr><td width="100%" id="grid-message" valign="top"></td><td></td><td></td></tr></table>${this.grid_table(
|
||||
options
|
||||
)}`;
|
||||
}
|
||||
|
||||
// add info text
|
||||
if (options.info_text) {
|
||||
tmpl += `<br><div class="toolParamHelp" style="clear: both;">${options.info_text}</div>`;
|
||||
}
|
||||
|
||||
// return
|
||||
return tmpl;
|
||||
},
|
||||
|
||||
// template
|
||||
grid_table: function() {
|
||||
return `
|
||||
<form method="post" onsubmit="return false;">
|
||||
<table id="grid-table" class="grid">
|
||||
<thead id="grid-table-header"></thead>
|
||||
<tbody id="grid-table-body"></tbody>
|
||||
<tfoot id="grid-table-footer"></tfoot>
|
||||
</table>
|
||||
</form>`;
|
||||
},
|
||||
|
||||
// template
|
||||
grid_header: function(options) {
|
||||
var tmpl = '<div class="grid-header">';
|
||||
if (!options.embedded) {
|
||||
tmpl += `<h2>${options.title}</h2>`;
|
||||
}
|
||||
if (options.global_actions) {
|
||||
tmpl += '<ul class="manage-table-actions">';
|
||||
var show_popup = options.global_actions.length >= 3;
|
||||
if (show_popup) {
|
||||
tmpl +=
|
||||
'<li><a class="action-button" id="popup-global-actions" class="menubutton">Actions</a></li>' +
|
||||
'<div popupmenu="popup-global-actions">';
|
||||
}
|
||||
for (let action of options.global_actions) {
|
||||
tmpl += `<li><a class="action-button use-target" target="${action.target}" href="${
|
||||
action.url_args
|
||||
}" onclick="return false;" >${action.label}</a></li>`;
|
||||
}
|
||||
if (show_popup) {
|
||||
tmpl += "</div>";
|
||||
}
|
||||
tmpl += "</ul>";
|
||||
}
|
||||
if (options.insert) {
|
||||
tmpl += options.insert;
|
||||
}
|
||||
|
||||
// add grid filters
|
||||
tmpl += this.grid_filters(options);
|
||||
tmpl += "</div>";
|
||||
|
||||
// return template
|
||||
return tmpl;
|
||||
},
|
||||
|
||||
// template
|
||||
header: function(options) {
|
||||
// start
|
||||
var tmpl = "<tr>";
|
||||
|
||||
// add checkbox
|
||||
if (options.show_item_checkboxes) {
|
||||
tmpl += "<th>";
|
||||
if (options.items.length > 0) {
|
||||
tmpl +=
|
||||
'<input type="checkbox" id="check_all" name=select_all_checkbox value="true">' +
|
||||
'<input type="hidden" name=select_all_checkbox value="true">';
|
||||
}
|
||||
tmpl += "</th>";
|
||||
}
|
||||
|
||||
// create header elements
|
||||
for (let column of options.columns) {
|
||||
if (column.visible) {
|
||||
tmpl += `<th id="${column.key}-header">`;
|
||||
if (column.href) {
|
||||
tmpl += `<a href="${column.href}" class="sort-link" sort_key="${column.key}">${column.label}</a>`;
|
||||
} else {
|
||||
tmpl += column.label;
|
||||
}
|
||||
tmpl += `<span class="sort-arrow">${column.extra}</span></th>`;
|
||||
}
|
||||
}
|
||||
|
||||
// finalize
|
||||
tmpl += "</tr>";
|
||||
|
||||
// return template
|
||||
return tmpl;
|
||||
},
|
||||
|
||||
// template
|
||||
body: function(options) {
|
||||
// initialize
|
||||
var tmpl = "";
|
||||
var items_length = options.items.length;
|
||||
|
||||
// empty grid?
|
||||
if (items_length === 0) {
|
||||
// No results.
|
||||
tmpl += '<tr><td colspan="100"><em>No Items</em></td></tr>';
|
||||
}
|
||||
|
||||
// create rows
|
||||
for (let item of options.items) {
|
||||
// Tag current
|
||||
tmpl += "<tr ";
|
||||
if (options.current_item_id == item.id) {
|
||||
tmpl += 'class="current"';
|
||||
}
|
||||
tmpl += ">";
|
||||
|
||||
// Item selection column
|
||||
if (options.show_item_checkboxes) {
|
||||
tmpl += `<td style="width: 1.5em;"><input type="checkbox" name="id" value="${item.encode_id}" id="${
|
||||
item.encode_id
|
||||
}" class="grid-row-select-checkbox" /></td>`;
|
||||
}
|
||||
|
||||
// Data columns
|
||||
for (let column of options.columns) {
|
||||
if (column.visible) {
|
||||
// Nowrap
|
||||
var nowrap = "";
|
||||
if (column.nowrap) {
|
||||
nowrap = 'style="white-space:nowrap;"';
|
||||
}
|
||||
|
||||
// get column settings
|
||||
var column_settings = item.column_config[column.label];
|
||||
|
||||
// load attributes
|
||||
var link = column_settings.link;
|
||||
var value = column_settings.value;
|
||||
var target = column_settings.target;
|
||||
|
||||
// unescape value
|
||||
if (jQuery.type(value) === "string") {
|
||||
value = value.replace(/\/\//g, "/");
|
||||
}
|
||||
|
||||
// Attach popup menu?
|
||||
var id = "";
|
||||
var cls = "";
|
||||
if (column.attach_popup) {
|
||||
id = `grid-${item.encode_id}-popup`;
|
||||
cls = "menubutton";
|
||||
if (link !== "") {
|
||||
cls += " split";
|
||||
}
|
||||
cls += " popup";
|
||||
}
|
||||
|
||||
// Check for row wrapping
|
||||
tmpl += `<td ${nowrap}>`;
|
||||
|
||||
// Link
|
||||
if (link) {
|
||||
if (options.operations.length !== 0) {
|
||||
tmpl += `<div id="${id}" class="${cls}" style="float: left;">`;
|
||||
}
|
||||
tmpl += `<a class="menubutton-label use-target" target="${target}" href="${link}" onclick="return false;">${value}</a>`;
|
||||
if (options.operations.length !== 0) {
|
||||
tmpl += "</div>";
|
||||
}
|
||||
} else {
|
||||
tmpl += `<div id="${id}" class="${cls}"><label id="${column.label_id_prefix}${
|
||||
item.encode_id
|
||||
}" for="${item.encode_id}">${value || ""}</label></div>`;
|
||||
}
|
||||
tmpl += "</td>";
|
||||
}
|
||||
}
|
||||
tmpl += "</tr>";
|
||||
}
|
||||
return tmpl;
|
||||
},
|
||||
|
||||
// template
|
||||
footer: function(options) {
|
||||
// create template string
|
||||
var tmpl = "";
|
||||
|
||||
// paging
|
||||
if (options.use_paging && options.num_pages > 1) {
|
||||
// get configuration
|
||||
var num_page_links = options.num_page_links;
|
||||
var cur_page_num = options.cur_page_num;
|
||||
var num_pages = options.num_pages;
|
||||
|
||||
// First pass on min page.
|
||||
var page_link_range = num_page_links / 2;
|
||||
var min_page = cur_page_num - page_link_range;
|
||||
var min_offset = 0;
|
||||
if (min_page <= 0) {
|
||||
// Min page is too low.
|
||||
min_page = 1;
|
||||
min_offset = page_link_range - (cur_page_num - min_page);
|
||||
}
|
||||
|
||||
// Set max page.
|
||||
var max_range = page_link_range + min_offset;
|
||||
var max_page = cur_page_num + max_range;
|
||||
var max_offset;
|
||||
if (max_page <= num_pages) {
|
||||
// Max page is fine.
|
||||
max_offset = 0;
|
||||
} else {
|
||||
// Max page is too high.
|
||||
max_page = num_pages;
|
||||
// +1 to account for the +1 in the loop below.
|
||||
max_offset = max_range - (max_page + 1 - cur_page_num);
|
||||
}
|
||||
|
||||
// Second and final pass on min page to add any unused
|
||||
// offset from max to min.
|
||||
if (max_offset !== 0) {
|
||||
min_page -= max_offset;
|
||||
if (min_page < 1) {
|
||||
min_page = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// template header
|
||||
tmpl += '<tr id="page-links-row">';
|
||||
if (options.show_item_checkboxes) {
|
||||
tmpl += "<td></td>";
|
||||
}
|
||||
tmpl += '<td colspan="100">' + '<span id="page-link-container">' + "Page:";
|
||||
|
||||
if (min_page > 1) {
|
||||
tmpl +=
|
||||
'<span class="page-link" id="page-link-1"><a href="javascript:void(0);" page_num="1" onclick="return false;">1</a></span> ...';
|
||||
}
|
||||
|
||||
// create page urls
|
||||
for (var page_index = min_page; page_index < max_page + 1; page_index++) {
|
||||
if (page_index == options.cur_page_num) {
|
||||
tmpl += `<span class="page-link inactive-link" id="page-link-${page_index}">${page_index}</span>`;
|
||||
} else {
|
||||
tmpl += `<span class="page-link" id="page-link-${page_index}"><a href="javascript:void(0);" onclick="return false;" page_num="${page_index}">${page_index}</a></span>`;
|
||||
}
|
||||
}
|
||||
|
||||
// show last page
|
||||
if (max_page < num_pages) {
|
||||
tmpl += `...<span class="page-link" id="page-link-${num_pages}"><a href="javascript:void(0);" onclick="return false;" page_num="${num_pages}">${num_pages}</a></span>`;
|
||||
}
|
||||
tmpl += "</span>";
|
||||
|
||||
// Show all link
|
||||
tmpl += `
|
||||
<span class="page-link" id="show-all-link-span"> | <a href="javascript:void(0);" onclick="return false;" page_num="all">Show All</a></span>
|
||||
</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
// Grid operations for multiple items.
|
||||
if (options.show_item_checkboxes) {
|
||||
// start template
|
||||
tmpl += `
|
||||
<tr>
|
||||
<input type="hidden" id="operation" name="operation" value="">
|
||||
<td></td>
|
||||
<td colspan="100">
|
||||
For <span class="grid-selected-count"></span> selected items:
|
||||
`;
|
||||
|
||||
// configure buttons for operations
|
||||
for (let operation of options.operations) {
|
||||
if (operation.allow_multiple) {
|
||||
tmpl += `<input type="button" value="${
|
||||
operation.label
|
||||
}" class="operation-button action-button"> `;
|
||||
}
|
||||
}
|
||||
|
||||
// finalize template
|
||||
tmpl += "</td>" + "</tr>";
|
||||
}
|
||||
|
||||
// count global operations
|
||||
var found_global = false;
|
||||
for (let operation of options.operations) {
|
||||
if (operation.global_operation) {
|
||||
found_global = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add global operations
|
||||
if (found_global) {
|
||||
tmpl += "<tr>" + '<td colspan="100">';
|
||||
for (let operation of options.operations) {
|
||||
if (operation.global_operation) {
|
||||
tmpl += `<a class="action-button" href="${operation.global_operation}">${operation.label}</a>`;
|
||||
}
|
||||
}
|
||||
tmpl += "</td>" + "</tr>";
|
||||
}
|
||||
|
||||
// add legend
|
||||
if (options.legend) {
|
||||
tmpl += `<tr><td colspan="100">${options.legend}</td></tr>`;
|
||||
}
|
||||
|
||||
// return
|
||||
return tmpl;
|
||||
},
|
||||
|
||||
// template
|
||||
message: function(options) {
|
||||
var status = options.status;
|
||||
if (["success", "ok"].indexOf(status) != -1) {
|
||||
status = "done";
|
||||
}
|
||||
return `<p><div class="${status}message transient-message">${_.escape(
|
||||
options.message
|
||||
)}</div><div style="clear: both"></div></p>`;
|
||||
},
|
||||
|
||||
// template
|
||||
grid_filters: function(options) {
|
||||
// get filters
|
||||
var default_filter_dict = options.default_filter_dict;
|
||||
var filters = options.filters;
|
||||
|
||||
// show advanced search if flag set or if there are filters for advanced search fields
|
||||
var advanced_search_display = "none";
|
||||
if (options.advanced_search) {
|
||||
advanced_search_display = "block";
|
||||
}
|
||||
|
||||
// identify columns with advanced filtering
|
||||
var show_advanced_search_link = false;
|
||||
for (let column of options.columns) {
|
||||
if (column.filterable == "advanced") {
|
||||
var column_key = column.key;
|
||||
var f_key = filters[column_key];
|
||||
var d_key = default_filter_dict[column_key];
|
||||
if (f_key && d_key && f_key != d_key) {
|
||||
advanced_search_display = "block";
|
||||
}
|
||||
show_advanced_search_link = true;
|
||||
}
|
||||
}
|
||||
|
||||
// hide standard search if advanced is shown
|
||||
var standard_search_display = "block";
|
||||
if (advanced_search_display == "block") {
|
||||
standard_search_display = "none";
|
||||
}
|
||||
|
||||
//
|
||||
// standard search
|
||||
//
|
||||
var tmpl = `<div id="standard-search" style="display: ${standard_search_display};"><table><tr><td style="padding: 0;"><table>`;
|
||||
|
||||
// add standard filters
|
||||
for (let column of options.columns) {
|
||||
if (column.filterable == "standard") {
|
||||
tmpl += this.grid_column_filter(options, column);
|
||||
}
|
||||
}
|
||||
|
||||
// finalize standard search
|
||||
tmpl += "</table>" + "</td>" + "</tr>" + "<tr>" + "<td>";
|
||||
|
||||
// show advanced search link in standard display
|
||||
if (show_advanced_search_link) {
|
||||
tmpl += '<a href="" class="advanced-search-toggle">Advanced Search</a>';
|
||||
}
|
||||
|
||||
// finalize standard search display
|
||||
tmpl += "</td>" + "</tr>" + "</table>" + "</div>";
|
||||
|
||||
//
|
||||
// advanced search
|
||||
//
|
||||
tmpl += `<div id="advanced-search" style="display: ${advanced_search_display}; margin-top: 5px; border: 1px solid #ccc;"><table><tr><td style="text-align: left" colspan="100"><a href="" class="advanced-search-toggle">Close Advanced Search</a></td></tr>`;
|
||||
|
||||
// add advanced filters
|
||||
for (let column of options.columns) {
|
||||
if (column.filterable == "advanced") {
|
||||
tmpl += this.grid_column_filter(options, column);
|
||||
}
|
||||
}
|
||||
|
||||
// finalize advanced search template
|
||||
tmpl += "</table>" + "</div>";
|
||||
|
||||
// return template
|
||||
return tmpl;
|
||||
},
|
||||
|
||||
// template
|
||||
grid_column_filter: function(options, column) {
|
||||
// collect parameters
|
||||
var filters = options.filters;
|
||||
var column_label = column.label;
|
||||
var column_key = column.key;
|
||||
if (column.filterable == "advanced") {
|
||||
column_label = column_label.toLowerCase();
|
||||
}
|
||||
|
||||
// start
|
||||
var tmpl = "<tr>";
|
||||
|
||||
if (column.filterable == "advanced") {
|
||||
tmpl += `<td align="left" style="padding-left: 10px">${column_label}:</td>`;
|
||||
}
|
||||
tmpl += '<td style="padding-bottom: 1px;">';
|
||||
if (column.is_text) {
|
||||
tmpl += `<form class="text-filter-form" column_key="${column_key}" action="${options.url}" method="get" >`;
|
||||
// Carry forward filtering criteria with hidden inputs.
|
||||
for (let column of options.columns) {
|
||||
var filter_value = filters[column.key];
|
||||
if (filter_value) {
|
||||
if (filter_value != "All") {
|
||||
if (column.is_text) {
|
||||
filter_value = JSON.stringify(filter_value);
|
||||
}
|
||||
tmpl += `<input type="hidden" id="${column.key}" name="f-${
|
||||
column.key
|
||||
}" value="${filter_value}"/>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Print current filtering criteria and links to delete.
|
||||
tmpl += `<span id="${column_key}-filtering-criteria">`;
|
||||
|
||||
// add filters
|
||||
var column_filter = filters[column_key];
|
||||
if (column_filter) {
|
||||
// identify type
|
||||
var type = jQuery.type(column_filter);
|
||||
|
||||
// single filter value
|
||||
if (type == "string") {
|
||||
if (column_filter != "All") {
|
||||
// append template
|
||||
tmpl += this.filter_element(column_key, column_filter);
|
||||
}
|
||||
}
|
||||
|
||||
// multiple filter values
|
||||
if (type == "array") {
|
||||
for (let i in column_filter) {
|
||||
// copy filters and remove entry
|
||||
var params = column_filter;
|
||||
params = params.slice(i);
|
||||
|
||||
// append template
|
||||
tmpl += this.filter_element(column_key, column_filter[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// close span
|
||||
tmpl += "</span>";
|
||||
|
||||
// Set value, size of search input field. Minimum size is 20 characters.
|
||||
var value = "";
|
||||
var size = 20;
|
||||
if (column.filterable == "standard") {
|
||||
value = column.label.toLowerCase();
|
||||
if (value.length < 20) {
|
||||
size = value.length;
|
||||
}
|
||||
// +4 to account for space after placeholder
|
||||
size = size + 4;
|
||||
}
|
||||
|
||||
// print input field for column
|
||||
tmpl += `
|
||||
<span class="search-box">
|
||||
<input class="search-box-input" id="input-${column_key}-filter" name="f-${column_key}" type="text" placeholder="${value}" size="${size}"/>
|
||||
<button type="submit" style="background: transparent; border: none; padding: 4px; margin: 0px;">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
</form>`;
|
||||
} else {
|
||||
// filter criteria
|
||||
tmpl += `<span id="${column_key}-filtering-criteria">`;
|
||||
|
||||
// add category filters
|
||||
var seperator = false;
|
||||
for (var cf_label in options.categorical_filters[column_key]) {
|
||||
// get category filter
|
||||
var cf = options.categorical_filters[column_key][cf_label];
|
||||
|
||||
// each filter will have only a single argument, so get that single argument
|
||||
var cf_key = "";
|
||||
var cf_arg = "";
|
||||
for (var key in cf) {
|
||||
cf_key = key;
|
||||
cf_arg = cf[key];
|
||||
}
|
||||
|
||||
// add seperator
|
||||
if (seperator) {
|
||||
tmpl += " | ";
|
||||
}
|
||||
seperator = true;
|
||||
|
||||
// add category
|
||||
var filter = filters[column_key];
|
||||
if (filter && cf[column_key] && filter == cf_arg) {
|
||||
tmpl += `<span class="categorical-filter ${column_key}-filter current-filter">${cf_label}</span>`;
|
||||
} else {
|
||||
tmpl += `<span class="categorical-filter ${column_key}-filter"><a href="javascript:void(0);" filter_key="${cf_key}" filter_val="${cf_arg}">${cf_label}</a></span>`;
|
||||
}
|
||||
}
|
||||
tmpl += "</span>";
|
||||
}
|
||||
tmpl += "</td>" + "</tr>";
|
||||
|
||||
// return template
|
||||
return tmpl;
|
||||
},
|
||||
|
||||
// template for filter items
|
||||
filter_element: function(filter_key, filter_value) {
|
||||
filter_value = Utils.sanitize(filter_value);
|
||||
return `<span class="text-filter-val">${filter_value}<a href="javascript:void(0);" filter_key="${filter_key}" filter_val="${filter_value}"><i class="fa fa-times" style="padding-left: 5px; padding-bottom: 6px;"/></a></span>`;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,677 @@
|
||||
// This is necessary so that, when nested arrays are used in ajax/post/get methods, square brackets ('[]') are
|
||||
// not appended to the identifier of a nested array.
|
||||
jQuery.ajaxSettings.traditional = true;
|
||||
|
||||
// dependencies
|
||||
import Utils from "utils/utils";
|
||||
import GridModel from "legacy/grid/grid-model";
|
||||
import Templates from "legacy/grid/grid-template";
|
||||
import PopupMenu from "mvc/ui/popup-menu";
|
||||
// grid view
|
||||
export default Backbone.View.extend({
|
||||
// model
|
||||
grid: null,
|
||||
|
||||
// Initialize
|
||||
initialize: function(grid_config) {
|
||||
this.grid = new GridModel();
|
||||
this.dict_format = grid_config.dict_format;
|
||||
this.title = grid_config.title;
|
||||
var self = this;
|
||||
window.add_tag_to_grid_filter = (tag_name, tag_value) => {
|
||||
// Put tag name and value together.
|
||||
var tag = tag_name + (tag_value !== undefined && tag_value !== "" ? `:${tag_value}` : "");
|
||||
var advanced_search = $("#advanced-search").is(":visible");
|
||||
if (!advanced_search) {
|
||||
$("#standard-search").slideToggle("fast");
|
||||
$("#advanced-search").slideToggle("fast");
|
||||
}
|
||||
self.add_filter_condition("tags", tag);
|
||||
};
|
||||
|
||||
// set element
|
||||
if (this.dict_format) {
|
||||
this.setElement("<div/>");
|
||||
if (grid_config.url_base && !grid_config.items) {
|
||||
var url_data = grid_config.url_data || {};
|
||||
_.each(grid_config.filters, (v, k) => {
|
||||
url_data[`f-${k}`] = v;
|
||||
});
|
||||
$.ajax({
|
||||
url: `${grid_config.url_base}?${$.param(url_data)}`,
|
||||
success: function(response) {
|
||||
response.embedded = grid_config.embedded;
|
||||
response.filters = grid_config.filters || {};
|
||||
self.init_grid(response);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.init_grid(grid_config);
|
||||
}
|
||||
} else {
|
||||
this.setElement("#grid-container");
|
||||
this.init_grid(grid_config);
|
||||
}
|
||||
|
||||
// fix padding
|
||||
if (grid_config.use_panels) {
|
||||
$("#center").css({
|
||||
padding: "10px",
|
||||
overflow: "auto"
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// refresh frames
|
||||
handle_refresh: function(refresh_frames) {
|
||||
if (refresh_frames) {
|
||||
if ($.inArray("history", refresh_frames) > -1) {
|
||||
if (window.top.Galaxy && window.top.Galaxy.currHistoryPanel) {
|
||||
window.top.Galaxy.currHistoryPanel.loadCurrentHistory();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Initialize
|
||||
init_grid: function(grid_config) {
|
||||
this.grid.set(grid_config);
|
||||
|
||||
// get options
|
||||
var options = this.grid.attributes;
|
||||
|
||||
if (this.allow_title_display && options.title) {
|
||||
Utils.setWindowTitle(options.title);
|
||||
}
|
||||
// handle refresh requests
|
||||
this.handle_refresh(options.refresh_frames);
|
||||
|
||||
// strip protocol and domain
|
||||
var url = this.grid.get("url_base");
|
||||
url = url.replace(/^.*\/\/[^\/]+/, "");
|
||||
this.grid.set("url_base", url);
|
||||
|
||||
// append main template
|
||||
this.$el.html(Templates.grid(options));
|
||||
|
||||
// update div contents
|
||||
this.$el.find("#grid-table-header").html(Templates.header(options));
|
||||
this.$el.find("#grid-table-body").html(Templates.body(options));
|
||||
this.$el.find("#grid-table-footer").html(Templates.footer(options));
|
||||
|
||||
// update message
|
||||
if (options.message) {
|
||||
this.$el.find("#grid-message").html(Templates.message(options));
|
||||
var self = this;
|
||||
if (options.use_hide_message) {
|
||||
setTimeout(() => {
|
||||
self.$el.find("#grid-message").html("");
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
// configure elements
|
||||
this.init_grid_elements();
|
||||
this.init_grid_controls();
|
||||
|
||||
// attach global event handler
|
||||
// TODO: redundant (the onload/standard page handlers do this) - but needed because these are constructed after page ready
|
||||
if (window.init_refresh_on_change) {
|
||||
window.init_refresh_on_change();
|
||||
}
|
||||
},
|
||||
|
||||
// Initialize grid controls
|
||||
init_grid_controls: function() {
|
||||
// link
|
||||
var self = this;
|
||||
|
||||
// Initialize grid operation button.
|
||||
this.$el.find(".operation-button").each(function() {
|
||||
$(this).off();
|
||||
$(this).click(function() {
|
||||
self.submit_operation(this);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize text filters to select text on click and use normal font when user is typing.
|
||||
this.$el.find("input[type=text]").each(function() {
|
||||
$(this).off();
|
||||
$(this)
|
||||
.click(function() {
|
||||
$(this).select();
|
||||
})
|
||||
.keyup(function() {
|
||||
$(this).css("font-style", "normal");
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize sort links.
|
||||
this.$el.find(".sort-link").each(function() {
|
||||
$(this).off();
|
||||
$(this).click(function() {
|
||||
self.set_sort_condition($(this).attr("sort_key"));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize text filters.
|
||||
this.$el.find(".text-filter-form").each(function() {
|
||||
$(this).off();
|
||||
$(this).submit(function() {
|
||||
var column_key = $(this).attr("column_key");
|
||||
var text_input_obj = $(`#input-${column_key}-filter`);
|
||||
var text_input = text_input_obj.val();
|
||||
text_input_obj.val("");
|
||||
self.add_filter_condition(column_key, text_input);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize categorical filters.
|
||||
this.$el.find(".text-filter-val > a").each(function() {
|
||||
$(this).off();
|
||||
$(this).click(function() {
|
||||
// Remove visible element.
|
||||
$(this)
|
||||
.parent()
|
||||
.remove();
|
||||
|
||||
// Remove filter condition.
|
||||
self.remove_filter_condition($(this).attr("filter_key"), $(this).attr("filter_val"));
|
||||
|
||||
// Return
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize categorical filters.
|
||||
this.$el.find(".categorical-filter > a").each(function() {
|
||||
$(this).off();
|
||||
$(this).click(function() {
|
||||
self.set_categorical_filter($(this).attr("filter_key"), $(this).attr("filter_val"));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize standard, advanced search toggles.
|
||||
this.$el.find(".advanced-search-toggle").each(function() {
|
||||
$(this).off();
|
||||
$(this).click(() => {
|
||||
self.$el.find("#standard-search").slideToggle("fast");
|
||||
self.$el.find("#advanced-search").slideToggle("fast");
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// Add event to check all box
|
||||
this.$el.find("#check_all").off();
|
||||
this.$el.find("#check_all").on("click", () => {
|
||||
self.check_all_items();
|
||||
});
|
||||
},
|
||||
|
||||
// Initialize grid elements.
|
||||
init_grid_elements: function() {
|
||||
// Initialize grid selection checkboxes.
|
||||
this.$el.find(".grid").each(function() {
|
||||
var checkboxes = $(this).find("input.grid-row-select-checkbox");
|
||||
var check_count = $(this).find("span.grid-selected-count");
|
||||
var update_checked = () => {
|
||||
check_count.text($(checkboxes).filter(":checked").length);
|
||||
};
|
||||
|
||||
$(checkboxes).each(function() {
|
||||
$(this).change(update_checked);
|
||||
});
|
||||
update_checked();
|
||||
});
|
||||
|
||||
// Initialize ratings.
|
||||
if (this.$el.find(".community_rating_star").length !== 0) this.$el.find(".community_rating_star").rating({});
|
||||
|
||||
// get options
|
||||
var options = this.grid.attributes;
|
||||
var self = this;
|
||||
|
||||
//
|
||||
// add page click events
|
||||
//
|
||||
this.$el.find(".page-link > a").each(function() {
|
||||
$(this).click(function() {
|
||||
self.set_page($(this).attr("page_num"));
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
// add inbound/outbound events
|
||||
//
|
||||
this.$el.find(".use-target").each(function() {
|
||||
$(this).click(function() {
|
||||
self.execute({
|
||||
href: $(this).attr("href"),
|
||||
target: $(this).attr("target")
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
// empty grid?
|
||||
var items_length = options.items.length;
|
||||
if (items_length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add operation popup menus
|
||||
_.each(options.items, (item, index) => {
|
||||
var button = self.$(`#grid-${item.encode_id}-popup`).off();
|
||||
var popup = new PopupMenu(button);
|
||||
_.each(options.operations, operation => {
|
||||
self._add_operation(popup, operation, item);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/** Add an operation to the items menu */
|
||||
_add_operation: function(popup, operation, item) {
|
||||
var self = this;
|
||||
var settings = item.operation_config[operation.label];
|
||||
if (settings.allowed && operation.allow_popup) {
|
||||
popup.addItem({
|
||||
html: operation.label,
|
||||
href: settings.url_args,
|
||||
target: settings.target,
|
||||
confirmation_text: operation.confirm,
|
||||
func: function(e) {
|
||||
e.preventDefault();
|
||||
var label = $(e.target).html();
|
||||
if (operation.onclick) {
|
||||
operation.onclick(item.encode_id);
|
||||
} else {
|
||||
self.execute(this.findItemByHtml(label));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Add a condition to the grid filter; this adds the condition and refreshes the grid.
|
||||
add_filter_condition: function(name, value) {
|
||||
// Do nothing is value is empty.
|
||||
if (value === "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add condition to grid.
|
||||
this.grid.add_filter(name, value, true);
|
||||
|
||||
// Add button that displays filter and provides a button to delete it.
|
||||
var t = $(Templates.filter_element(name, value));
|
||||
var self = this;
|
||||
t.click(function() {
|
||||
// Remove visible element.
|
||||
$(this).remove();
|
||||
|
||||
// Remove filter condition.
|
||||
self.remove_filter_condition(name, value);
|
||||
});
|
||||
|
||||
// append to container
|
||||
var container = this.$el.find(`#${name}-filtering-criteria`);
|
||||
container.append(t);
|
||||
|
||||
// execute
|
||||
this.go_page_one();
|
||||
this.execute();
|
||||
},
|
||||
|
||||
// Remove a condition to the grid filter; this adds the condition and refreshes the grid.
|
||||
remove_filter_condition: function(name, value) {
|
||||
// Remove filter condition.
|
||||
this.grid.remove_filter(name, value);
|
||||
|
||||
// Execute
|
||||
this.go_page_one();
|
||||
this.execute();
|
||||
},
|
||||
|
||||
// Set sort condition for grid.
|
||||
set_sort_condition: function(col_key) {
|
||||
// Set new sort condition. New sort is col_key if sorting new column; if reversing sort on
|
||||
// currently sorted column, sort is reversed.
|
||||
var cur_sort = this.grid.get("sort_key");
|
||||
var new_sort = col_key;
|
||||
if (cur_sort.indexOf(col_key) !== -1) {
|
||||
// Reverse sort.
|
||||
if (cur_sort.substring(0, 1) !== "-") {
|
||||
new_sort = `-${col_key}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove sort arrows elements.
|
||||
this.$el.find(".sort-arrow").remove();
|
||||
|
||||
// Add sort arrow element to new sort column.
|
||||
var sort_arrow = new_sort.substring(0, 1) == "-" ? "↑" : "↓";
|
||||
var t = $(`<span>${sort_arrow}</span>`).addClass("sort-arrow");
|
||||
|
||||
// Add to header
|
||||
this.$el.find(`#${col_key}-header`).append(t);
|
||||
|
||||
// Update grid.
|
||||
this.grid.set("sort_key", new_sort);
|
||||
this.go_page_one();
|
||||
this.execute();
|
||||
},
|
||||
|
||||
// Set new value for categorical filter.
|
||||
set_categorical_filter: function(name, new_value) {
|
||||
// Update filter hyperlinks to reflect new filter value.
|
||||
var category_filter = this.grid.get("categorical_filters")[name];
|
||||
|
||||
var cur_value = this.grid.get("filters")[name];
|
||||
var self = this;
|
||||
this.$el.find(`.${name}-filter`).each(function() {
|
||||
var text = $.trim($(this).text());
|
||||
var filter = category_filter[text];
|
||||
var filter_value = filter[name];
|
||||
if (filter_value == new_value) {
|
||||
// Remove filter link since grid will be using this filter. It is assumed that
|
||||
// this element has a single child, a hyperlink/anchor with text.
|
||||
$(this).empty();
|
||||
$(this).addClass("current-filter");
|
||||
$(this).append(text);
|
||||
} else if (filter_value == cur_value) {
|
||||
// Add hyperlink for this filter since grid will no longer be using this filter. It is assumed that
|
||||
// this element has a single child, a hyperlink/anchor.
|
||||
$(this).empty();
|
||||
var t = $(`<a href="#">${text}</a>`);
|
||||
t.click(() => {
|
||||
self.set_categorical_filter(name, filter_value);
|
||||
});
|
||||
$(this).removeClass("current-filter");
|
||||
$(this).append(t);
|
||||
}
|
||||
});
|
||||
|
||||
// Update grid.
|
||||
this.grid.add_filter(name, new_value);
|
||||
this.go_page_one();
|
||||
this.execute();
|
||||
},
|
||||
|
||||
// Set page to view.
|
||||
set_page: function(new_page) {
|
||||
// Update page hyperlink to reflect new page.
|
||||
var self = this;
|
||||
this.$el.find(".page-link").each(function() {
|
||||
var id = $(this).attr("id");
|
||||
|
||||
var // Id has form 'page-link-<page_num>
|
||||
page_num = parseInt(id.split("-")[2], 10);
|
||||
|
||||
var cur_page = self.grid.get("cur_page");
|
||||
var text;
|
||||
if (page_num === new_page) {
|
||||
// Remove link to page since grid will be on this page. It is assumed that
|
||||
// this element has a single child, a hyperlink/anchor with text.
|
||||
text = $(this)
|
||||
.children()
|
||||
.text();
|
||||
$(this).empty();
|
||||
$(this).addClass("inactive-link");
|
||||
$(this).text(text);
|
||||
} else if (page_num === cur_page) {
|
||||
// Add hyperlink to this page since grid will no longer be on this page. It is assumed that
|
||||
// this element has a single child, a hyperlink/anchor.
|
||||
text = $(this).text();
|
||||
$(this).empty();
|
||||
$(this).removeClass("inactive-link");
|
||||
var t = $(`<a href="#">${text}</a>`);
|
||||
t.click(() => {
|
||||
self.set_page(page_num);
|
||||
});
|
||||
$(this).append(t);
|
||||
}
|
||||
});
|
||||
|
||||
if (new_page === "all") {
|
||||
this.grid.set("cur_page", new_page);
|
||||
} else {
|
||||
this.grid.set("cur_page", parseInt(new_page, 10));
|
||||
}
|
||||
this.execute();
|
||||
},
|
||||
|
||||
// confirmation/submission of operation request
|
||||
submit_operation: function(operation_button, confirmation_text) {
|
||||
// identify operation
|
||||
var operation_name = $(operation_button).val();
|
||||
|
||||
// verify any item is selected
|
||||
var number_of_checked_ids = this.$el.find('input[name="id"]:checked').length;
|
||||
if (number_of_checked_ids < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to see if there's grid confirmation text for this operation
|
||||
var operation = _.findWhere(this.grid.attributes.operations, {
|
||||
label: operation_name
|
||||
});
|
||||
if (operation && !confirmation_text) {
|
||||
confirmation_text = operation.confirm || "";
|
||||
}
|
||||
|
||||
// collect ids
|
||||
var item_ids = [];
|
||||
this.$el.find("input[name=id]:checked").each(function() {
|
||||
item_ids.push($(this).val());
|
||||
});
|
||||
|
||||
// execute operation
|
||||
var options = {
|
||||
operation: operation_name,
|
||||
id: item_ids,
|
||||
confirmation_text: confirmation_text
|
||||
};
|
||||
if (operation.target == "top" || operation.target == "center") {
|
||||
options = _.extend(options, {
|
||||
href: operation.href,
|
||||
target: operation.target
|
||||
});
|
||||
}
|
||||
this.execute(options);
|
||||
return true;
|
||||
},
|
||||
|
||||
check_all_items: function() {
|
||||
var check = this.$(".grid-row-select-checkbox");
|
||||
var state = this.$("#check_all").prop("checked");
|
||||
_.each(check, c => {
|
||||
$(c).prop("checked", state);
|
||||
});
|
||||
this.init_grid_elements();
|
||||
},
|
||||
|
||||
// Go back to page one; this is useful when a filter is applied.
|
||||
go_page_one: function() {
|
||||
// Need to go back to page 1 if not showing all.
|
||||
var cur_page = this.grid.get("cur_page");
|
||||
if (cur_page !== null && cur_page !== undefined && cur_page !== "all") {
|
||||
this.grid.set("cur_page", 1);
|
||||
}
|
||||
},
|
||||
|
||||
//
|
||||
// execute operations and hyperlink requests
|
||||
//
|
||||
execute: function(options) {
|
||||
// get url
|
||||
var id = null;
|
||||
var href = null;
|
||||
var operation = null;
|
||||
var confirmation_text = null;
|
||||
var target = null;
|
||||
|
||||
// check for options
|
||||
if (options) {
|
||||
// get options
|
||||
href = options.href;
|
||||
operation = options.operation;
|
||||
id = options.id;
|
||||
confirmation_text = options.confirmation_text;
|
||||
target = options.target;
|
||||
|
||||
// check if input contains the operation tag
|
||||
if (href !== undefined && href.indexOf("operation=") != -1) {
|
||||
// Get operation, id in hyperlink's href.
|
||||
var href_parts = href.split("?");
|
||||
if (href_parts.length > 1) {
|
||||
var href_parms_str = href_parts[1];
|
||||
var href_parms = href_parms_str.split("&");
|
||||
for (var index = 0; index < href_parms.length; index++) {
|
||||
if (href_parms[index].indexOf("operation") != -1) {
|
||||
// Found operation parm; get operation value.
|
||||
operation = href_parms[index].split("=")[1];
|
||||
operation = operation.replace(/\+/g, " ");
|
||||
} else if (href_parms[index].indexOf("id") != -1) {
|
||||
// Found id parm; get id value.
|
||||
id = href_parms[index].split("=")[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for operation details
|
||||
if (operation && id) {
|
||||
// show confirmation box
|
||||
if (
|
||||
confirmation_text &&
|
||||
confirmation_text !== "" &&
|
||||
confirmation_text != "None" &&
|
||||
confirmation_text != "null"
|
||||
)
|
||||
if (!confirm(confirmation_text)) return false;
|
||||
|
||||
// use small characters for operation?!
|
||||
operation = operation.toLowerCase();
|
||||
|
||||
// Update grid.
|
||||
this.grid.set({
|
||||
operation: operation,
|
||||
item_ids: id
|
||||
});
|
||||
|
||||
// Do operation. If operation cannot be performed asynchronously, redirect to location.
|
||||
if (target == "top") {
|
||||
window.top.location = `${href}?${$.param(this.grid.get_url_data())}`;
|
||||
} else if (target == "center") {
|
||||
$("#galaxy_main").attr("src", `${href}?${$.param(this.grid.get_url_data())}`);
|
||||
} else if (this.grid.can_async_op(operation) || this.dict_format) {
|
||||
this.update_grid();
|
||||
} else {
|
||||
this.go_to(target, href);
|
||||
}
|
||||
|
||||
// done
|
||||
return false;
|
||||
}
|
||||
|
||||
// refresh grid
|
||||
if (href) {
|
||||
this.go_to(target, href);
|
||||
return false;
|
||||
}
|
||||
|
||||
// refresh grid
|
||||
if (this.grid.get("async") || this.dict_format) {
|
||||
this.update_grid();
|
||||
} else {
|
||||
this.go_to(target, href);
|
||||
}
|
||||
|
||||
// done
|
||||
return false;
|
||||
},
|
||||
|
||||
// go to url
|
||||
go_to: function(target, href) {
|
||||
// get aysnc status
|
||||
var async = this.grid.get("async");
|
||||
this.grid.set("async", false);
|
||||
|
||||
// get slide status
|
||||
var advanced_search = this.$el.find("#advanced-search").is(":visible");
|
||||
this.grid.set("advanced_search", advanced_search);
|
||||
|
||||
// get default url
|
||||
if (!href) {
|
||||
href = `${this.grid.get("url_base")}?${$.param(this.grid.get_url_data())}`;
|
||||
}
|
||||
|
||||
// clear grid of transient request attributes.
|
||||
this.grid.set({
|
||||
operation: undefined,
|
||||
item_ids: undefined,
|
||||
async: async
|
||||
});
|
||||
switch (target) {
|
||||
case "center":
|
||||
$("#galaxy_main").attr("src", href);
|
||||
break;
|
||||
case "top":
|
||||
window.top.location = href;
|
||||
break;
|
||||
default:
|
||||
window.location = href;
|
||||
}
|
||||
},
|
||||
|
||||
// Update grid.
|
||||
update_grid: function() {
|
||||
// If there's an operation, do POST; otherwise, do GET.
|
||||
var method = this.grid.get("operation") ? "POST" : "GET";
|
||||
|
||||
// Show overlay to indicate loading and prevent user actions.
|
||||
this.$el.find(".loading-elt-overlay").show();
|
||||
var self = this;
|
||||
$.ajax({
|
||||
type: method,
|
||||
url: self.grid.get("url_base"),
|
||||
data: self.grid.get_url_data(),
|
||||
error: function() {
|
||||
alert("Grid refresh failed");
|
||||
},
|
||||
success: function(response_text) {
|
||||
// backup
|
||||
var embedded = self.grid.get("embedded");
|
||||
var insert = self.grid.get("insert");
|
||||
var advanced_search = self.$el.find("#advanced-search").is(":visible");
|
||||
|
||||
// request new configuration
|
||||
var json = self.dict_format ? response_text : $.parseJSON(response_text);
|
||||
|
||||
// update
|
||||
json.embedded = embedded;
|
||||
json.insert = insert;
|
||||
json.advanced_search = advanced_search;
|
||||
|
||||
// Initialize new grid config
|
||||
self.init_grid(json);
|
||||
|
||||
// Hide loading overlay.
|
||||
self.$el.find(".loading-elt-overlay").hide();
|
||||
},
|
||||
complete: function() {
|
||||
// Clear grid of transient request attributes.
|
||||
self.grid.set({
|
||||
operation: undefined,
|
||||
item_ids: undefined
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -16,53 +16,54 @@ var View = Backbone.View.extend({
|
||||
render: function() {
|
||||
var data_url = `${Galaxy.root}api/datasets/${this.model.get("dataset_id")}`;
|
||||
|
||||
var self = this;
|
||||
|
||||
Utils.get({
|
||||
url: data_url,
|
||||
success: function(dataset) {
|
||||
success: dataset => {
|
||||
var job_url = `${Galaxy.root}api/jobs/${dataset.creating_job}?full=True`;
|
||||
Utils.get({
|
||||
url: job_url,
|
||||
success: function(job) {
|
||||
var job_url = `${Galaxy.root}api/jobs/${dataset.creating_job}?full=True`;
|
||||
self.render_error_page(self, dataset, job);
|
||||
success: job => {
|
||||
this.render_error_page(dataset, job);
|
||||
},
|
||||
error: function(response) {
|
||||
error: response => {
|
||||
var error_response = {
|
||||
status: "error",
|
||||
message: "Error occured while loading the job.",
|
||||
persistent: true,
|
||||
cls: "errormessage"
|
||||
};
|
||||
self.display_message(error_response, self.$(".response-message"));
|
||||
this.display_message(error_response, this.$(".response-message"));
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(response) {
|
||||
error: response => {
|
||||
var error_response = {
|
||||
status: "error",
|
||||
message: "Error occured while loading the dataset.",
|
||||
persistent: true,
|
||||
cls: "errormessage"
|
||||
};
|
||||
self.display_message(error_response, self.$(".response-message"));
|
||||
this.display_message(error_response, this.$(".response-message"));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Render the view */
|
||||
render_error_page: function(self, dataset, job) {
|
||||
self.$el.empty().append(self._templateHeader());
|
||||
self.$el.append("<h2>Dataset Error</h2>");
|
||||
self.$el.append(`<p>An error occured while running the tool <b>${job.tool_id}</b>.</p>`);
|
||||
self.$el.append("<p>Tool execution generated the following messages:</p>");
|
||||
self.$el.append(`<pre class="code">${job.stderr}</pre>`);
|
||||
self.$el.append("<h2>Report This Error</pre>");
|
||||
self.$el.append(
|
||||
"<p>Usually the local Galaxy administrators regularly review errors that occur on the server. However, if you would like to provide additional information (such as what you were trying to do when the error occurred) and a contact e-mail address, we will be better able to investigate your problem and get back to you.</p>"
|
||||
);
|
||||
self.$el.append(self._getBugFormTemplate(dataset, job));
|
||||
render_error_page: function(dataset, job) {
|
||||
this.$el.empty().append(`
|
||||
${this._templateHeader()}
|
||||
<h2>Dataset Error</h2>
|
||||
<p>An error occured while running the tool <b>${job.tool_id}</b>.</p>
|
||||
<p>Tool execution generated the following messages:</p>
|
||||
<pre class="code">${_.escape(job.stderr)}</pre>
|
||||
<h2>Report This Error</h2>
|
||||
<p>
|
||||
Usually the local Galaxy administrators regularly review errors that occur on the server
|
||||
However, if you would like to provide additional information (such as what you were trying
|
||||
to do when the error occurred) and a contact e-mail address, we will be better able to
|
||||
investigate your problem and get back to you.
|
||||
</p>`);
|
||||
this.$el.append(this._getBugFormTemplate(dataset, job));
|
||||
},
|
||||
|
||||
/** Display actions messages */
|
||||
@@ -84,12 +85,11 @@ var View = Backbone.View.extend({
|
||||
|
||||
/** Main template */
|
||||
_templateHeader: function() {
|
||||
return '<div class="page-container edit-attr">' + '<div class="response-message"></div>' + "</div>";
|
||||
return `<div class="page-container edit-attr"><div class="response-message"></div></div>`;
|
||||
},
|
||||
|
||||
/** Convert tab template */
|
||||
_getBugFormTemplate: function(dataset, job) {
|
||||
var self = this;
|
||||
var inputs = [
|
||||
{
|
||||
help: _l("Your email address"),
|
||||
@@ -135,11 +135,11 @@ var View = Backbone.View.extend({
|
||||
title: _l("Report"),
|
||||
cls: "ui-button btn btn-primary",
|
||||
floating: "clear",
|
||||
onclick: function() {
|
||||
onclick: () => {
|
||||
var form_data = form.data.create();
|
||||
var url = `${Galaxy.root}api/jobs/${job.id}/error`;
|
||||
form_data.dataset_id = dataset.id;
|
||||
self.submit(form_data, url);
|
||||
this.submit(form_data, url);
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -149,37 +149,36 @@ var View = Backbone.View.extend({
|
||||
|
||||
/** Make ajax request */
|
||||
submit: function(form_data, url) {
|
||||
var self = this;
|
||||
// Some required metadata
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
data: form_data,
|
||||
success: function(response) {
|
||||
success: response => {
|
||||
// Clear out the div
|
||||
self.$el.empty().append(self._templateHeader());
|
||||
this.$el.empty().append(this._templateHeader());
|
||||
// And display the messages.
|
||||
response.messages.forEach(message => {
|
||||
self.display_message(
|
||||
this.display_message(
|
||||
{
|
||||
status: message[1],
|
||||
message: message[0],
|
||||
persistent: true
|
||||
},
|
||||
self.$(".response-message"),
|
||||
this.$(".response-message"),
|
||||
true,
|
||||
true
|
||||
);
|
||||
});
|
||||
},
|
||||
error: function(response) {
|
||||
error: response => {
|
||||
var error_response = {
|
||||
status: "error",
|
||||
message: "Error occured while saving. Please fill all the required fields and try again.",
|
||||
persistent: true,
|
||||
cls: "errormessage"
|
||||
};
|
||||
self.display_message(error_response, self.$(".response-message"));
|
||||
this.display_message(error_response, this.$(".response-message"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -17,13 +17,6 @@ export default Backbone.Model.extend({
|
||||
item_ids: undefined
|
||||
},
|
||||
|
||||
/**
|
||||
* Return true if operation can be done asynchronously.
|
||||
*/
|
||||
can_async_op: function(op) {
|
||||
return _.indexOf(this.attributes.async_ops, op) !== -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add filtering criterion.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,6 @@ var View = Backbone.View.extend({
|
||||
$.ajax({
|
||||
url: `${Galaxy.root + this.item}/${this.model.get("action_id")}?${$.param(Galaxy.params)}`,
|
||||
success: function(response) {
|
||||
response["dict_format"] = true;
|
||||
self.model.set(response);
|
||||
self.render();
|
||||
}
|
||||
|
||||
@@ -112,14 +112,12 @@ export default {
|
||||
body: function(options) {
|
||||
// initialize
|
||||
var tmpl = "";
|
||||
var num_rows_rendered = 0;
|
||||
var items_length = options.items.length;
|
||||
|
||||
// empty grid?
|
||||
if (items_length === 0) {
|
||||
// No results.
|
||||
tmpl += '<tr><td colspan="100"><em>No Items</em></td></tr>';
|
||||
num_rows_rendered = 1;
|
||||
}
|
||||
|
||||
// create rows
|
||||
@@ -180,9 +178,7 @@ export default {
|
||||
if (options.operations.length !== 0) {
|
||||
tmpl += `<div id="${id}" class="${cls}" style="float: left;">`;
|
||||
}
|
||||
tmpl += `<a class="menubutton-label use-target" target="${target}" href="${
|
||||
link
|
||||
}" onclick="return false;">${value}</a>`;
|
||||
tmpl += `<a class="menubutton-label use-target" target="${target}" href="${link}" onclick="return false;">${value}</a>`;
|
||||
if (options.operations.length !== 0) {
|
||||
tmpl += "</div>";
|
||||
}
|
||||
@@ -195,7 +191,6 @@ export default {
|
||||
}
|
||||
}
|
||||
tmpl += "</tr>";
|
||||
num_rows_rendered++;
|
||||
}
|
||||
return tmpl;
|
||||
},
|
||||
@@ -262,21 +257,13 @@ export default {
|
||||
if (page_index == options.cur_page_num) {
|
||||
tmpl += `<span class="page-link inactive-link" id="page-link-${page_index}">${page_index}</span>`;
|
||||
} else {
|
||||
tmpl += `<span class="page-link" id="page-link-${
|
||||
page_index
|
||||
}"><a href="javascript:void(0);" onclick="return false;" page_num="${page_index}">${
|
||||
page_index
|
||||
}</a></span>`;
|
||||
tmpl += `<span class="page-link" id="page-link-${page_index}"><a href="javascript:void(0);" onclick="return false;" page_num="${page_index}">${page_index}</a></span>`;
|
||||
}
|
||||
}
|
||||
|
||||
// show last page
|
||||
if (max_page < num_pages) {
|
||||
tmpl += `...<span class="page-link" id="page-link-${
|
||||
num_pages
|
||||
}"><a href="javascript:void(0);" onclick="return false;" page_num="${num_pages}">${
|
||||
num_pages
|
||||
}</a></span>`;
|
||||
tmpl += `...<span class="page-link" id="page-link-${num_pages}"><a href="javascript:void(0);" onclick="return false;" page_num="${num_pages}">${num_pages}</a></span>`;
|
||||
}
|
||||
tmpl += "</span>";
|
||||
|
||||
@@ -386,9 +373,7 @@ export default {
|
||||
//
|
||||
// standard search
|
||||
//
|
||||
var tmpl = `<div id="standard-search" style="display: ${
|
||||
standard_search_display
|
||||
};"><table><tr><td style="padding: 0;"><table>`;
|
||||
var tmpl = `<div id="standard-search" style="display: ${standard_search_display};"><table><tr><td style="padding: 0;"><table>`;
|
||||
|
||||
// add standard filters
|
||||
for (let column of options.columns) {
|
||||
@@ -411,9 +396,7 @@ export default {
|
||||
//
|
||||
// advanced search
|
||||
//
|
||||
tmpl += `<div id="advanced-search" style="display: ${
|
||||
advanced_search_display
|
||||
}; margin-top: 5px; border: 1px solid #ccc;"><table><tr><td style="text-align: left" colspan="100"><a href="" class="advanced-search-toggle">Close Advanced Search</a></td></tr>`;
|
||||
tmpl += `<div id="advanced-search" style="display: ${advanced_search_display}; margin-top: 5px; border: 1px solid #ccc;"><table><tr><td style="text-align: left" colspan="100"><a href="" class="advanced-search-toggle">Close Advanced Search</a></td></tr>`;
|
||||
|
||||
// add advanced filters
|
||||
for (let column of options.columns) {
|
||||
@@ -456,9 +439,9 @@ export default {
|
||||
if (column.is_text) {
|
||||
filter_value = JSON.stringify(filter_value);
|
||||
}
|
||||
tmpl += `<input type="hidden" id="${column.key}" name="f-${column.key}" value="${
|
||||
filter_value
|
||||
}"/>`;
|
||||
tmpl += `<input type="hidden" id="${column.key}" name="f-${
|
||||
column.key
|
||||
}" value="${filter_value}"/>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -510,9 +493,7 @@ export default {
|
||||
// print input field for column
|
||||
tmpl += `
|
||||
<span class="search-box">
|
||||
<input class="search-box-input" id="input-${column_key}-filter" name="f-${
|
||||
column_key
|
||||
}" type="text" placeholder="${value}" size="${size}"/>
|
||||
<input class="search-box-input" id="input-${column_key}-filter" name="f-${column_key}" type="text" placeholder="${value}" size="${size}"/>
|
||||
<button type="submit" style="background: transparent; border: none; padding: 4px; margin: 0px;">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
@@ -547,11 +528,7 @@ export default {
|
||||
if (filter && cf[column_key] && filter == cf_arg) {
|
||||
tmpl += `<span class="categorical-filter ${column_key}-filter current-filter">${cf_label}</span>`;
|
||||
} else {
|
||||
tmpl += `<span class="categorical-filter ${
|
||||
column_key
|
||||
}-filter"><a href="javascript:void(0);" filter_key="${cf_key}" filter_val="${cf_arg}">${
|
||||
cf_label
|
||||
}</a></span>`;
|
||||
tmpl += `<span class="categorical-filter ${column_key}-filter"><a href="javascript:void(0);" filter_key="${cf_key}" filter_val="${cf_arg}">${cf_label}</a></span>`;
|
||||
}
|
||||
}
|
||||
tmpl += "</span>";
|
||||
@@ -565,10 +542,6 @@ export default {
|
||||
// template for filter items
|
||||
filter_element: function(filter_key, filter_value) {
|
||||
filter_value = Utils.sanitize(filter_value);
|
||||
return `<span class="text-filter-val">${filter_value}<a href="javascript:void(0);" filter_key="${
|
||||
filter_key
|
||||
}" filter_val="${
|
||||
filter_value
|
||||
}"><i class="fa fa-times" style="padding-left: 5px; padding-bottom: 6px;"/></a></span>`;
|
||||
return `<span class="text-filter-val">${filter_value}<a href="javascript:void(0);" filter_key="${filter_key}" filter_val="${filter_value}"><i class="fa fa-times" style="padding-left: 5px; padding-bottom: 6px;"/></a></span>`;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -15,7 +15,6 @@ export default Backbone.View.extend({
|
||||
// Initialize
|
||||
initialize: function(grid_config) {
|
||||
this.grid = new GridModel();
|
||||
this.dict_format = grid_config.dict_format;
|
||||
this.title = grid_config.title;
|
||||
var self = this;
|
||||
window.add_tag_to_grid_filter = (tag_name, tag_value) => {
|
||||
@@ -30,26 +29,21 @@ export default Backbone.View.extend({
|
||||
};
|
||||
|
||||
// set element
|
||||
if (this.dict_format) {
|
||||
this.setElement("<div/>");
|
||||
if (grid_config.url_base && !grid_config.items) {
|
||||
var url_data = grid_config.url_data || {};
|
||||
_.each(grid_config.filters, (v, k) => {
|
||||
url_data[`f-${k}`] = v;
|
||||
});
|
||||
$.ajax({
|
||||
url: `${grid_config.url_base}?${$.param(url_data)}`,
|
||||
success: function(response) {
|
||||
response.embedded = grid_config.embedded;
|
||||
response.filters = grid_config.filters || {};
|
||||
self.init_grid(response);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.init_grid(grid_config);
|
||||
}
|
||||
this.setElement("<div/>");
|
||||
if (grid_config.url_base && !grid_config.items) {
|
||||
var url_data = grid_config.url_data || {};
|
||||
_.each(grid_config.filters, (v, k) => {
|
||||
url_data[`f-${k}`] = v;
|
||||
});
|
||||
$.ajax({
|
||||
url: `${grid_config.url_base}?${$.param(url_data)}`,
|
||||
success: function(response) {
|
||||
response.embedded = grid_config.embedded;
|
||||
response.filters = grid_config.filters || {};
|
||||
self.init_grid(response);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.setElement("#grid-container");
|
||||
this.init_grid(grid_config);
|
||||
}
|
||||
|
||||
@@ -570,10 +564,8 @@ export default Backbone.View.extend({
|
||||
window.top.location = `${href}?${$.param(this.grid.get_url_data())}`;
|
||||
} else if (target == "center") {
|
||||
$("#galaxy_main").attr("src", `${href}?${$.param(this.grid.get_url_data())}`);
|
||||
} else if (this.grid.can_async_op(operation) || this.dict_format) {
|
||||
this.update_grid();
|
||||
} else {
|
||||
this.go_to(target, href);
|
||||
this.update_grid();
|
||||
}
|
||||
|
||||
// done
|
||||
@@ -587,11 +579,7 @@ export default Backbone.View.extend({
|
||||
}
|
||||
|
||||
// refresh grid
|
||||
if (this.grid.get("async") || this.dict_format) {
|
||||
this.update_grid();
|
||||
} else {
|
||||
this.go_to(target, href);
|
||||
}
|
||||
this.update_grid();
|
||||
|
||||
// done
|
||||
return false;
|
||||
@@ -599,10 +587,6 @@ export default Backbone.View.extend({
|
||||
|
||||
// go to url
|
||||
go_to: function(target, href) {
|
||||
// get aysnc status
|
||||
var async = this.grid.get("async");
|
||||
this.grid.set("async", false);
|
||||
|
||||
// get slide status
|
||||
var advanced_search = this.$el.find("#advanced-search").is(":visible");
|
||||
this.grid.set("advanced_search", advanced_search);
|
||||
@@ -615,8 +599,7 @@ export default Backbone.View.extend({
|
||||
// clear grid of transient request attributes.
|
||||
this.grid.set({
|
||||
operation: undefined,
|
||||
item_ids: undefined,
|
||||
async: async
|
||||
item_ids: undefined
|
||||
});
|
||||
switch (target) {
|
||||
case "center":
|
||||
@@ -652,7 +635,7 @@ export default Backbone.View.extend({
|
||||
var advanced_search = self.$el.find("#advanced-search").is(":visible");
|
||||
|
||||
// request new configuration
|
||||
var json = self.dict_format ? response_text : $.parseJSON(response_text);
|
||||
var json = response_text;
|
||||
|
||||
// update
|
||||
json.embedded = embedded;
|
||||
|
||||
@@ -75,9 +75,7 @@ var HDCAListItemView = _super.extend(
|
||||
} else if (!jobStatesSummary || !jobStatesSummary.hasDetails()) {
|
||||
return `
|
||||
<div class="progress state-progress">
|
||||
<span class="note">Loading job data for ${
|
||||
collectionTypeDescription
|
||||
}.<span class="blinking">..</span></span>
|
||||
<span class="note">Loading job data for ${collectionTypeDescription}.<span class="blinking">..</span></span>
|
||||
<div class="progress-bar info" style="width:100%">
|
||||
</div>`;
|
||||
} else {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -60,7 +60,6 @@ var View = Backbone.View.extend({
|
||||
Utils.get({
|
||||
url: `${Galaxy.root}history/${options.action_id}?${$.param(Galaxy.params)}`,
|
||||
success: function(response) {
|
||||
response.dict_format = true;
|
||||
self.model.set(response);
|
||||
self.render();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -124,9 +124,9 @@ var LibraryView = Backbone.View.extend({
|
||||
placeholder: "Click to select a role",
|
||||
container: self.$el.find(`#${id}`),
|
||||
ajax: {
|
||||
url: `${Galaxy.root}api/libraries/${self.id}/permissions?scope=available&is_library_access=${
|
||||
is_library_access
|
||||
}`,
|
||||
url: `${Galaxy.root}api/libraries/${
|
||||
self.id
|
||||
}/permissions?scope=available&is_library_access=${is_library_access}`,
|
||||
dataType: "json",
|
||||
quietMillis: 100,
|
||||
data: function(term, page) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import Deferred from "utils/deferred";
|
||||
import Ui from "mvc/ui/ui-misc";
|
||||
import FormBase from "mvc/form/form-view";
|
||||
import Citations from "components/Citations.vue";
|
||||
import Vue from "libs/vue";
|
||||
import Vue from "vue";
|
||||
export default FormBase.extend({
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
|
||||
@@ -119,7 +119,7 @@ var View = Backbone.View.extend({
|
||||
input.help = input.step_linked ? `${input.help}, ` : "";
|
||||
input.help += `Output dataset '${connection.output_name}' from step ${parseInt(i) + 1}`;
|
||||
input.step_linked = input.step_linked || [];
|
||||
input.step_linked.push(step);
|
||||
input.step_linked.push({ index: step.index, step_type: step.step_type });
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -200,6 +200,7 @@ var View = Backbone.View.extend({
|
||||
this._renderMessage();
|
||||
this._renderParameters();
|
||||
this._renderHistory();
|
||||
this._renderUseCachedJob();
|
||||
_.each(this.steps, step => {
|
||||
self._renderStep(step);
|
||||
});
|
||||
@@ -311,6 +312,39 @@ var View = Backbone.View.extend({
|
||||
this._append(this.$steps, this.history_form.$el);
|
||||
},
|
||||
|
||||
/** Render job caching option */
|
||||
_renderUseCachedJob: function() {
|
||||
var extra_user_preferences = {};
|
||||
if (Galaxy.user.attributes.preferences && "extra_user_preferences" in Galaxy.user.attributes.preferences) {
|
||||
extra_user_preferences = JSON.parse(Galaxy.user.attributes.preferences.extra_user_preferences);
|
||||
}
|
||||
var display_use_cached_job_checkbox =
|
||||
"use_cached_job|use_cached_job_checkbox" in extra_user_preferences
|
||||
? extra_user_preferences["use_cached_job|use_cached_job_checkbox"]
|
||||
: false;
|
||||
this.display_use_cached_job_checkbox = display_use_cached_job_checkbox === "true";
|
||||
if (this.display_use_cached_job_checkbox) {
|
||||
this.job_options_form = new Form({
|
||||
cls: "ui-portlet-narrow",
|
||||
title: "<b>Job re-use Options</b>",
|
||||
inputs: [
|
||||
{
|
||||
type: "conditional",
|
||||
name: "use_cached_job",
|
||||
test_param: {
|
||||
name: "check",
|
||||
label: "BETA: Attempt to reuse jobs with identical parameters?",
|
||||
type: "boolean",
|
||||
value: "false",
|
||||
help: "This may skip executing jobs that you have already run."
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
this._append(this.$steps, this.job_options_form.$el);
|
||||
}
|
||||
},
|
||||
|
||||
/** Render step */
|
||||
_renderStep: function(step) {
|
||||
var self = this;
|
||||
@@ -510,6 +544,9 @@ var View = Backbone.View.extend({
|
||||
// so that inputs can be batched.
|
||||
batch: true
|
||||
};
|
||||
if (this.display_use_cached_job_checkbox) {
|
||||
job_def["use_cached_job"] = this.job_options_form.data.create()["use_cached_job|check"] === "true";
|
||||
}
|
||||
var validated = true;
|
||||
for (var i in this.forms) {
|
||||
var form = this.forms[i];
|
||||
|
||||
@@ -148,6 +148,28 @@ var View = Backbone.View.extend({
|
||||
"The previous run of this tool failed and other tools were waiting for it to finish successfully. Use this option to resume those tools using the new output(s) of this tool run."
|
||||
});
|
||||
}
|
||||
|
||||
// Job Re-use Options
|
||||
var extra_user_preferences = {};
|
||||
if (Galaxy.user.attributes.preferences && "extra_user_preferences" in Galaxy.user.attributes.preferences) {
|
||||
extra_user_preferences = JSON.parse(Galaxy.user.attributes.preferences.extra_user_preferences);
|
||||
}
|
||||
var use_cached_job =
|
||||
"use_cached_job|use_cached_job_checkbox" in extra_user_preferences
|
||||
? extra_user_preferences["use_cached_job|use_cached_job_checkbox"]
|
||||
: false;
|
||||
if (use_cached_job === "true") {
|
||||
options.inputs.push({
|
||||
label: "BETA: Attempt to re-use jobs with identical parameters ?",
|
||||
help: "This may skip executing jobs that you have already run",
|
||||
name: "use_cached_job",
|
||||
type: "select",
|
||||
display: "radio",
|
||||
ignore: "__ignore__",
|
||||
value: "__ignore__",
|
||||
options: [["No", false], ["Yes", true]]
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/** Submit a regular job.
|
||||
@@ -269,9 +291,7 @@ var View = Backbone.View.extend({
|
||||
} else if (batch_n !== n) {
|
||||
this.form.highlight(
|
||||
input_id,
|
||||
`Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>${
|
||||
n
|
||||
}</b> selection(s) while a previous field contains <b>${batch_n}</b>.`
|
||||
`Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>${n}</b> selection(s) while a previous field contains <b>${batch_n}</b>.`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ var ToolShedRepositoryView = Backbone.View.extend({
|
||||
this.options.tps_select_options = this.templatePanelSelectOptions;
|
||||
this.options.tool_dependencies = models.get("tool_dependencies");
|
||||
this.options.shed_tool_conf = this.templateShedToolConf({
|
||||
stc_html: models.get("shed_conf")
|
||||
shed_tool_confs: models.get("shed_conf")
|
||||
});
|
||||
this.options.panel_section_dict = models.get("panel_section_dict");
|
||||
this.options.api_url = `${Galaxy.root}api/tool_shed_repositories/install?async=True`;
|
||||
@@ -474,7 +474,11 @@ var ToolShedRepositoryView = Backbone.View.extend({
|
||||
'<div class="toolFormTitle">Shed tool configuration file:</div>',
|
||||
'<div class="toolFormBody">',
|
||||
'<div class="form-row">',
|
||||
"<%= stc_html %>",
|
||||
'<select name="shed_tool_conf">',
|
||||
"<% _.each(shed_tool_confs.options, function(conf) { %>",
|
||||
'<option value="<%= conf.value %>"><%= conf.label %></option>',
|
||||
"<% }); %>",
|
||||
"</select>",
|
||||
'<div class="toolParamHelp" style="clear: both;">Select the file whose <b>tool_path</b> setting you want used for installing repositories.</div>',
|
||||
"</div>",
|
||||
"</div>"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -62,7 +62,7 @@ var Model = Backbone.Model.extend({
|
||||
description: _l("Associate OpenIDs with your account."),
|
||||
icon: "fa-openid",
|
||||
onclick: function() {
|
||||
window.location.href = `${Galaxy.root}user/openid_manage?cntrller=user&use_panels=True`;
|
||||
window.location.href = `${Galaxy.root}openids/list`;
|
||||
}
|
||||
},
|
||||
custom_builds: {
|
||||
|
||||
@@ -106,7 +106,7 @@ $.extend(CanvasManager.prototype, {
|
||||
// If it appears that the user is trying to copy/paste text, we
|
||||
// pass that through.
|
||||
if (window.getSelection().toString() === "") {
|
||||
if (this.app.workflow.active_node) {
|
||||
if (this.app.workflow.active_node && this.app.workflow.active_node.type !== "subworkflow") {
|
||||
e.clipboardData.setData(
|
||||
"application/json",
|
||||
JSON.stringify({
|
||||
|
||||
@@ -35,9 +35,7 @@ $.extend(Workflow.prototype, {
|
||||
}
|
||||
if (!this.canLabelOutputWith(toLabel)) {
|
||||
Toastr.warning(
|
||||
`Workflow contains duplicate workflow output labels ${
|
||||
toLabel
|
||||
}. This must be fixed before it can be saved.`
|
||||
`Workflow contains duplicate workflow output labels ${toLabel}. This must be fixed before it can be saved.`
|
||||
);
|
||||
}
|
||||
if (toLabel) {
|
||||
|
||||
@@ -179,13 +179,19 @@ var Node = Backbone.Model.extend({
|
||||
// Remove active class
|
||||
$(element).removeClass("toolForm-active");
|
||||
},
|
||||
set_tool_version: function() {
|
||||
if (this.config_form) {
|
||||
this.tool_version = this.config_form.version;
|
||||
this.content_id = this.config_form.id;
|
||||
}
|
||||
},
|
||||
init_field_data: function(data) {
|
||||
if (data.type) {
|
||||
this.type = data.type;
|
||||
}
|
||||
this.name = data.name;
|
||||
this.config_form = data.config_form;
|
||||
this.tool_version = this.config_form && this.config_form.version;
|
||||
this.set_tool_version();
|
||||
this.tool_state = data.tool_state;
|
||||
this.errors = data.errors;
|
||||
this.tooltip = data.tooltip ? data.tooltip : "";
|
||||
@@ -263,7 +269,7 @@ var Node = Backbone.Model.extend({
|
||||
});
|
||||
this.tool_state = data.tool_state;
|
||||
this.config_form = data.config_form;
|
||||
this.tool_version = this.config_form && this.config_form.version;
|
||||
this.set_tool_version();
|
||||
this.errors = data.errors;
|
||||
this.annotation = data.annotation;
|
||||
this.label = data.label;
|
||||
|
||||
@@ -277,9 +277,7 @@ export default Backbone.View.extend({
|
||||
if (upgrade_message) {
|
||||
window.show_modal(
|
||||
"Issues loading this workflow",
|
||||
`Please review the following issues, possibly resulting from tool upgrades or changes.<p><ul>${
|
||||
upgrade_message
|
||||
}</ul></p>`,
|
||||
`Please review the following issues, possibly resulting from tool upgrades or changes.<p><ul>${upgrade_message}</ul></p>`,
|
||||
{ Continue: hide_modal }
|
||||
);
|
||||
} else {
|
||||
@@ -560,9 +558,7 @@ export default Backbone.View.extend({
|
||||
if (upgrade_message) {
|
||||
window.show_modal(
|
||||
"Subworkflow embedded with changes",
|
||||
`Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>${
|
||||
upgrade_message
|
||||
}</ul>`,
|
||||
`Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>${upgrade_message}</ul>`,
|
||||
{ Continue: hide_modal }
|
||||
);
|
||||
} else {
|
||||
@@ -764,13 +760,15 @@ export default Backbone.View.extend({
|
||||
// Fix width to computed width
|
||||
// Now add floats
|
||||
var buttons = $("<div class='buttons' style='float: right;'></div>");
|
||||
buttons.append(
|
||||
$("<div/>")
|
||||
.addClass("fa-icon-button fa fa-files-o")
|
||||
.click(e => {
|
||||
node.clone();
|
||||
})
|
||||
);
|
||||
if (type !== "subworkflow") {
|
||||
buttons.append(
|
||||
$("<div/>")
|
||||
.addClass("fa-icon-button fa fa-files-o")
|
||||
.click(e => {
|
||||
node.clone();
|
||||
})
|
||||
);
|
||||
}
|
||||
buttons.append(
|
||||
$("<div/>")
|
||||
.addClass("fa-icon-button fa fa-times")
|
||||
|
||||
@@ -5,7 +5,7 @@ import WORKFLOWS from "mvc/workflow/workflow-model";
|
||||
import QueryStringParsing from "utils/query-string-parsing";
|
||||
import _l from "utils/localization";
|
||||
/** View of the individual workflows */
|
||||
var WorkflowItemView = Backbone.View.extend({
|
||||
const WorkflowItemView = Backbone.View.extend({
|
||||
tagName: "tr", // name of (orphan) root tag in this.el
|
||||
initialize: function() {
|
||||
_.bindAll(
|
||||
@@ -33,15 +33,20 @@ var WorkflowItemView = Backbone.View.extend({
|
||||
},
|
||||
|
||||
showInToolPanel: function() {
|
||||
this.model.set("show_in_tool_panel", !this.model.get("show_in_tool_panel"));
|
||||
this.model.save();
|
||||
// This reloads the whole page, so that the workflow appears in the tool panel.
|
||||
// Ideally we would notify only the tool panel of a change
|
||||
window.location = `${Galaxy.root}workflows/list`;
|
||||
this.model.save(
|
||||
{ show_in_tool_panel: !this.model.get("show_in_tool_panel") },
|
||||
{
|
||||
success: function() {
|
||||
window.location = `${Galaxy.root}workflows/list`;
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
removeWorkflow: function() {
|
||||
var wfName = this.model.get("name");
|
||||
const wfName = this.model.get("name");
|
||||
if (window.confirm(`Are you sure you want to delete workflow '${wfName}'?`)) {
|
||||
this.model.destroy({
|
||||
success: function() {
|
||||
@@ -53,8 +58,8 @@ var WorkflowItemView = Backbone.View.extend({
|
||||
},
|
||||
|
||||
renameWorkflow: function() {
|
||||
var oldName = this.model.get("name");
|
||||
var newName = window.prompt(`Enter a new Name for workflow '${oldName}'`, oldName);
|
||||
const oldName = this.model.get("name");
|
||||
const newName = window.prompt(`Enter a new Name for workflow '${oldName}'`, oldName);
|
||||
if (newName) {
|
||||
this.model.save(
|
||||
{ name: newName },
|
||||
@@ -69,16 +74,15 @@ var WorkflowItemView = Backbone.View.extend({
|
||||
},
|
||||
|
||||
copyWorkflow: function() {
|
||||
var self = this;
|
||||
var oldName = this.model.get("name");
|
||||
const oldName = this.model.get("name");
|
||||
$.getJSON(`${this.model.urlRoot}/${this.model.id}/download`, wfJson => {
|
||||
var newName = `Copy of ${oldName}`;
|
||||
var currentOwner = self.model.get("owner");
|
||||
let newName = `Copy of ${oldName}`;
|
||||
const currentOwner = this.model.get("owner");
|
||||
if (currentOwner != Galaxy.user.attributes.username) {
|
||||
newName += ` shared by user ${currentOwner}`;
|
||||
}
|
||||
wfJson.name = newName;
|
||||
self.collection.create(wfJson, {
|
||||
this.collection.create(wfJson, {
|
||||
at: 0,
|
||||
wait: true,
|
||||
success: function() {
|
||||
@@ -96,16 +100,14 @@ var WorkflowItemView = Backbone.View.extend({
|
||||
},
|
||||
|
||||
_rowTemplate: function() {
|
||||
var show = this.model.get("show_in_tool_panel");
|
||||
var wfId = this.model.id;
|
||||
var checkboxHtml = `<input id="show-in-tool-panel" type="checkbox" class="show-in-tool-panel" ${
|
||||
let show = this.model.get("show_in_tool_panel");
|
||||
let wfId = this.model.id;
|
||||
const checkboxHtml = `<input id="show-in-tool-panel" type="checkbox" class="show-in-tool-panel" ${
|
||||
show ? `checked="${show}"` : ""
|
||||
} value="${wfId}">`;
|
||||
var trHtml = `<td><div class="dropdown"><button class="menubutton" type="button" data-toggle="dropdown">${_.escape(
|
||||
const trHtml = `<td><div class="dropdown"><button class="menubutton" type="button" data-toggle="dropdown">${_.escape(
|
||||
this.model.get("name")
|
||||
)}<span class="caret"></span></button>${this._templateActions()}</div></td><td><span><div class="${
|
||||
wfId
|
||||
} tags-display"></div></td><td>${
|
||||
)}<span class="caret"></span></button>${this._templateActions()}</div></td><td><span><div class="${wfId} tags-display"></div></td><td>${
|
||||
this.model.get("owner") === Galaxy.user.attributes.username ? "You" : this.model.get("owner")
|
||||
}</span></td><td>${this.model.get("number_of_steps")}</td><td>${
|
||||
this.model.get("published") ? "Yes" : "No"
|
||||
@@ -114,7 +116,7 @@ var WorkflowItemView = Backbone.View.extend({
|
||||
},
|
||||
|
||||
renderTagEditor: function() {
|
||||
var TagEditor = new TAGS.TagsEditor({
|
||||
const TagEditor = new TAGS.TagsEditor({
|
||||
model: this.model,
|
||||
el: $.find(`.${this.model.id}.tags-display`),
|
||||
workflow_mode: true
|
||||
@@ -152,7 +154,7 @@ var WorkflowItemView = Backbone.View.extend({
|
||||
});
|
||||
|
||||
/** View of the main workflow list page */
|
||||
var WorkflowListView = Backbone.View.extend({
|
||||
const WorkflowListView = Backbone.View.extend({
|
||||
title: _l("Workflows"),
|
||||
initialize: function() {
|
||||
this.setElement("<div/>");
|
||||
@@ -182,18 +184,16 @@ var WorkflowListView = Backbone.View.extend({
|
||||
// TODO: check that file is valid galaxy workflow
|
||||
this.unhighlightDropZone();
|
||||
e.preventDefault();
|
||||
var files = e.dataTransfer.files;
|
||||
var self = this;
|
||||
for (var i = 0, f; (f = files[i]); i++) {
|
||||
self.readWorkflowFiles(f);
|
||||
const files = e.dataTransfer.files;
|
||||
for (let i = 0, f; (f = files[i]); i++) {
|
||||
this.readWorkflowFiles(f);
|
||||
}
|
||||
},
|
||||
|
||||
readWorkflowFiles: function(f) {
|
||||
var self = this;
|
||||
var reader = new FileReader();
|
||||
const reader = new FileReader();
|
||||
reader.onload = theFile => {
|
||||
var wf_json;
|
||||
let wf_json;
|
||||
try {
|
||||
wf_json = JSON.parse(reader.result);
|
||||
} catch (e) {
|
||||
@@ -201,7 +201,7 @@ var WorkflowListView = Backbone.View.extend({
|
||||
wf_json = null;
|
||||
}
|
||||
if (wf_json) {
|
||||
self.collection.create(wf_json, {
|
||||
this.collection.create(wf_json, {
|
||||
at: 0,
|
||||
wait: true,
|
||||
success: function() {
|
||||
@@ -218,8 +218,8 @@ var WorkflowListView = Backbone.View.extend({
|
||||
|
||||
_showArgErrors: _.once(() => {
|
||||
// Parse args out of params, display if there's a message.
|
||||
var msg_text = QueryStringParsing.get("message");
|
||||
var msg_status = QueryStringParsing.get("status");
|
||||
const msg_text = QueryStringParsing.get("message");
|
||||
const msg_status = QueryStringParsing.get("status");
|
||||
if (msg_status === "error") {
|
||||
mod_toastr.error(_.escape(msg_text || "Unknown Error, please report this to an administrator."));
|
||||
} else if (msg_text) {
|
||||
@@ -229,18 +229,17 @@ var WorkflowListView = Backbone.View.extend({
|
||||
|
||||
render: function() {
|
||||
// Add workflow header
|
||||
var header = this._templateHeader();
|
||||
const header = this._templateHeader();
|
||||
// Add the actions buttons
|
||||
var templateActions = this._templateActionButtons();
|
||||
var tableTemplate = this._templateWorkflowTable();
|
||||
const templateActions = this._templateActionButtons();
|
||||
const tableTemplate = this._templateWorkflowTable();
|
||||
this.$el.html(header + templateActions + tableTemplate);
|
||||
var self = this;
|
||||
_(this.collection.models).each(item => {
|
||||
// in case collection is not empty
|
||||
self.appendItem(item);
|
||||
self.confirmDelete(item);
|
||||
this.appendItem(item);
|
||||
this.confirmDelete(item);
|
||||
}, this);
|
||||
var minQueryLength = 3;
|
||||
const minQueryLength = 3;
|
||||
this.searchWorkflow(this.$(".search-wf"), this.$(".workflow-search tr"), minQueryLength);
|
||||
this.adjustActiondropdown();
|
||||
this._showArgErrors();
|
||||
@@ -248,7 +247,7 @@ var WorkflowListView = Backbone.View.extend({
|
||||
},
|
||||
|
||||
appendItem: function(item) {
|
||||
var workflowItemView = new WorkflowItemView({
|
||||
const workflowItemView = new WorkflowItemView({
|
||||
model: item,
|
||||
collection: this.collection
|
||||
});
|
||||
@@ -258,7 +257,7 @@ var WorkflowListView = Backbone.View.extend({
|
||||
|
||||
/** Add confirm box before removing/unsharing workflow */
|
||||
confirmDelete: function(workflow) {
|
||||
var $el_shared_wf_link = this.$(`.link-confirm-shared-${workflow.id}`);
|
||||
const $el_shared_wf_link = this.$(`.link-confirm-shared-${workflow.id}`);
|
||||
$el_shared_wf_link.click(() =>
|
||||
window.confirm(`Are you sure you want to remove the shared workflow '${workflow.attributes.name}'?`)
|
||||
);
|
||||
@@ -267,12 +266,12 @@ var WorkflowListView = Backbone.View.extend({
|
||||
/** Implement client side workflow search/filtering */
|
||||
searchWorkflow: function($el_searchinput, $el_tabletr, min_querylen) {
|
||||
$el_searchinput.on("keyup", function() {
|
||||
var query = $(this).val();
|
||||
const query = $(this).val();
|
||||
// Filter when query is at least 3 characters
|
||||
// otherwise show all rows
|
||||
if (query.length >= min_querylen) {
|
||||
// Ignore the query's case using 'i'
|
||||
var regular_expression = new RegExp(query, "i");
|
||||
const regular_expression = new RegExp(query, "i");
|
||||
$el_tabletr.hide();
|
||||
$el_tabletr
|
||||
.filter(function() {
|
||||
@@ -313,7 +312,7 @@ var WorkflowListView = Backbone.View.extend({
|
||||
|
||||
/** Template for workflow table */
|
||||
_templateWorkflowTable: function() {
|
||||
var tableHtml =
|
||||
const tableHtml =
|
||||
'<table class="table colored"><thead>' +
|
||||
'<tr class="header">' +
|
||||
"<th>Name</th>" +
|
||||
@@ -323,9 +322,7 @@ var WorkflowListView = Backbone.View.extend({
|
||||
"<th>Published</th>" +
|
||||
"<th>Show in tools panel</th>" +
|
||||
"</tr></thead>";
|
||||
return `${
|
||||
tableHtml
|
||||
}<tbody class="workflow-search "><div class="hidden_description_layer"><p>Drop workflow files here to import</p></tbody></table></div>`;
|
||||
return `${tableHtml}<tbody class="workflow-search "><div class="hidden_description_layer"><p>Drop workflow files here to import</p></tbody></table></div>`;
|
||||
},
|
||||
|
||||
/** Main template */
|
||||
@@ -343,7 +340,7 @@ var WorkflowListView = Backbone.View.extend({
|
||||
}
|
||||
});
|
||||
|
||||
var ImportWorkflowView = Backbone.View.extend({
|
||||
const ImportWorkflowView = Backbone.View.extend({
|
||||
initialize: function() {
|
||||
this.setElement("<div/>");
|
||||
this.render();
|
||||
@@ -351,9 +348,8 @@ var ImportWorkflowView = Backbone.View.extend({
|
||||
|
||||
/** Open page to import workflow */
|
||||
render: function() {
|
||||
var self = this;
|
||||
$.getJSON(`${Galaxy.root}workflow/upload_import_workflow`, options => {
|
||||
self.$el.empty().append(self._mainTemplate(options));
|
||||
this.$el.empty().append(this._mainTemplate(options));
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -208,33 +208,33 @@ define({
|
||||
|
||||
"Edit dataset tags": "Editer les mots-clés du jeu de données",
|
||||
"Edit dataset annotation": "Editer les annotations du jeu de données",
|
||||
"Tool Help": false,
|
||||
"Tool Help": "Aide outil",
|
||||
// ---------------------------------------------------------------------------- admin
|
||||
"Reset passwords": false,
|
||||
"Search Tool Shed": false,
|
||||
"Monitor installing repositories": false,
|
||||
"Manage installed tools": false,
|
||||
"Reset metadata": false,
|
||||
"Download local tool": false,
|
||||
"Tool lineage": false,
|
||||
"Reload a tool's configuration": false,
|
||||
"Review tool migration stages": false,
|
||||
"View Tool Error Logs": false,
|
||||
"Manage Display Whitelist": false,
|
||||
"Manage Tool Dependencies": false,
|
||||
"Reset passwords": "Réinitialiser les mots de passe",
|
||||
"Search Tool Shed": "Chercher via un Tool Shed",
|
||||
"Monitor installing repositories": "Contrôler les dépôts installés",
|
||||
"Manage installed tools": "Gérer les outils installés",
|
||||
"Reset metadata": "Réinitialiser les métadonnées",
|
||||
"Download local tool": "Télécharger un outil en local",
|
||||
"Tool lineage": "Affiliation des outils",
|
||||
"Reload a tool's configuration": "Recharger une configuration d'outils",
|
||||
"Review tool migration stages": "Vérifier les étapes de migration d'outils",
|
||||
"View Tool Error Logs": "Voir les logs d'erreur d'outils",
|
||||
"Manage Display Whitelist": "Gérer la liste blanche d'outils graphiques",
|
||||
"Manage Tool Dependencies": "Gérer les dépendances d'outils",
|
||||
Users: false,
|
||||
Groups: false,
|
||||
"API keys": false,
|
||||
"Impersonate a user": false,
|
||||
"API keys": "Clé d'API",
|
||||
"Impersonate a user": "Prendre la place d'un utilisateur",
|
||||
Data: false,
|
||||
Quotas: false,
|
||||
Roles: false,
|
||||
"Local data": false,
|
||||
"Form Definitions": false,
|
||||
"Local data": "Données locales",
|
||||
"Form Definitions": "Définitions de formulaires",
|
||||
|
||||
// ---------------------------------------------------------------------------- Scratchbook
|
||||
"Enable/Disable Scratchbook": false,
|
||||
"Show/Hide Scratchbook": false,
|
||||
"Enable/Disable Scratchbook": "Activer/Désactiver la visu Scratchbook",
|
||||
"Show/Hide Scratchbook": "Montrer/cacher la visu Scratchbook",
|
||||
|
||||
// ---------------------------------------------------------------------------- misc. MVC
|
||||
Tags: "Mots-clés",
|
||||
@@ -246,24 +246,25 @@ define({
|
||||
Trackster: false,
|
||||
Visualize: false,
|
||||
// ---------------------------------------------------------------------------- dataset-error
|
||||
"Any additional comments you can provide regarding what you were doing at the time of the bug.": false,
|
||||
"Your email address": false,
|
||||
"Any additional comments you can provide regarding what you were doing at the time of the bug.":
|
||||
"N'importe quel commentaire que vous pouvez fournir concernant ce que vous faisiez lorsque le bug est apparu",
|
||||
"Your email address": "Votre adresse e-mail",
|
||||
Report: false,
|
||||
"Error Report": false,
|
||||
"Error Report": "Rapport d'erreur",
|
||||
// ---------------------------------------------------------------------------- dataset-li
|
||||
"Dataset details": false,
|
||||
"Dataset details": "Détails du jeu de données",
|
||||
// ---------------------------------------------------------------------------- dataset-edit-attributes
|
||||
"Save permissions.": false,
|
||||
"Change the datatype to a new type.": false,
|
||||
"Convert the datatype to a new format.": false,
|
||||
"Save attributes of the dataset.": false,
|
||||
"Change data type": false,
|
||||
"Edit dataset attributes": false,
|
||||
"Save permissions": false,
|
||||
"Manage dataset permissions": false,
|
||||
"Change datatype": false,
|
||||
"Convert datatype": false,
|
||||
"Convert to new format": false,
|
||||
"Save permissions.": "Sauvegarder les permissions",
|
||||
"Change the datatype to a new type.": "Changer en un nouveau format de données",
|
||||
"Convert the datatype to a new format.": "Convertir le format de données",
|
||||
"Save attributes of the dataset.": "Sauvegarder les attributs du jeu de données",
|
||||
"Change data type": "Changer le format de données",
|
||||
"Edit dataset attributes": "Modifier les attributs du jeu de données",
|
||||
"Save permissions": "Sauvegarder les permissions",
|
||||
"Manage dataset permissions": "Gérer les permissions sur les jeux de données",
|
||||
"Change datatype": "Changer le format de données",
|
||||
"Convert datatype": "Convertir le format de données",
|
||||
"Convert to new format": "Convertir en un nouveau format de données",
|
||||
Save: false,
|
||||
Permissions: false,
|
||||
Datatypes: false,
|
||||
@@ -272,16 +273,16 @@ define({
|
||||
// ---------------------------------------------------------------------------- dataset-li-edit
|
||||
Visualization: false,
|
||||
// ---------------------------------------------------------------------------- library-dataset-view
|
||||
"Import into History": false,
|
||||
"Import into History": "Importer dans l'historique",
|
||||
// ---------------------------------------------------------------------------- library-foldertoolbar-view
|
||||
"Location Details": false,
|
||||
"Deleting selected items": false,
|
||||
"Please select folders or files": false,
|
||||
"Please enter paths to import": false,
|
||||
"Adding datasets from your history": false,
|
||||
"Create New Folder": false,
|
||||
"Location Details": "Détails de localisation",
|
||||
"Deleting selected items": "Suppression des objets sélectionnés",
|
||||
"Please select folders or files": "S'il vous plaît sélectionnez des dossiers ou fichiers",
|
||||
"Please enter paths to import": "S'il vous plaît entrer des chemins/URLs à importer",
|
||||
"Adding datasets from your history": "Ajouts de jeux de données à partir de votre historique",
|
||||
"Create New Folder": "Créer un nouveau dossier",
|
||||
// ---------------------------------------------------------------------------- library-librarytoolbar-view
|
||||
"Create New Library": false,
|
||||
"Create New Library": "Créer une nouvelle bibliothèque",
|
||||
// ---------------------------------------------------------------------------- tours
|
||||
Tours: false,
|
||||
// ---------------------------------------------------------------------------- user-preferences
|
||||
|
||||
@@ -1,169 +1,245 @@
|
||||
/** 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": "保存页面",
|
||||
Tools: "工具",
|
||||
|
||||
//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: "历史",
|
||||
// ---- 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();
|
||||
@@ -459,7 +459,6 @@ var TracksterView = Backbone.View.extend({
|
||||
view_in_saved: function(dataset_params) {
|
||||
var tracks_grid = new GridView({
|
||||
url_base: `${Galaxy.root}visualization/list_tracks`,
|
||||
dict_format: true,
|
||||
embedded: true
|
||||
});
|
||||
Galaxy.modal.show({
|
||||
@@ -484,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(
|
||||
@@ -534,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
|
||||
@@ -589,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
|
||||
@@ -605,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) {
|
||||
|
||||
@@ -46,14 +46,12 @@ var select_datasets = (filters, success_fn) => {
|
||||
var history_grid = new GridView({
|
||||
url_base: `${Galaxy.root}visualization/list_history_datasets`,
|
||||
filters: filters,
|
||||
dict_format: true,
|
||||
embedded: true
|
||||
});
|
||||
|
||||
// library dataset selection tab
|
||||
var library_grid = new GridView({
|
||||
url_base: `${Galaxy.root}visualization/list_library_datasets`,
|
||||
dict_format: true,
|
||||
embedded: true
|
||||
});
|
||||
|
||||
|
||||
@@ -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
-2
@@ -34,8 +34,7 @@ var paths = {
|
||||
'jquery-mousewheel': [ 'jquery.mousewheel.js', 'jquery/jquery.mousewheel.js' ],
|
||||
'raven-js': ['dist/raven.js', 'raven.js'],
|
||||
'requirejs': [ 'require.js', 'require.js' ],
|
||||
'underscore': [ 'underscore.js', 'underscore.js' ],
|
||||
'vue': [ 'dist/vue.js', 'vue.js' ]
|
||||
'underscore': [ 'underscore.js', 'underscore.js' ]
|
||||
},
|
||||
libs: ['galaxy/scripts/libs/**/*.js']
|
||||
};
|
||||
|
||||
+12
-11
@@ -28,14 +28,15 @@
|
||||
"raven-js": "^3.17.0",
|
||||
"requirejs": "2",
|
||||
"underscore": "^1.8.3",
|
||||
"vue": "^2.5.3"
|
||||
"vue": "^2.5.9"
|
||||
},
|
||||
"scripts": {
|
||||
"watch": "gulp stage-libs && concurrently \"yarn run webpack-watch\" \"yarn run gulp watch\" \"yarn run style-watch\"",
|
||||
"build": "NODE_ENV=development gulp stage-libs && concurrently \"yarn run style\" \"yarn run webpack\" \"yarn run gulp clean && yarn run gulp\"",
|
||||
"build-production": "NODE_ENV=production gulp stage-libs && concurrently \"yarn run style\" \"yarn run webpack-production\" \"yarn run gulp clean && yarn run gulp-production\"",
|
||||
"build-production-maps": "NODE_ENV=production gulp stage-libs && concurrently \"yarn run style\" \"yarn run webpack-production-maps\" \"yarn run gulp clean && yarn run gulp-production-maps\"",
|
||||
"build": "NODE_ENV=development gulp stage-libs && concurrently \"yarn run style\" \"yarn run webpack\" \"yarn run gulp clean && yarn run gulp\" && yarn run save-build-hash",
|
||||
"build-production": "NODE_ENV=production gulp stage-libs && concurrently \"yarn run style\" \"yarn run webpack-production\" \"yarn run gulp clean && yarn run gulp-production\" && yarn run save-build-hash",
|
||||
"build-production-maps": "NODE_ENV=production gulp stage-libs && concurrently \"yarn run style\" \"yarn run webpack-production-maps\" \"yarn run gulp clean && yarn run gulp-production-maps\" && yarn run save-build-hash",
|
||||
"webpack": "webpack -d",
|
||||
"save-build-hash": "git rev-parse HEAD > ../static/client_build_hash.txt",
|
||||
"webpack-watch": "webpack -d --watch",
|
||||
"webpack-production": "webpack -p",
|
||||
"webpack-production-maps": "GXY_BUILD_SOURCEMAPS=1 webpack -p",
|
||||
@@ -50,16 +51,16 @@
|
||||
"jshint": "jshint --exclude='galaxy/scripts/libs/**' galaxy/scripts/**/*.js",
|
||||
"build-charts": "webpack -p --config ../config/plugins/visualizations/charts/webpack.config.js",
|
||||
"build-scatterplot": "NODE_PATH=./node_modules webpack -p --config ../config/plugins/visualizations/scatterplot/webpack.config.js",
|
||||
"prettier": "prettier --write --tab-width 4 --print-width 120 \"galaxy/scripts/{,!(libs)/**/}/*.js\""
|
||||
"prettier": "prettier --write --tab-width 4 --print-width 120 \"galaxy/scripts/{,!(libs)/**/}/{*.js,*.vue}\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.24.0",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-preset-env": "^1.3.2",
|
||||
"concurrently": "^3.4.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"concurrently": "^3.5.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"del": "^3.0.0",
|
||||
"expose-loader": "^0.7.3",
|
||||
"expose-loader": "^0.7.4",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-bower-install-simple": "^1.1.0",
|
||||
"grunt-cli": "^0.1.13",
|
||||
@@ -87,11 +88,11 @@
|
||||
"karma-webpack": "^2.0.6",
|
||||
"phantomjs-polyfill": "0.0.2",
|
||||
"phantomjs-prebuilt": "^2.1.7",
|
||||
"prettier": "^1.7.4",
|
||||
"prettier": "^1.10.1",
|
||||
"qunitjs": "^2.4.1",
|
||||
"sinon": "^4.1.2",
|
||||
"vue-loader": "^13.5.0",
|
||||
"vue-template-compiler": "^2.5.3",
|
||||
"webpack": "^3.6.0"
|
||||
"vue-template-compiler": "^2.5.9",
|
||||
"webpack": "^3.10.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
});
|
||||
@@ -25,7 +25,7 @@ var commonLibs = [
|
||||
"libs/farbtastic",
|
||||
"libs/bootstrap",
|
||||
"libs/bootstrap-tour",
|
||||
"libs/vue",
|
||||
"vue",
|
||||
// mvc
|
||||
"libs/underscore",
|
||||
"libs/backbone",
|
||||
@@ -78,10 +78,10 @@ let buildconfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
}
|
||||
loader: "vue-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
node: {
|
||||
@@ -99,9 +99,6 @@ let buildconfig = {
|
||||
name: "libs",
|
||||
filename: "libs.bundled.js"
|
||||
}),
|
||||
new webpack.SourceMapDevToolPlugin({
|
||||
filename: '[name].js.map',
|
||||
}),
|
||||
// this plugin allows using the following keys/globals in scripts (w/o req'ing them first)
|
||||
// and webpack will automagically require them in the bundle for you
|
||||
new webpack.ProvidePlugin({
|
||||
@@ -115,8 +112,8 @@ let buildconfig = {
|
||||
]
|
||||
};
|
||||
|
||||
if (process.env.GXY_BUILD_SOURCEMAPS){
|
||||
buildconfig.devtool = 'source-map';
|
||||
if (process.env.GXY_BUILD_SOURCEMAPS || process.env.NODE_ENV == "development") {
|
||||
buildconfig.devtool = "source-map";
|
||||
}
|
||||
|
||||
module.exports = buildconfig;
|
||||
|
||||
+23
-19
@@ -887,9 +887,9 @@ babel-plugin-transform-strict-mode@^6.24.1:
|
||||
babel-runtime "^6.22.0"
|
||||
babel-types "^6.24.1"
|
||||
|
||||
babel-preset-env@^1.3.2:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4"
|
||||
babel-preset-env@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48"
|
||||
dependencies:
|
||||
babel-plugin-check-es2015-constants "^6.22.0"
|
||||
babel-plugin-syntax-trailing-function-commas "^6.22.0"
|
||||
@@ -1659,9 +1659,9 @@ concat-stream@~1.4.6:
|
||||
readable-stream "~1.1.9"
|
||||
typedarray "~0.0.5"
|
||||
|
||||
concurrently@^3.4.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.5.0.tgz#8cf1b7707a6916a78a4ff5b77bb04dec54b379b2"
|
||||
concurrently@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.5.1.tgz#ee8b60018bbe86b02df13e5249453c6ececd2521"
|
||||
dependencies:
|
||||
chalk "0.5.1"
|
||||
commander "2.6.0"
|
||||
@@ -2616,9 +2616,9 @@ expand-tilde@^2.0.2:
|
||||
dependencies:
|
||||
homedir-polyfill "^1.0.1"
|
||||
|
||||
expose-loader@^0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/expose-loader/-/expose-loader-0.7.3.tgz#35fbd3659789e4faa81f59de8b7e9fc39e466d51"
|
||||
expose-loader@^0.7.4:
|
||||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/expose-loader/-/expose-loader-0.7.4.tgz#9bcdd3878b5da9107930b55a03f65afe90b3314a"
|
||||
|
||||
extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
|
||||
version "3.0.1"
|
||||
@@ -5894,7 +5894,11 @@ preserve@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
|
||||
|
||||
prettier@^1.7.0, prettier@^1.7.4:
|
||||
prettier@^1.10.1:
|
||||
version "1.10.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.10.1.tgz#01423fea6957ea23618d37d339ef0e7f7c967fc6"
|
||||
|
||||
prettier@^1.7.0:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.2.tgz#bff83e7fd573933c607875e5ba3abbdffb96aeb8"
|
||||
|
||||
@@ -7495,9 +7499,9 @@ vue-style-loader@^3.0.0:
|
||||
hash-sum "^1.0.2"
|
||||
loader-utils "^1.0.2"
|
||||
|
||||
vue-template-compiler@^2.5.3:
|
||||
version "2.5.3"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.3.tgz#ab631b0694e211a6aaf0d800102b37836aae36a4"
|
||||
vue-template-compiler@^2.5.9:
|
||||
version "2.5.9"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.9.tgz#7fabc73c8d3d12d32340cd86c5fc33e00e86d686"
|
||||
dependencies:
|
||||
de-indent "^1.0.2"
|
||||
he "^1.1.0"
|
||||
@@ -7506,9 +7510,9 @@ vue-template-es2015-compiler@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18"
|
||||
|
||||
vue@^2.5.3:
|
||||
version "2.5.3"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.3.tgz#e1a3b1f49b6e93e574ce040b95cbc873912fecc1"
|
||||
vue@^2.5.9:
|
||||
version "2.5.9"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.9.tgz#b2380cd040915dca69881dafd121d760952e65f7"
|
||||
|
||||
walk-sync@0.3.1:
|
||||
version "0.3.1"
|
||||
@@ -7577,9 +7581,9 @@ webpack@^1.14.0:
|
||||
watchpack "^0.2.1"
|
||||
webpack-core "~0.6.9"
|
||||
|
||||
webpack@^3.6.0:
|
||||
version "3.7.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.7.0.tgz#9081d0b1ba4950e34ddc54195721eba4bf205e83"
|
||||
webpack@^3.10.0:
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.10.0.tgz#5291b875078cf2abf42bdd23afe3f8f96c17d725"
|
||||
dependencies:
|
||||
acorn "^5.0.0"
|
||||
acorn-dynamic-import "^2.0.0"
|
||||
|
||||
@@ -505,6 +505,7 @@
|
||||
<datatype extension="augustus" type="galaxy.datatypes.annotation:Augustus" display_in_upload="true" />
|
||||
<datatype extension="icm" type="galaxy.datatypes.binary:ICM" display_in_upload="true"/>
|
||||
<!-- MSA Datatypes -->
|
||||
<datatype extension="cm" type="galaxy.datatypes.msa:InfernalCM" display_in_upload="False" />
|
||||
<datatype extension="hmm2" type="galaxy.datatypes.msa:Hmmer2" display_in_upload="true" />
|
||||
<datatype extension="hmm3" type="galaxy.datatypes.msa:Hmmer3" display_in_upload="true" />
|
||||
<datatype extension="stockholm" type="galaxy.datatypes.msa:Stockholm_1_0" display_in_upload="true" />
|
||||
@@ -625,6 +626,9 @@
|
||||
<datatype extension="mothur.sff.flow" type="galaxy.datatypes.mothur:SffFlow" display_in_upload="true"/>
|
||||
<datatype extension="mothur.count_table" type="galaxy.datatypes.mothur:CountTable" display_in_upload="true"/>
|
||||
<datatype extension="neostore" type="galaxy.datatypes.neo4j:Neo4jDB" mimetype="text/html" display_in_upload="false"/>
|
||||
<datatype extension="neostore.zip" type="galaxy.datatypes.neo4j:Neo4jDBzip" display_in_upload="true">
|
||||
<converter file="neostorezip_to_neostore_converter.xml" target_datatype="neostore"/>
|
||||
</datatype>
|
||||
<datatype extension="trackhub" type="galaxy.datatypes.tracks:UCSCTrackHub" display_in_upload="true">
|
||||
<display file="ucsc/trackhub.xml" />
|
||||
</datatype>
|
||||
@@ -636,18 +640,27 @@
|
||||
<datatype extension="maskinfo-asn1-binary" type="galaxy.datatypes.binary:GenericAsn1Binary" mimetype="application/octet-stream" subclass="true" display_in_upload="true" />
|
||||
<datatype extension="pssm-asn1" type="galaxy.datatypes.data:GenericAsn1" mimetype="text/plain" subclass="true" display_in_upload="true" />
|
||||
<!-- PlantTribes datatypes -->
|
||||
<!--
|
||||
The commented entries in this section are required by versions 1.0.0, 1.0.1 and 1.0.2 of the
|
||||
PlantTribes tools in the MTS Phylogenetics category, and are not required by version 1.0.3 of
|
||||
later. These datatypes will be removed in a future Galaxy release.
|
||||
-->
|
||||
<!--
|
||||
<datatype extension="ptalign" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignment" />
|
||||
<datatype extension="ptalignca" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignmentCodonAlignment" />
|
||||
<datatype extension="ptaligntrimmed" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignmentTrimmed" />
|
||||
<datatype extension="ptaligntrimmedca" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignmentTrimmedCodonAlignment" />
|
||||
<datatype extension="ptalignfiltered" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignmentFiltered" />
|
||||
<datatype extension="ptalignfilteredca" type="galaxy.datatypes.plant_tribes:PlantTribesMultipleSequenceAlignmentFilteredCodonAlignment" />
|
||||
-->
|
||||
<datatype extension="ptkscmp" type="galaxy.datatypes.plant_tribes:PlantTribesKsComponents" display_in_upload="true"/>
|
||||
<!--
|
||||
<datatype extension="ptortho" type="galaxy.datatypes.plant_tribes:PlantTribesOrtho" />
|
||||
<datatype extension="ptorthocs" type="galaxy.datatypes.plant_tribes:PlantTribesOrthoCodingSequence" />
|
||||
<datatype extension="ptphylip" type="galaxy.datatypes.plant_tribes:PlantTribesPhylip" />
|
||||
<datatype extension="pttgf" type="galaxy.datatypes.plant_tribes:PlantTribesTargetedGeneFamilies" />
|
||||
<datatype extension="pttree" type="galaxy.datatypes.plant_tribes:PlantTribesPhylogeneticTree" />
|
||||
-->
|
||||
<datatype extension="smat" type="galaxy.datatypes.plant_tribes:Smat" display_in_upload="true" />
|
||||
<!-- Start Haplotype / LOD Datatypes -->
|
||||
<datatype extension="alohomora_gts" type="galaxy.datatypes.genetics:GenotypeMatrix" />
|
||||
@@ -789,6 +802,7 @@
|
||||
<sniffer type="galaxy.datatypes.msa:Hmmer3" />
|
||||
<sniffer type="galaxy.datatypes.msa:Stockholm_1_0" />
|
||||
<sniffer type="galaxy.datatypes.msa:MauveXmfa" />
|
||||
<sniffer type="galaxy.datatypes.msa:InfernalCM"/>
|
||||
<sniffer type="galaxy.datatypes.annotation:SnapHmm" />
|
||||
<sniffer type="galaxy.datatypes.binary:Cel" />
|
||||
<sniffer type="galaxy.datatypes.binary:RData" />
|
||||
@@ -820,5 +834,6 @@
|
||||
<sniffer type="galaxy.datatypes.binary:OxliStopTags"/>
|
||||
<sniffer type="galaxy.datatypes.binary:OxliSubset"/>
|
||||
<sniffer type="galaxy.datatypes.binary:OxliGraphLabels"/>
|
||||
<sniffer type="galaxy.datatypes.neo4j:Neo4jDBzip"/>
|
||||
</sniffers>
|
||||
</datatypes>
|
||||
|
||||
@@ -615,6 +615,13 @@ nglims_config_file = tool-data/nglims.yaml
|
||||
# The URL linked by the "Support" link in the "Help" menu.
|
||||
#support_url = https://galaxyproject.org/support
|
||||
|
||||
# The following options enable integration with a custom Biostar instance.
|
||||
#biostar_url = None
|
||||
#biostar_key_name = None
|
||||
#biostar_key = None
|
||||
#biostar_enable_bug_reports = True
|
||||
#biostar_never_authenticate = False
|
||||
|
||||
# The URL linked by the "How to Cite Galaxy" link in the "Help" menu.
|
||||
#citation_url = https://galaxyproject.org/citing-galaxy
|
||||
|
||||
@@ -920,6 +927,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
|
||||
|
||||
@@ -248,6 +248,31 @@
|
||||
a requirement of the other.
|
||||
|
||||
-->
|
||||
<!-- <param id="requests_cpu">500m</param> -->
|
||||
<!-- <param id="requests_memory">500Mi</param> -->
|
||||
<!-- <param id="limits_cpu">2</param> -->
|
||||
<!-- <param id="limits_memory">2Gi</param> -->
|
||||
<!-- Kubernetes resource Requests and Limits
|
||||
Parameters above (requests_* and limits_*) set default minimal (requests) and
|
||||
maximal (limits) CPU and memory resources to be allocated to all containers in
|
||||
Kubernetes jobs by default.
|
||||
|
||||
Limits and requests for CPU resources are measured in cpu units. Fractional requests are allowed. A
|
||||
Container with requests_cpu of 0.5 is guaranteed half as much CPU as one that asks for 1 CPU. The
|
||||
expression 0.1 is equivalent to the expression 100m, which can be read as “one hundred millicpu”. Some
|
||||
people say “one hundred millicores”, and this is understood to mean the same thing. A request with a
|
||||
decimal point, like 0.1, is converted to 100m by the API, and precision finer than 1m is not allowed.
|
||||
For this reason, the form 100m might be preferred.
|
||||
|
||||
You can express memory as a plain integer or as a fixed-point integer using one of these suffixes: E,
|
||||
P, T, G, M, K. You can also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki.
|
||||
For instance, "1Gi" stands for 1 Gigabyte, and "500Mi" stands for 500 megabytes. Using other formats
|
||||
will make the jobs fail as Kubernetes won't recognize the assignment.
|
||||
|
||||
For more details on the Kubernetes resources management, see:
|
||||
https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
|
||||
-->
|
||||
|
||||
</plugin>
|
||||
<plugin id="godocker" type="runner" load="galaxy.jobs.runners.godocker:GodockerJobRunner">
|
||||
<!-- Go-Docker is a batch computing/cluster management tool using Docker
|
||||
|
||||
@@ -52,6 +52,16 @@
|
||||
</object_store>
|
||||
-->
|
||||
|
||||
<!-- Sample Cloud Object Store
|
||||
<object_store type="cloud">
|
||||
<auth access_key="..." secret_key="..." />
|
||||
<bucket name="..." use_reduced_redundancy="False" />
|
||||
<cache path="database/object_store_cache" size="1000" />
|
||||
<extra_dir type="job_work" path="database/job_working_directory_s3"/>
|
||||
<extra_dir type="temp" path="database/tmp_s3"/>
|
||||
</object_store>
|
||||
-->
|
||||
|
||||
|
||||
</backends>
|
||||
</object_store>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<openid>
|
||||
<provider file="genomespace.xml" />
|
||||
<provider file="yahoo.xml" />
|
||||
<provider file="aol.xml" />
|
||||
<provider file="launchpad.xml" />
|
||||
</openid>
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
# appropriate files.
|
||||
---
|
||||
-
|
||||
image: bgruening/docker-hicbrowser
|
||||
image: quay.io/bgruening/hicbrowser
|
||||
description: |
|
||||
A simple web browser to visualize Hi-C and other genomic tracks
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
error : function(){},
|
||||
assert : function(){}
|
||||
};
|
||||
window.jQuery = window.jquery = window.$;
|
||||
define( 'jquery', [], function(){ return window.$; })
|
||||
require.config({
|
||||
baseUrl: Galaxy.root + "static/scripts/",
|
||||
paths: {
|
||||
@@ -64,4 +66,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -174,7 +174,7 @@ class TourGenerator(object):
|
||||
elif input.type == 'select':
|
||||
params = []
|
||||
if name in test_inputs:
|
||||
for option in self._tool.inputs[name].static_options:
|
||||
for option in input.static_options:
|
||||
for test_option in self._test.inputs[name]:
|
||||
if test_option == option[1]:
|
||||
params.append(option[0])
|
||||
|
||||
@@ -39,3 +39,13 @@ preferences:
|
||||
label: Maximum number of search results
|
||||
type: text
|
||||
required: False
|
||||
|
||||
use_cached_job:
|
||||
description: Do you want to be able to re-use previously run jobs ?
|
||||
inputs:
|
||||
- name: use_cached_job_checkbox
|
||||
label: Do you want to be able to re-use equivalent jobs ?
|
||||
type: boolean
|
||||
checked: false
|
||||
value: false
|
||||
help: If you select yes, you will be able to select for each tool and workflow run if you would like to use this feature.
|
||||
|
||||
@@ -59,7 +59,7 @@ galaxy_status() {
|
||||
if [[ $(grep '\[server:' $RUN_IN/config/galaxy.ini|awk -F'(:)|(])' '{ print $2 }') == 'main' ]]
|
||||
then
|
||||
echo -n "$SERVICE_NAME status: "
|
||||
status -p $RUN_IN/paster.pid galaxy
|
||||
status -p $RUN_IN/galaxy.pid galaxy
|
||||
else
|
||||
for proc in $(grep '\[server:' $RUN_IN/config/galaxy.ini|awk -F'(:)|(])' '{ print $2 }')
|
||||
do
|
||||
|
||||
@@ -13,10 +13,15 @@ import os
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
import urllib2
|
||||
import warnings
|
||||
from user import home
|
||||
|
||||
from six.moves.urllib.request import (
|
||||
build_opener,
|
||||
HTTPCookieProcessor,
|
||||
Request
|
||||
)
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore')
|
||||
import twill.commands as tc
|
||||
@@ -85,7 +90,7 @@ class Browser:
|
||||
dprint("no cookie jar at above path, creating")
|
||||
tc.save_cookies(self.cookie_jar)
|
||||
tc.load_cookies(self.cookie_jar)
|
||||
self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(tc.get_browser().cj))
|
||||
self.opener = build_opener(HTTPCookieProcessor(tc.get_browser().cj))
|
||||
|
||||
def get(self, path):
|
||||
tc.go("%s%s" % (self.server, path))
|
||||
@@ -94,9 +99,9 @@ class Browser:
|
||||
def req(self, path, data=None, method=None):
|
||||
url = self.server + path
|
||||
if data:
|
||||
req = urllib2.Request(url, headers={'Content-Type': 'application/json'}, data=json.dumps(data))
|
||||
req = Request(url, headers={'Content-Type': 'application/json'}, data=json.dumps(data))
|
||||
else:
|
||||
req = urllib2.Request(url, headers={'Content-Type': 'application/json'})
|
||||
req = Request(url, headers={'Content-Type': 'application/json'})
|
||||
if method:
|
||||
req.get_method = lambda: method
|
||||
res = self.opener.open(req)
|
||||
|
||||
@@ -21,7 +21,7 @@ Many of the following instructions are best practices for any production applica
|
||||
|
||||
* Create a **NON-ROOT** user called galaxy. Running as an existing user will cause problems down the line when you want to grant or restrict access to data.
|
||||
* Start with a fresh checkout of Galaxy, don't try to convert one previously used for development. Download and install it in the galaxy user home directory.
|
||||
* Galaxy should be a managed system service (like Apache, mail servers, database servers, *etc.*) run by the galaxy user. Init scripts, OS X launchd definitions and Solaris SMF manifests are provided in the `contrib/` directory of the distribution. You can also use the `--daemon` and `--stop-daemon` arguments to `run.sh` to start and stop by hand, but still run detached. When running as a daemon the server's output log will be written to `paster.log` instead of the terminal, unless instructed otherwise with the `--log-file` argument.
|
||||
* Galaxy should be a managed system service (like Apache, mail servers, database servers, *etc.*) run by the galaxy user. Init scripts, OS X launchd definitions and Solaris SMF manifests are provided in the `contrib/` directory of the distribution. You can also use the `--daemon` and `--stop-daemon` arguments to `run.sh` to start and stop by hand, but still run detached. When running as a daemon the server's output log will be written to `galaxy.log` instead of the terminal, unless instructed otherwise with the `--log-file` argument.
|
||||
* Give Galaxy its own database user and database to prevent Galaxy's schema from conflicting with other tables in your database. Also, restrict Galaxy's database user so it only has access to its own database.
|
||||
* Make sure Galaxy is using a clean Python interpreter. Conflicts in $PYTHONPATH or the interpreter's `site-packages/` directory could cause problems. Galaxy manages its own dependencies for the framework, so you do not need to worry about these. The easiest way to do this is with a [virtualenv](http://pypi.python.org/pypi/virtualenv):
|
||||
|
||||
@@ -37,7 +37,7 @@ nate@weyerbacher% sh run.sh
|
||||
|
||||
## Basic configuration
|
||||
|
||||
The steps to install Galaxy mostly follow those of the regular instructions at [Admin/GetGalaxy](https://getgalaxy.org). The difference is that after performing the groundwork above, you should initialize the configuration file (`cp config/galaxy.ini.sample config/galaxy.ini`) and modify it as outlined below before starting the server. If you make any changes to this configuration file while the server is running, you will have to restart the server for the changes to take effect.
|
||||
The steps to install Galaxy mostly follow those of the [regular instructions](http://getgalaxy.org). The difference is that after performing the groundwork above, you should initialize the configuration file (`cp config/galaxy.ini.sample config/galaxy.ini`) and modify it as outlined below before starting the server. If you make any changes to this configuration file while the server is running, you will have to restart the server for the changes to take effect.
|
||||
|
||||
### Disable the developer settings
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ For this to work, the user under which your nginx server runs will need read acc
|
||||
### External user authentication
|
||||
|
||||
- [Apache for External Authentication](https://galaxyproject.org/admin/config/apache-external-user-auth/)
|
||||
- [Built-in Galaxy External Authentication](../authentication.md)
|
||||
- [Built-in Galaxy External Authentication](../authentication.html)
|
||||
|
||||
### Display Sites
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
AGalaxy contains a plugin infrastructure for collecting and displaying metrics for job execution (see the original [pull request](https://bitbucket.org/galaxy/galaxy-central/pull-request/352) for implementation details).
|
||||
# Job Metrics
|
||||
|
||||
Galaxy contains a plugin infrastructure for collecting and displaying metrics for job execution (see the original [pull request](https://bitbucket.org/galaxy/galaxy-central/pull-request/352) for implementation details).
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ http {
|
||||
|
||||
**Notes:**
|
||||
|
||||
Make sure that you either comment out or modify line containing default configuration for enabled sites.
|
||||
Make sure that you either comment out or modify line containing default configuration for enabled sites (if present, e.g. on Debian/Ubuntu systems).
|
||||
|
||||
```
|
||||
include /etc/nginx/sites-enabled/*;
|
||||
@@ -304,4 +304,4 @@ server { # This you should already have.
|
||||
### External User Authentication
|
||||
|
||||
- [Nginx for External Authentication](https://galaxyproject.org/admin/config/nginx-external-user-auth/)
|
||||
- [Built-in Galaxy External Authentication](../authentication.md)
|
||||
- [Built-in Galaxy External Authentication](../authentication.html)
|
||||
|
||||
@@ -4,9 +4,10 @@ Quickstart
|
||||
Log in as your user, navigate to the API Keys page in the User menu, and
|
||||
generate a new API key. Make a note of the API key, and then pull up a
|
||||
terminal. Now we'll use the display.py script in your galaxy/scripts/api
|
||||
directory for a short example::
|
||||
directory for a short example, which assumes your local galaxy server is
|
||||
running on the default port 8080::
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/histories
|
||||
% ./display.py my_key http://localhost:8080/api/histories
|
||||
Collection Members
|
||||
------------------
|
||||
#1: /api/histories/8c49be448cfe29bc
|
||||
@@ -20,7 +21,7 @@ The result is a Collection of the histories of the user specified by the API
|
||||
key (you). To look at the details of a particular history, say #1 above, do
|
||||
the following::
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/histories/8c49be448cfe29bc
|
||||
% ./display.py my_key http://localhost:8080/api/histories/8c49be448cfe29bc
|
||||
Member Information
|
||||
------------------
|
||||
state_details: {'ok': 1, 'failed_metadata': 0, 'upload': 0, 'discarded': 0, 'running': 0, 'setting_metadata': 0, 'error': 0, 'new': 0, 'queued': 0, 'empty': 0}
|
||||
@@ -33,7 +34,7 @@ This gives detailed information about the specific member in question, in this
|
||||
case the History. To view history contents, do the following::
|
||||
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/histories/8c49be448cfe29bc/contents
|
||||
% ./display.py my_key http://localhost:8080/api/histories/8c49be448cfe29bc/contents
|
||||
Collection Members
|
||||
------------------
|
||||
#1: /api/histories/8c49be448cfe29bc/contents/6f91353f3eb0fa4a
|
||||
@@ -45,7 +46,7 @@ What we have here is another Collection of items containing all of the datasets
|
||||
in this particular history. Finally, to view details of a particular dataset
|
||||
in this collection, execute the following::
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/histories/8c49be448cfe29bc/contents/6f91353f3eb0fa4a
|
||||
% ./display.py my_key http://localhost:8080/api/histories/8c49be448cfe29bc/contents/6f91353f3eb0fa4a
|
||||
Member Information
|
||||
------------------
|
||||
misc_blurb: 1 line
|
||||
@@ -82,27 +83,27 @@ In Galaxy, create an account that matches the address you put in 'admin_users',
|
||||
then browse to that user's preferences and generate a new API Key. Copy the
|
||||
key to your clipboard and then use these scripts::
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/libraries
|
||||
% ./display.py my_key http://localhost:8080/api/libraries
|
||||
Collection Members
|
||||
------------------
|
||||
|
||||
0 elements in collection
|
||||
|
||||
% ./library_create_library.py my_key http://localhost:4096/api/libraries api_test 'API Test Library'
|
||||
% ./library_create_library.py my_key http://localhost:8080/api/libraries api_test 'API Test Library'
|
||||
Response
|
||||
--------
|
||||
/api/libraries/f3f73e481f432006
|
||||
name: api_test
|
||||
id: f3f73e481f432006
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/libraries
|
||||
% ./display.py my_key http://localhost:8080/api/libraries
|
||||
Collection Members
|
||||
------------------
|
||||
/api/libraries/f3f73e481f432006
|
||||
name: api_test
|
||||
id: f3f73e481f432006
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/libraries/f3f73e481f432006
|
||||
% ./display.py my_key http://localhost:8080/api/libraries/f3f73e481f432006
|
||||
Member Information
|
||||
------------------
|
||||
synopsis: None
|
||||
@@ -110,7 +111,7 @@ key to your clipboard and then use these scripts::
|
||||
description: API Test Library
|
||||
name: api_test
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/libraries/f3f73e481f432006/contents
|
||||
% ./display.py my_key http://localhost:8080/api/libraries/f3f73e481f432006/contents
|
||||
Collection Members
|
||||
------------------
|
||||
/api/libraries/f3f73e481f432006/contents/28202595c0d2591f61ddda595d2c3670
|
||||
@@ -118,14 +119,14 @@ key to your clipboard and then use these scripts::
|
||||
type: folder
|
||||
id: 28202595c0d2591f61ddda595d2c3670
|
||||
|
||||
% ./library_create_folder.py my_key http://localhost:4096/api/libraries/f3f73e481f432006/contents 28202595c0d2591f61ddda595d2c3670 api_test_folder1 'API Test Folder 1'
|
||||
% ./library_create_folder.py my_key http://localhost:8080/api/libraries/f3f73e481f432006/contents 28202595c0d2591f61ddda595d2c3670 api_test_folder1 'API Test Folder 1'
|
||||
Response
|
||||
--------
|
||||
/api/libraries/f3f73e481f432006/contents/28202595c0d2591fa4f9089d2303fd89
|
||||
name: api_test_folder1
|
||||
id: 28202595c0d2591fa4f9089d2303fd89
|
||||
|
||||
% ./library_upload_from_import_dir.py my_key http://localhost:4096/api/libraries/f3f73e481f432006/contents 28202595c0d2591fa4f9089d2303fd89 bed bed hg19
|
||||
% ./library_upload_from_import_dir.py my_key http://localhost:8080/api/libraries/f3f73e481f432006/contents 28202595c0d2591fa4f9089d2303fd89 bed bed hg19
|
||||
Response
|
||||
--------
|
||||
/api/libraries/f3f73e481f432006/contents/e9ef7fdb2db87d7b
|
||||
@@ -135,7 +136,7 @@ key to your clipboard and then use these scripts::
|
||||
name: 3.bed
|
||||
id: 3b7f6a31f80a5018
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/libraries/f3f73e481f432006/contents
|
||||
% ./display.py my_key http://localhost:8080/api/libraries/f3f73e481f432006/contents
|
||||
Collection Members
|
||||
------------------
|
||||
/api/libraries/f3f73e481f432006/contents/28202595c0d2591f61ddda595d2c3670
|
||||
@@ -155,7 +156,7 @@ key to your clipboard and then use these scripts::
|
||||
type: file
|
||||
id: 3b7f6a31f80a5018
|
||||
|
||||
% ./display.py my_key http://localhost:4096/api/libraries/f3f73e481f432006/contents/e9ef7fdb2db87d7b
|
||||
% ./display.py my_key http://localhost:8080/api/libraries/f3f73e481f432006/contents/e9ef7fdb2db87d7b
|
||||
Member Information
|
||||
------------------
|
||||
misc_blurb: 68 regions
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -371,9 +371,6 @@ class Configuration(object):
|
||||
# Beta containers interface used by GIEs
|
||||
self.enable_beta_containers_interface = string_as_bool(kwargs.get('enable_beta_containers_interface', 'False'))
|
||||
|
||||
# Deprecated API for sample tracking
|
||||
self.enable_legacy_sample_tracking_api = string_as_bool(kwargs.get('enable_legacy_sample_tracking_api', 'False'))
|
||||
|
||||
# Certain modules such as the pause module will automatically cause
|
||||
# workflows to be scheduled in job handlers the way all workflows will
|
||||
# be someday - the following two properties can also be used to force this
|
||||
@@ -429,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...
|
||||
|
||||
@@ -46,7 +46,7 @@ SWARM_MANAGER_CONF_DEFAULTS = {
|
||||
'service_wait_count_limit': 0,
|
||||
'service_wait_time_limit': 5,
|
||||
'slots_min_limit': 0,
|
||||
'slots_max_limit': sys.maxint,
|
||||
'slots_max_limit': sys.maxsize,
|
||||
'slots_min_spare': 0,
|
||||
'node_idle_limit': 120,
|
||||
'limits': [],
|
||||
@@ -137,7 +137,7 @@ class SwarmManager(object):
|
||||
state = node_state['state']
|
||||
if not nodes:
|
||||
nodes = self._docker_interface.nodes()
|
||||
node = (filter(lambda x: x.name == name, nodes) + [None])[0]
|
||||
node = ([x for x in nodes if x.name == name] + [None])[0]
|
||||
if not node:
|
||||
if elapsed > self._conf.spawn_wait_time:
|
||||
log.warning("spawning node '%s' not found in `docker node ls` and spawn_wait_time exceeded! %d seconds have elapsed", name, elapsed)
|
||||
|
||||
@@ -267,27 +267,35 @@ class BamNative(Binary):
|
||||
return zip(file_paths, rel_paths)
|
||||
|
||||
def get_chunk(self, trans, dataset, offset=0, ck_size=None):
|
||||
with pysam.AlignmentFile(dataset.file_name, "rb") as bamfile:
|
||||
ck_size = 300 # 300 lines
|
||||
ck_data = ""
|
||||
header_line_count = 0
|
||||
if offset == 0:
|
||||
ck_data = bamfile.text.replace('\t', ' ')
|
||||
header_line_count = bamfile.text.count('\n')
|
||||
else:
|
||||
bamfile.seek(offset)
|
||||
for line_number, alignment in enumerate(bamfile) :
|
||||
# return only Header lines if 'header_line_count' exceeds 'ck_size'
|
||||
# FIXME: Can be problematic if bam has million lines of header
|
||||
offset = bamfile.tell()
|
||||
if (line_number + header_line_count) > ck_size:
|
||||
break
|
||||
else:
|
||||
bamline = alignment.tostring(bamfile)
|
||||
# Galaxy display each tag as separate column because 'tostring()' funcition put tabs in between each tag of tags column.
|
||||
# Below code will remove spaces between each tag.
|
||||
bamline_modified = ('\t').join(bamline.split()[:11] + [(' ').join(bamline.split()[11:])])
|
||||
ck_data = "%s\n%s" % (ck_data, bamline_modified)
|
||||
if not offset == -1:
|
||||
try:
|
||||
with pysam.AlignmentFile(dataset.file_name, "rb") as bamfile:
|
||||
ck_size = 300 # 300 lines
|
||||
ck_data = ""
|
||||
header_line_count = 0
|
||||
if offset == 0:
|
||||
ck_data = bamfile.text.replace('\t', ' ')
|
||||
header_line_count = bamfile.text.count('\n')
|
||||
else:
|
||||
bamfile.seek(offset)
|
||||
for line_number, alignment in enumerate(bamfile) :
|
||||
# return only Header lines if 'header_line_count' exceeds 'ck_size'
|
||||
# FIXME: Can be problematic if bam has million lines of header
|
||||
offset = bamfile.tell()
|
||||
if (line_number + header_line_count) > ck_size:
|
||||
break
|
||||
else:
|
||||
bamline = alignment.tostring(bamfile)
|
||||
# Galaxy display each tag as separate column because 'tostring()' funcition put tabs in between each tag of tags column.
|
||||
# Below code will remove spaces between each tag.
|
||||
bamline_modified = ('\t').join(bamline.split()[:11] + [(' ').join(bamline.split()[11:])])
|
||||
ck_data = "%s\n%s" % (ck_data, bamline_modified)
|
||||
except Exception as e:
|
||||
offset = -1
|
||||
ck_data = "Could not display BAM file, error was:\n%s" % e.message
|
||||
else:
|
||||
ck_data = ''
|
||||
offset = -1
|
||||
return dumps({'ck_data': util.unicodify(ck_data),
|
||||
'offset': offset})
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user