Vue rewrite of admin data manager (local data): view job page

* Rewrite (old mako, new json interface, new vue component)
 - View job page (view_job.mako, job_info, DataManagerJob)
* Added Selenium test for DataManagerJob component (view job page)
This commit is contained in:
Sebastian Kapust
2018-09-18 02:10:04 +02:00
parent 747e998d40
commit 13b8098259
7 changed files with 209 additions and 70 deletions
@@ -0,0 +1,160 @@
<template>
<div>
<b-breadcrumb :items="breadcrumbItems" />
<Alert :message="message" :variant="status" />
<Alert v-for="(error, index) in errorMessages" :key="index" :message="error" variant="error" />
<Alert v-if="viewOnly" message="Not implemented" variant="dark" />
<b-container v-else>
<b-row>
<b-col>
<b-card header-bg-variant="primary" header-text-variant="white" border-variant="primary" class="mb-3" id="data-manager-card">
<template slot="header">
<b-container>
<b-row align-v="center">
<b-col cols="auto">
<b-button v-b-tooltip.hover title="Rerun" :href="runUrl">
<span class="fa fa-refresh" />
</b-button>
</b-col>
<b-col>
<b>{{ dataManager["name"] }}</b>
<i>{{ dataManager['description'] }}</i>
</b-col>
</b-row>
</b-container>
</template>
<b-card v-for="(item, i) in tableItems" :key="i" class="mb-4" id="data-card">
<template slot="header">
<b-table :fields="fields" :items="[item]" caption-top small stacked>
<template slot="table-caption">
<b-container>
<b-row align-v="center">
<b-col cols="auto">
<b-button v-b-tooltip.hover title="View complete info" :href="tableItems[i]['infoUrl']" target="galaxy_main">
<span class="fa fa-info-circle" />
</b-button>
</b-col>
<b-col>
<b>{{ item["name"] }}</b>
</b-col>
</b-row>
</b-container>
</template>
</b-table>
</template>
<b-table v-for="(output, j) in dataManagerOutput[i]" :key="j" :fields="outputFields(output[1])" :items="output[1]" small stacked hover striped>
<template slot="table-caption">
Data Table:
<b>{{ output[0] }}</b>
</template>
</b-table>
</b-card>
</b-card>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import axios from "axios";
import Alert from "components/Alert.vue";
export default {
components: {
Alert
},
props: {
id: {
type: String,
required: true
}
},
data() {
return {
exitCode: Number,
runUrl: "#",
dataManager: [],
hdaInfo: [],
dataManagerOutput: [],
errorMessages: [],
fields: [
{ key: "created" },
{ key: "fileSize", label: "Filesize" },
{
key: "fileName",
label: "Full path",
tdClass: "table-cell-break-word"
}
],
viewOnly: false,
message: "",
status: ""
};
},
computed: {
breadcrumbItems() {
return [
{
text: "Data Managers",
to: "/"
},
{
text: this.dataManager["name"] + " ( " + this.dataManager["description"] + " )",
href: this.dataManager["toolUrl"],
target: "_blank"
},
{
text: "Jobs",
to: {
name: "DataManagerJobs",
params: { id: this.dataManager["id"] }
}
},
{
text: "Job " + this.jobId,
active: true
}
];
},
tableItems() {
let tableItems = this.hdaInfo;
return tableItems;
}
},
methods: {
outputFields(output) {
let outputFields = [];
for (const k of Object.keys(output[0])) {
outputFields.push({ key: k, label: k });
}
return outputFields;
}
},
created() {
axios
.get(`${Galaxy.root}data_manager/job_info?id=${this.id}`)
.then(response => {
this.jobId = response.data.jobId;
this.exitCode = response.data.exitCode;
this.runUrl = response.data.runUrl;
this.dataManager = response.data.dataManager;
this.hdaInfo = response.data.hdaInfo;
this.dataManagerOutput = response.data.dataManagerOutput;
this.errorMessages = response.data.errorMessages;
this.viewOnly = response.data.viewOnly;
this.message = response.data.message;
this.status = response.data.status;
})
.catch(error => {
console.error(error);
});
}
};
</script>
<style>
.table-cell-break-word {
word-break: break-word;
}
</style>
@@ -35,7 +35,7 @@
<b-button v-b-tooltip.hover title="Rerun" :href="jobs[row.index]['runUrl']">
<span class="fa fa-refresh" />
</b-button>
<b-button v-b-tooltip.hover title="View Info" :href="jobs[row.index]['infoUrl']" target="galaxy_main" :id="'job-' + jobs[row.index]['encId']">
<b-button v-b-tooltip.hover title="View Info" :to="{name: 'DataManagerJob', params: { id: jobs[row.index]['encId'] }}" :id="'job-' + jobs[row.index]['encId']">
<span class="fa fa-info-circle" />
</b-button>
<b-button v-if="!showCommandLine" @click.stop="row.toggleDetails()" :pressed.sync="row.detailsShowing">
@@ -3,6 +3,7 @@ import Vue from "vue";
import VueRouter from "vue-router";
import DataManager from "./DataManager.vue";
import DataManagerJobs from "./DataManagerJobs.vue";
import DataManagerJob from "./DataManagerJob.vue";
Vue.use(VueRouter);
@@ -19,6 +20,12 @@ export default new VueRouter({
name: "DataManagerJobs",
component: DataManagerJobs,
props: true
},
{
path: "/job/:id",
name: "DataManagerJob",
component: DataManagerJob,
props: true
}
]
});
@@ -7,6 +7,7 @@ from six import string_types
import galaxy.queue_worker
from galaxy import web
from galaxy.util import nice_size, unicodify
from galaxy.web.base.controller import BaseUIController
log = logging.getLogger(__name__)
@@ -64,7 +65,6 @@ class DataManager(BaseUIController):
'id': j.id,
'encId': trans.security.encode_id(j.id),
'runUrl': web.url_for(controller="tool_runner", action="rerun", job_id=trans.security.encode_id(j.id)),
'infoUrl': web.url_for(controller="data_manager", action="view_job", id=trans.security.encode_id(j.id)),
'user': j.history.user.email if j.history and j.history.user else "anonymous",
'updateTime': j.update_time.isoformat(),
'state': j.state,
@@ -83,12 +83,13 @@ class DataManager(BaseUIController):
'status': status}
@web.expose
def view_job(self, trans, **kwd):
@web.json
def job_info(self, trans, **kwd):
not_is_admin = not trans.user_is_admin()
if not_is_admin and not trans.app.config.enable_data_manager_user_view:
raise paste.httpexceptions.HTTPUnauthorized("This Galaxy instance is not configured to allow non-admins to view the data manager.")
message = escape(kwd.get('message', ''))
status = escape(kwd.get('status', 'info'))
message = kwd.get('message', '')
status = kwd.get('status', 'info')
job_id = kwd.get('id', None)
try:
job_id = trans.security.decode_id(job_id)
@@ -101,19 +102,45 @@ class DataManager(BaseUIController):
data_manager_id = job.data_manager_association.data_manager_id
data_manager = trans.app.data_managers.get_manager(data_manager_id)
hdas = [assoc.dataset for assoc in job.get_output_datasets()]
hda_info = []
data_manager_output = []
error_messages = []
for hda in hdas:
hda_info.append({'id': hda.id,
'encId': trans.security.encode_id(hda.id),
'name': hda.name,
'created': unicodify(hda.create_time.strftime(trans.app.config.pretty_datetime_format)),
'fileSize': nice_size(hda.dataset.file_size),
'fileName': hda.file_name,
'infoUrl': web.url_for(controller='dataset',
action='show_params',
dataset_id=trans.security.encode_id(hda.id))})
try:
data_manager_json = loads(open(hda.get_file_name()).read())
except Exception as e:
data_manager_json = {}
error_messages.append(escape("Unable to obtain data_table info for hda (%s): %s" % (hda.id, e)))
error_messages.append("Unable to obtain data_table info for hda (%s): %s" % (hda.id, e))
values = []
for key, value in data_manager_json.get('data_tables', {}).items():
values.append((key, value))
data_manager_output.append(values)
return trans.fill_template("data_manager/view_job.mako", data_manager=data_manager, job=job, view_only=not_is_admin, hdas=hdas, data_manager_output=data_manager_output, message=message, status=status, error_messages=error_messages)
return {'jobId': job_id,
'exitCode': job.exit_code,
'runUrl': web.url_for(controller="tool_runner",
action="rerun",
job_id=trans.security.encode_id(job.id)),
'commandLine': job.command_line,
'dataManager': {'id': data_manager_id,
'name': data_manager.name,
'description': data_manager.description.lower(),
'toolUrl': web.url_for(controller='root',
tool_id=data_manager.tool.id)},
'hdaInfo': hda_info,
'dataManagerOutput': data_manager_output,
'errorMessages': error_messages,
'viewOnly': not_is_admin,
'message': message,
'status': status}
@web.expose
def manage_data_table(self, trans, **kwd):
@@ -1,63 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<% from galaxy.util import nice_size, unicodify %>
<%def name="title()">Data Manager: ${ data_manager.name | h } - ${ data_manager.description | h }</%def>
%if message:
${render_msg( message, status )}
%endif
%if error_messages:
%for error_message in error_messages:
${ render_msg( error_message, 'error' ) }
%endfor
%endif
%if view_only:
<p>Not implemented</p>
%else:
%for i, hda in enumerate( hdas ):
<table class="tabletip">
<thead>
<tr><th colspan="2" style="font-size: 120%;">
Data Manager: <a href="${ h.url_for( controller='root', tool_id=data_manager.tool.id ) }" target="_blank">${ data_manager.name | h }</a> - ${ data_manager.description | h } <a class="icon-btn" href="${ h.url_for( controller="tool_runner", action="rerun", job_id=trans.security.encode_id( job.id ) ) }" title="Rerun" data-placement="bottom"><span class="fa fa-refresh"></span></a>
</th></tr>
</thead>
<tbody>
<tr><td>Name:</td><td>${hda.name | h}</td></tr>
<tr><td>Created:</td><td>${unicodify(hda.create_time.strftime(trans.app.config.pretty_datetime_format)) | h}</td></tr>
<tr><td>Filesize:</td><td>${nice_size(hda.dataset.file_size) | h}</td></tr>
<tr><td>Tool Exit Code:</td><td>${job.exit_code | h}</td></tr>
<tr><td>Full Path:</td><td>${hda.file_name | h}</td></tr>
<tr><td>View complete info:</td><td><a href="${h.url_for( controller='dataset', action='show_params', dataset_id=trans.security.encode_id( hda.id ))}">${ hda.id | h }</a></td></tr>
</table>
<br />
<% json_tables = data_manager_output[i]%>
%for table_name, json_table in json_tables:
<table class="tabletip">
<thead>
<tr><th colspan="2" style="font-size: 120%;">
Data Table: <a href="${h.url_for( controller='data_manager', action='manage_data_table', table_name=table_name)}">${ table_name | h }</a>
</th></tr>
</thead>
<% len_json_table = len( json_table ) %>
%for j, table_row in enumerate( json_table ):
<tbody>
%if len_json_table > 1:
<tr><td><strong>Entry &#35;${j | h}</strong></td><td> </td></tr>
%endif
%for name, value in table_row.iteritems():
<tr><td>${name | h}:</td><td>${value | h}</td></tr>
%endfor
%endfor
</tbody>
</table>
<br />
%endfor
%endfor
%endif
+3
View File
@@ -308,6 +308,9 @@ admin:
dm_jobs_button: '#${data_manager}-jobs'
dm_jobs_breadcrumb: '#breadcrumb'
dm_jobs_table: '#jobs-table'
dm_job: '#job-${job_id}'
dm_job_data_manager_card: '#data-manager-card'
dm_job_data_card: '#data-card'
users_grid: '#users-grid'
users_grid_create_button: '.manage-table-actions .action-button'
groups_grid_create_button: '.manage-table-actions .action-button'
+5
View File
@@ -91,3 +91,8 @@ class AdminAppTestCase(SeleniumTestCase):
admin_component.dm_jobs_breadcrumb.wait_for_visible()
admin_component.dm_jobs_table.wait_for_visible()
self.screenshot("admin_data_manager_jobs")
admin_component.dm_job(job_id=job_id).wait_for_and_click()
admin_component.dm_job_data_manager_card.wait_for_visible()
admin_component.dm_job_data_card.wait_for_visible()
self.screenshot("admin_data_manager_job")