/*global define */
define(['jquery', 'underscore', 'backbone', 'd3',
"models/SolrResult",
'DonutChart', 'views/CitationView',
'text!templates/mdqRun.html', 'text!templates/mdqSuites.html', 'text!templates/loading-metrics.html', 'collections/QualityReport'],
function($, _, Backbone, d3,
SolrResult,
DonutChart, CitationView,
MdqRunTemplate, SuitesTemplate, LoadingTemplate, QualityReport) {
'use strict';
/**
* @class MdqRunView
* @classdesc A view that fetches and displays a Metadata Assessment Report
* @classcategory Views
* @name MdqRunView
* @extends Backbone.View
* @constructs
*/
var MdqRunView = Backbone.View.extend(
/** @lends MdqRunView.prototype */{
el: '#Content',
events: {
"change #suiteId" : "switchSuite"
},
url: null,
pid: null,
/**
* The currently selected/requested suite
* @type {string}
*/
suiteId: null,
/**
* The list of all potential suites for this theme
* @type {string[]}
*/
suiteIdList: [],
loadingTemplate: _.template(LoadingTemplate),
template: _.template(MdqRunTemplate),
breadcrumbContainer: "#breadcrumb-container",
/**
* A JQuery selector for the element in the template that will contain the loading
* image
* @type {string}
* @since 2.15.0
*/
loadingContainer: "#mdqResult",
initialize: function () {
},
switchSuite: function(event) {
var select = $(event.target);
var suiteId = $(select).val();
MetacatUI.uiRouter.navigate("quality/s=" + suiteId + "/" + encodeURIComponent(this.pid), {trigger: false});
this.suiteId = suiteId;
this.render();
return false;
},
render: function () {
var viewRef = this;
// The suite use for rendering can initially be set via the theme AppModel.
// If a suite id is request via the metacatui route, then we have to display that
// suite, and in addition have to display all possible suites for this theme in
// a selection list, if the user wants to view a different one.
if (!this.suiteId) {
this.suiteId = MetacatUI.appModel.get("mdqSuiteIds")[0];
}
this.suiteIdList = MetacatUI.appModel.get("mdqSuiteIds");
this.suiteLabels = MetacatUI.appModel.get("mdqSuiteLabels");
//this.url = this.mdqRunsServiceUrl + "/" + this.suiteId + "/" + this.pid;
// Insert the basic template
this.$el.html(this.template({}));
// Show breadcrumbs leading back to the dataset & data search
this.insertBreadcrumbs();
// Insert the loading image
this.showLoading();
if (!this.pid){
var searchLink = $(document.createElement("a"))
.attr("href", MetacatUI.root + "/data")
.text("Search our database");
var message = $(document.createElement("span"))
.text(" to see an assessment report for a dataset")
.prepend(searchLink);
this.showMessage(message, true, false)
return
}
// Fetch a quality report from the quality server and display it.
var qualityUrl = MetacatUI.appModel.get("mdqRunsServiceUrl") + viewRef.suiteId + "/" + viewRef.pid;
var qualityReport = new QualityReport([], { url: qualityUrl, pid: viewRef.pid });
qualityReport.fetch({ url: qualityUrl });
this.listenToOnce(qualityReport, "fetchError", function() {
// Inspect the results to see if a quality report was returned.
// If not, then submit a request to the quality engine to create the
// quality report for this pid/suiteId, and inform the user of this.
var msgText;
console.log("Error status: " + qualityReport.fetchResponse.status);
if(qualityReport.fetchResponse.status == 404) {
msgText = "The assessment report for this dataset is not ready yet. Try checking back in 24 hours to see these results.";
} else {
msgText = "There was an error retrieving the assessment report for this dataset.";
if(typeof qualityReport.fetchResponse.statusText !== 'undefined' && typeof qualityReport.fetchResponse.status !== 'undefined') {
if(qualityReport.fetchResponse.status != 0)
msgText += "Error details: " + qualityReport.fetchResponse.statusText;
}
}
this.showMessage(msgText);
}),
this.listenToOnce(qualityReport, "fetchComplete", function() {
var msgText;
if(qualityReport.runStatus != "success") {
if(qualityReport.runStatus == "failure") {
msgText = "There was an error generating the assessment report. The Assessment Server reported this error: " + qualityReport.errorDescription;
} else if (qualityReport.runStatus == "queued") {
msgText = "The assessment report is in the Assessment Server queue to be generated. It was queued at: " + qualityReport.timestamp;
} else {
msgText = "There was an error retrieving the assessment report."
}
this.showMessage(msgText);
return
} else {
viewRef.hideLoading();
}
// Filter out the checks with level 'METADATA', as these checks are intended
// to pass info to metadig-engine indexing (for search, faceting), and not intended for display.
qualityReport.reset(_.reject(qualityReport.models, function (model) {
var check = model.get("check");
if (check.level == "METADATA") {
return true
} else {
return false;
}
}));
var groupedResults = qualityReport.groupResults(qualityReport.models);
var groupedByType = qualityReport.groupByType(qualityReport.models);
var data = {
objectIdentifier: qualityReport.id,
suiteId: viewRef.suiteId,
suiteIdList: viewRef.suiteIdList,
suiteLabels: viewRef.suiteLabels,
groupedResults: groupedResults,
groupedByType: groupedByType,
timestamp: _.now(),
id: viewRef.pid,
checkCount: qualityReport.length
};
viewRef.$el.html(viewRef.template(data));
viewRef.insertBreadcrumbs();
viewRef.drawScoreChart(qualityReport.models, groupedResults);
viewRef.showCitation();
viewRef.show();
viewRef.$('.popover-this').popover();
});
},
/**
* Updates the message in the loading image
* @param {string} message The new message to display
* @param {boolean} [showHelp=true] If set to true, and an email contact is configured
* in MetacatUI, then the contact email will be shown at the bottom of the message.
* @param {boolean} [showLink=true] If set to true, a link back to the dataset will be
* appended to the end of the message.
* @since 2.15.0
*/
showMessage : function(message, showHelp = true, showLink = true){
try {
var view = this;
var messageEl = this.loadingEl.find(".message");
if(!messageEl){
return
}
// Update the message
messageEl.html(message);
// Create a link back to the data set
if(showLink){
var viewURL = "/view/" + encodeURIComponent(this.pid);
var backLink = $(document.createElement("a"))
.text(" Return to the dataset")
backLink.on("click", function(){
view.hideLoading();
MetacatUI.uiRouter.navigate(viewURL, { trigger: true, replace: true });
})
messageEl.append(backLink)
}
// Show how the user can get more help
if(showHelp){
var emailAddress = MetacatUI.appModel.get('emailContact')
// Don't show help if there's no contact email configured
if(emailAddress){
var helpEl = $(
"<p class='webmaster-email' style='margin-top:20px'>" +
"<i class='icon-envelope-alt icon icon-on-left'></i>" +
"Need help? Email us at </p>"
);
var emailLink = $(document.createElement("a"))
.attr("href", "mailto:" + emailAddress)
.text(emailAddress);
helpEl.append(emailLink)
messageEl.append(helpEl)
}
}
}
catch (error) {
console.log(
'There was an error showing a message in a MdqRunView' +
'. Error details: ' + error
);
}
},
/**
* Render a loading image with message
*/
showLoading: function() {
try {
var loadingEl = this.loadingTemplate({
message: "Retrieving assessment report...",
character: "none",
type: "barchart"
});
this.loadingEl = $(loadingEl)
this.$el.find(this.loadingContainer).html(this.loadingEl)
}
catch (error) {
console.log(
'There was an error showing the loading image in a MdqRunView' +
'. Error details: ' + error
);
}
},
/**
* Remove the loading image and message.
*/
hideLoading: function() {
try {
this.loadingEl.remove();
}
catch (error) {
console.log(
'There was an error hiding a loading image in a MdqRunView' +
'. Error details: ' + error
);
}
},
showCitation: function(){
var solrResultModel = new SolrResult({
id: this.pid
});
this.listenTo(solrResultModel, "sync", function(){
var citationView = new CitationView({
model: solrResultModel,
createLink: false,
createTitleLink: true
});
citationView.render();
this.$("#mdqCitation").prepend(citationView.el);
});
solrResultModel.getInfo();
},
show: function() {
var view = this;
this.$el.hide();
this.$el.fadeIn({duration: "slow"});
},
drawScoreChart: function(results, groupedResults){
var dataCount = results.length;
var data = [
{label: "Pass", count: groupedResults.GREEN.length, perc: groupedResults.GREEN.length/results.length },
{label: "Warn", count: groupedResults.ORANGE.length, perc: groupedResults.ORANGE.length/results.length},
{label: "Fail", count: groupedResults.RED.length, perc: groupedResults.RED.length/results.length},
{label: "Info", count: groupedResults.BLUE.length, perc: groupedResults.BLUE.length/results.length},
];
var svgClass = "data";
//If d3 isn't supported in this browser or didn't load correctly, insert a text title instead
if(!d3){
this.$('.format-charts-data').html("<h2 class='" + svgClass + " fallback'>" + MetacatUI.appView.commaSeparateNumber(dataCount) + " data files</h2>");
return;
}
//Draw a donut chart
var donut = new DonutChart({
id: "data-chart",
data: data,
total: dataCount,
titleText: "checks",
titleCount: dataCount,
svgClass: svgClass,
countClass: "data",
height: 250,
width: 250,
keepOrder: true,
formatLabel: function(name) {
return name;
}
});
this.$('.format-charts-data').html(donut.render().el);
},
insertBreadcrumbs: function(){
var breadcrumbs = $(document.createElement("ol"))
.addClass("breadcrumb")
.append($(document.createElement("li"))
.addClass("home")
.append($(document.createElement("a"))
.attr("href", MetacatUI.root? MetacatUI.root : "/")
.addClass("home")
.text("Home")))
.append($(document.createElement("li"))
.addClass("search")
.append($(document.createElement("a"))
.attr("href", MetacatUI.root + "/data" + ((MetacatUI.appModel.get("page") > 0)? ("/page/" + (parseInt(MetacatUI.appModel.get("page"))+1)) : ""))
.addClass("search")
.text("Search")))
.append($(document.createElement("li"))
.append($(document.createElement("a"))
.attr("href", MetacatUI.root + "/view/" + encodeURIComponent(this.pid))
.addClass("inactive")
.text("Metadata")))
.append($(document.createElement("li"))
.append($(document.createElement("a"))
.attr("href", MetacatUI.root + "/quality/" + encodeURIComponent(this.pid))
.addClass("inactive")
.text("Assessment Report")));
this.$(this.breadcrumbContainer).html(breadcrumbs);
},
});
return MdqRunView;
});