/*global define */
define(['jquery', 'underscore', 'backbone', 'd3', 'LineChart', 'BarChart', 'DonutChart', 'CircleBadge',
'collections/Citations', 'models/MetricsModel', 'models/Stats', 'MetricsChart', 'views/CitationListView',
'text!templates/metricModalTemplate.html', 'text!templates/profile.html',
'text!templates/alert.html', 'text!templates/loading.html'],
function($, _, Backbone, d3, LineChart, BarChart, DonutChart, CircleBadge, Citations, MetricsModel,
StatsModel, MetricsChart, CitationList, MetricModalTemplate, profileTemplate, AlertTemplate,
LoadingTemplate) {
'use strict';
var StatsView = Backbone.View.extend(
/** @lends StatsView.prototype */{
el: '#Content',
model: null,
hideUpdatesChart: false,
/**
* Whether or not to show the graph that indicated the assessment score for all metadata in the query.
* @type {boolean}
*/
hideMetadataAssessment: false,
template: _.template(profileTemplate),
metricTemplate: _.template(MetricModalTemplate),
alertTemplate: _.template(AlertTemplate),
loadingTemplate: _.template(LoadingTemplate),
initialize: function(options){
if(!options) options = {};
this.title = (typeof options.title === "undefined") ? "Summary of Holdings" : options.title;
this.description = (typeof options.description === "undefined") ?
"A summary of all datasets in our catalog." : options.description;
this.metricsModel = (typeof options.metricsModel === undefined) ? undefined : options.metricsModel;
this.userType = options.userType;
if(typeof options.el === "undefined")
this.el = options.el;
this.hideUpdatesChart = (options.hideUpdatesChart === true)? true : false;
this.hideMetadataAssessment = (typeof options.hideMetadataAssessment === "undefined") ? true : options.hideMetadataAssessment;
this.hideCitationsChart = (typeof options.hideCitationsChart === "undefined") ? true : options.hideCitationsChart;
this.hideDownloadsChart = (typeof options.hideDownloadsChart === "undefined") ? true : options.hideDownloadsChart;
this.hideViewsChart = (typeof options.hideViewsChart === "undefined") ? true : options.hideViewsChart;
this.model = options.model || null;
},
render: function (options) {
if ( !options )
options = {};
var view = this;
if ( options.nodeSummaryView ) {
var nodeId = MetacatUI.appModel.get("nodeId");
// Overwrite the metrics display flags as set in the AppModel
this.hideMetadataAssessment = false;
this.hideCitationsChart = MetacatUI.appModel.get("hideSummaryCitationsChart");
this.hideDownloadsChart = MetacatUI.appModel.get("hideSummaryDownloadsChart");
this.hideViewsChart = MetacatUI.appModel.get("hideSummaryViewsChart");
// Disable the metrics of the nodeId is not available
if (nodeId === "undefined" || nodeId === null) {
this.hideCitationsChart = true;
this.hideDownloadsChart = true;
this.hideViewsChart = true;
}
}
//If the metadata summery charts are turned off in the entire app, then they should be turned off here too
if( MetacatUI.appModel.get("hideSummaryMetadataAssessment") === true ){
this.hideMetadataAssessment = true;
}
if ( !this.hideCitationsChart || !this.hideDownloadsChart || !this.hideViewsChart ) {
if ( typeof this.metricsModel === "undefined" ) {
// Create a list with the repository ID
var pid_list = new Array();
pid_list.push(nodeId);
// Create a new object of the metrics model
var metricsModel = new MetricsModel({
pid_list: pid_list,
type: this.userType
});
metricsModel.fetch();
this.metricsModel = metricsModel;
}
}
if( !this.model ){
this.model = new StatsModel({
hideMetadataAssessment: this.hideMetadataAssessment
});
}
//Clear the page
this.$el.html("");
//Only trigger the functions that draw SVG charts if d3 loaded correctly
if(d3){
//Draw a chart that shows the temporal coverage of all datasets in this collection
this.listenTo(this.model, 'change:temporalCoverage', this.drawCoverageChart);
//Draw charts that plot the latest updates of metadata and data files
this.listenTo(this.model, "change:dataUpdateDates", this.drawDataUpdatesChart);
this.listenTo(this.model, "change:metadataUpdateDates", this.drawMetadataUpdatesChart);
//Render the total file size of all contents in this collection
this.listenTo(this.model, "change:totalSize", this.drawTotalSize);
//Render the total number of datasets in this collection
this.listenTo(this.model, 'change:metadataCount', this.drawTotalCount);
//Draw charts that show the breakdown of format IDs for metadata and data files
this.listenTo(this.model, 'change:dataFormatIDs', this.drawDataCountChart);
this.listenTo(this.model, 'change:metadataFormatIDs', this.drawMetadataCountChart);
}
//When the last coverage endDate is found, draw a title for the temporal coverage chart
this.listenTo(this.model, 'change:lastEndDate', this.drawCoverageChartTitle);
//When the total count is updated, check if there if the count is 0, so we can show there is no "activity" for this collection
this.listenTo(this.model, "change:totalCount", this.showNoActivity);
// set the header type
MetacatUI.appModel.set('headerType', 'default');
//Insert the template
this.$el.html(this.template({
query: this.model.get('query'),
title: this.title,
description: this.description,
userType: this.userType,
hideUpdatesChart: this.hideUpdatesChart,
hideCitationsChart: this.hideCitationsChart,
hideDownloadsChart: this.hideDownloadsChart,
hideViewsChart: this.hideViewsChart,
hideMetadataAssessment: this.hideMetadataAssessment
}));
// Insert the metadata assessment chart
if( this.hideMetadataAssessment !== true ){
this.listenTo(this.model, "change:mdqScoresImage", this.drawMetadataAssessment);
this.listenTo(this.model, "change:mdqScoresError", function () {
this.$("#metadata-assessment-loading").remove();
MetacatUI.appView.showAlert("Metadata assessment scores are not available for this collection. " + this.model.get("mdqScoresError"),
"alert-warning", this.$("#metadata-assessment-graphic"));
});
}
//Insert the loading template into the space where the charts will go
if(d3){
this.$(".chart").html(this.loadingTemplate);
this.$(".show-loading").html(this.loadingTemplate);
}
//If SVG isn't supported, insert an info warning
else{
this.$el.prepend(this.alertTemplate({
classes: "alert-info",
msg: "Please upgrade your browser or use a different browser to view graphs of these statistics.",
email: false
}));
}
this.$el.data("view", this);
if (this.userType == "portal" || this.userType === "repository") {
if ( !this.hideCitationsChart || !this.hideDownloadsChart || !this.hideViewsChart ) {
if (this.metricsModel.get("totalViews") !== null) {
this.renderMetrics();
}
else{
// render metrics on fetch success.
this.listenTo(view.metricsModel, "sync" , this.renderMetrics);
// in case when there is an error for the fetch call.
this.listenTo(view.metricsModel, "error", this.renderUsageMetricsError);
}
}
}
//Start retrieving data from Solr
this.model.getAll();
return this;
},
/**
* drawMetadataAssessment - Insert the metadata assessment image into the view
*/
drawMetadataAssessment: function(){
try {
var scoresImage = this.model.get("mdqScoresImage");
// Hide the spinner
this.$("#metadata-assessment-loading").remove();
if( scoresImage ){
// Show the figure
this.$("#metadata-assessment-graphic").append(scoresImage);
}
//If there was no image received from the MDQ scores service, then show a warning message
else{
MetacatUI.appView.showAlert(
"Something went wrong while getting the metadata assessment scores. If changes were recently made " +
" to these dataset(s), the scores may still be calculating.",
"alert-warning",
this.$("#metadata-assessment-graphic")
);
}
} catch (e) {
// If there's an error inserting the image, remove the entire section
// that contains the image.
console.error("Error displaying the metadata assessment figure. Error message: " + e);
MetacatUI.appView.showAlert(
"Something went wrong while getting the metadata assessment scores.",
"alert-error",
this.$("#metadata-assessment-graphic")
);
}
},
renderMetrics: function(){
if(!this.hideCitationsChart)
this.renderCitationMetric();
if(!this.hideDownloadsChart)
this.renderDownloadMetric();
if(!this.hideViewsChart)
this.renderViewMetric();
var self = this;
$(window).on("resize", function(){
if(!self.hideDownloadsChart)
self.renderDownloadMetric();
if(!self.hideViewsChart)
self.renderViewMetric();
});
},
renderCitationMetric: function() {
var citationSectionEl = this.$('#user-citations');
var citationEl = this.$('.citations-metrics-list');
var citationCountEl = this.$('.citation-count');
var metricName = "Citations";
var metricCount = this.metricsModel.get("totalCitations");
citationCountEl.text(MetacatUI.appView.numberAbbreviator(metricCount,1));
// Displaying Citations
var resultDetails = this.metricsModel.get("resultDetails");
// Creating a new collection object
// Parsing result-details with citation dictionary format
var resultDetailsCitationCollection = new Array();
for (var key in resultDetails["citations"]) {
resultDetailsCitationCollection.push(resultDetails["citations"][key]);
}
var citationCollection = new Citations(resultDetailsCitationCollection, {parse:true});
this.citationCollection = citationCollection;
// Checking if there are any citations available for the List display.
if(this.metricsModel.get("totalCitations") == 0) {
var citationList = new CitationList();
// reattaching the citations at the bottom when the counts are 0.
var detachCitationEl = this.$(citationSectionEl).detach();
this.$('.charts-container').append(detachCitationEl);
}
else {
var citationList = new CitationList({citations: this.citationCollection});
}
this.citationList = citationList;
citationEl.html(this.citationList.render().$el.html());
},
renderDownloadMetric: function() {
var downloadEl = this.$('.downloads-metrics > .metric-chart');
var metricName = "Downloads";
var metricCount = this.metricsModel.get("totalDownloads");
var downloadCountEl = this.$('.download-count');
downloadCountEl.text(MetacatUI.appView.numberAbbreviator(metricCount,1));
downloadEl.html(this.drawMetricsChart(metricName));
},
renderViewMetric: function() {
var viewEl = this.$('.views-metrics > .metric-chart');
var metricName = "Views";
var metricCount = this.metricsModel.get("totalViews");
var viewCountEl = this.$('.view-count');
viewCountEl.text(MetacatUI.appView.numberAbbreviator(metricCount,1));
viewEl.html(this.drawMetricsChart(metricName));
},
// Currently only being used for portals and profile views
drawMetricsChart: function(metricName){
var metricNameLemma = metricName.toLowerCase()
var metricMonths = this.metricsModel.get("months");
var metricCount = this.metricsModel.get(metricNameLemma);
var chartEl = document.getElementById('user-'+metricNameLemma+'-chart' );
var width = (chartEl && chartEl.offsetWidth)? chartEl.offsetWidth : 1080;
var viewType = this.userType;
// Draw a metric chart
var modalMetricChart = new MetricsChart({
id: metricNameLemma + "-chart",
metricCount: metricCount,
metricMonths: metricMonths,
type: viewType,
metricName: metricName,
width: width
});
return modalMetricChart.render().el;
},
drawDataCountChart: function(){
var dataCount = this.model.get('dataCount');
var data = this.model.get('dataFormatIDs');
if(dataCount){
var svgClass = "data";
}
else if(!this.model.get('dataCount') && this.model.get('metadataCount')){ //Are we drawing a blank chart (i.e. 0 data objects found)?
var svgClass = "data default";
}
else if(!this.model.get('metadataCount') && !this.model.get('dataCount'))
var svgClass = "data no-activity";
//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: this.model.get('dataCount'),
titleText: "data files",
titleCount: dataCount,
svgClass: svgClass,
countClass: "data",
height: 300,
width: 380,
formatLabel: function(name){
//If this is the application/vnd.ms-excel formatID - let's just display "MS Excel"
if((name !== undefined) && (name.indexOf("ms-excel") > -1)) name = "MS Excel";
else if((name != undefined) && (name == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) name= "MS Excel OpenXML"
else if((name != undefined) && (name == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")) name= "MS Word OpenXML"
//Application/octet-stream - shorten it
else if((name !== undefined) && (name == "application/octet-stream")) name = "Application file";
if(name === undefined) name = "";
return name;
}
});
this.$('.format-charts-data').html(donut.render().el);
},
drawMetadataCountChart: function(){
var metadataCount = this.model.get("metadataCount");
var data = this.model.get('metadataFormatIDs');
if(metadataCount){
var svgClass = "metadata";
}
else if(!this.model.get('metadataCount') && this.model.get('dataCount')){ //Are we drawing a blank chart (i.e. 0 data objects found)?
var svgClass = "metadata default";
}
else if(!this.model.get('metadataCount') && !this.model.get('dataCount'))
var svgClass = "metadata no-activity";
//If d3 isn't supported in this browser or didn't load correctly, insert a text title instead
if(!d3){
this.$('.format-charts-metadata').html("<h2 class='" + svgClass + " fallback'>" + MetacatUI.appView.commaSeparateNumber(metadataCount) + " metadata files</h2>");
return;
}
//Draw a donut chart
var donut = new DonutChart({
id: "metadata-chart",
data: data,
total: this.model.get('metadataCount'),
titleText: "metadata files",
titleCount: metadataCount,
svgClass: svgClass,
countClass: "metadata",
height: 300,
width: 380,
formatLabel: function(name){
if((name !== undefined) && ((name.indexOf("//ecoinformatics.org") > -1) || (name.indexOf("//eml.ecoinformatics.org") > -1))){
//EML - extract the version only
if((name.substring(0,4) == "eml:") || (name.substring(0,6) == "https:")) name = name.substr(name.lastIndexOf("/")+1).toUpperCase().replace('-', ' ');
//EML modules
if((name.indexOf("-//ecoinformatics.org//eml-") > -1) || (name.indexOf("-//eml.ecoinformatics.org//eml-") > -1)) name = "EML " + name.substring(name.indexOf("//eml-")+6, name.lastIndexOf("-")) + " " + name.substr(name.lastIndexOf("-")+1, 5);
}
//Dryad - shorten it
else if((name !== undefined) && (name == "http://datadryad.org/profile/v3.1")) name = "Dryad 3.1";
//FGDC - just display "FGDC {year}"
else if((name !== undefined) && (name.indexOf("FGDC") > -1)) name = "FGDC " + name.substring(name.length-4);
//Onedcx v1.0
else if((name !== undefined) && (name == "http://ns.dataone.org/metadata/schema/onedcx/v1.0")) name = "Onedcx v1.0";
//GMD-NOAA
else if((name !== undefined) && (name == "http://www.isotc211.org/2005/gmd-noaa")) name = "GMD-NOAA";
//GMD-PANGAEA
else if((name !== undefined) && (name == "http://www.isotc211.org/2005/gmd-pangaea")) name = "GMD-PANGAEA";
if(name === undefined) name = "";
return name;
}
});
this.$('.format-charts-metadata').html(donut.render().el);
},
//drawUploadChart will get the upload stats from the stats model and draw a time series cumulative chart
drawUploadChart: function(){
//Get the width of the chart by using the parent container width
var parentEl = this.$('.upload-chart');
var width = parentEl.width() || null;
//If there was no first upload, draw a blank chart and exit
if( (!this.model.get("metadataUploads") || !this.model.get("metadataUploads").length) && (!this.model.get("dataUploads") || !this.model.get("dataUploads").length) ){
var lineChartView = new LineChart(
{ id: "upload-chart",
yLabel: "files uploaded",
frequency: 0,
width: width
});
this.$('.upload-chart').html(lineChartView.render().el);
return;
}
//Set the frequency of our points
var frequency = 12;
//Check which line we should draw first since the scale will be based off the first line
if(this.model.get("metadataUploads") > this.model.get("dataUploads") ){
//If there isn't a lot of point to graph, draw points more frequently on the line
if(this.model.get("metadataUploadDates").length < 40) frequency = 1;
//Create the line chart and draw the metadata line
var lineChartView = new LineChart(
{ data: this.model.get('metadataUploadDates'),
formatFromSolrFacets: true,
cumulative: true,
id: "upload-chart",
className: "metadata",
yLabel: "files uploaded",
labelValue: "Metadata: ",
// frequency: frequency,
radius: 2,
width: width,
labelDate: "M-y"
});
this.$('.upload-chart').html(lineChartView.render().el);
//Only draw the data file line if there was at least one uploaded
if(this.model.get("dataUploads")){
//Add a line to our chart for data uploads
lineChartView.className = "data";
lineChartView.labelValue ="Data: ";
lineChartView.addLine(this.model.get('dataUploadDates'));
}
}
else{
var lineChartView = new LineChart(
{ data: this.model.get('dataUploadDates'),
formatFromSolrFacets: true,
cumulative: true,
id: "upload-chart",
className: "data",
yLabel: "files uploaded",
labelValue: "Data: ",
// frequency: frequency,
radius: 2,
width: width,
labelDate: "M-y"
});
this.$('.upload-chart').html(lineChartView.render().el);
//If no metadata files were uploaded, we don't want to draw the data file line
if(this.model.get("metadataUploads")){
//Add a line to our chart for metadata uploads
lineChartView.className = "metadata";
lineChartView.labelValue = "Metadata: ";
lineChartView.addLine(this.model.get('metadataUploadDates'));
}
}
},
//drawUploadTitle will draw a circle badge title for the uploads time series chart
drawUploadTitle: function(){
//If d3 isn't supported in this browser or didn't load correctly, insert a text title instead
if(!d3){
this.$('#uploads-title').html("<h2 class='packages fallback'>" + MetacatUI.appView.commaSeparateNumber(this.model.get('totalCount')) + "</h2>");
return;
}
if(!this.model.get('dataUploads') && !this.model.get('metadataUploads')){
//Draw the upload chart title
var uploadChartTitle = new CircleBadge({
id: "upload-chart-title",
className: "no-activity",
globalR: 60,
data: [{ count: 0, label: "uploads" }]
});
this.$('#uploads-title').prepend(uploadChartTitle.render().el);
return;
}
//Get information for our upload chart title
var titleChartData = [],
metadataUploads = this.model.get("metadataUploads"),
dataUploads = this.model.get("dataUploads"),
metadataClass = "metadata",
dataClass = "data";
if(metadataUploads == 0) metadataClass = "default";
if(dataUploads == 0) dataClass = "default";
var titleChartData = [
{count: this.model.get("metadataUploads"), label: "metadata", className: metadataClass},
{count: this.model.get("dataUploads"), label: "data", className: dataClass}
];
//Draw the upload chart title
var uploadChartTitle = new CircleBadge({
id: "upload-chart-title",
data: titleChartData,
className: "chart-title",
useGlobalR: true,
globalR: 60
});
this.$('#uploads-title').prepend(uploadChartTitle.render().el);
},
/*
* drawTotalCount - draws a simple count of total metadata files/datasets
*/
drawTotalCount: function(){
var className = "";
if( !this.model.get("metadataCount") && !this.model.get("dataCount") )
className += " no-activity";
var chartData = [{
count: this.model.get("metadataCount"),
className: "packages" + className
}];
//Create the circle badge
var countBadge = new CircleBadge({
id: "total-datasets-title",
data: chartData,
title: "datasets",
titlePlacement: "inside",
useGlobalR: true,
globalR: 100,
height: 220
});
this.$('#total-datasets').html(countBadge.render().el);
},
/*
* drawTotalSize draws a CircleBadgeView with the total file size of
* all current metadata and data files
*/
drawTotalSize: function(){
if( !this.model.get("totalSize") ){
var chartData = [{
count: "0 bytes",
className: "packages no-activity"
}];
}
else{
var chartData = [{
count: this.bytesToSize( this.model.get("totalSize") ),
className: "packages"
}];
}
//Create the circle badge
var sizeBadge = new CircleBadge({
id: "total-size-title",
data: chartData,
title: "of content",
titlePlacement: "inside",
useGlobalR: true,
globalR: 100,
height: 220
});
this.$('#total-size').html(sizeBadge.render().el);
},
/**
* Draws both the metadata and data update date charts.
* Note that this function may be deprecated in the future.
* Views should directly call drawMetadataUpdatesChart() or drawDataUpdatesChart() directly,
* since metadata and data dates are fetched via separate AJAX calls.
*/
drawUpdatesChart: function(){
//Draw the metadata and data updates charts
this.drawMetadataUpdatesChart();
this.drawDataUpdatesChart();
},
/**
* Draws a line chart representing the latest metadata updates over time
*/
drawMetadataUpdatesChart: function(){
//Set some configurations for the LineChart
var chartClasses = "data",
data;
//If the number of metadata objects in this data collection is 0, then set the data for the LineChart to null.
// And add a "no-activity" class to the chart.
if( !this.model.get("metadataUpdateDates") || !this.model.get("metadataUpdateDates").length ){
data = null;
chartClasses += " no-activity";
}
else{
//Use the metadata update dates for the LineChart
data = this.model.get('metadataUpdateDates');
}
//Create the line chart for metadata updates
var metadataLineChart = new LineChart({
data: data,
formatFromSolrFacets: true,
cumulative: false,
id: "updates-chart",
className: chartClasses,
yLabel: "metadata files updated",
radius: 2,
width: this.$('.metadata-updates-chart').width(),
labelDate: "M-y"
});
//Render the LineChart and insert it into the container element
this.$('.metadata-updates-chart').html(metadataLineChart.render().el);
},
/**
* Draws a line chart representing the latest metadata updates over time
*/
drawDataUpdatesChart: function(){
//Set some configurations for the LineChart
var chartClasses = "data",
data;
//Use the data update dates for the LineChart
if(this.model.get("dataCount")){
data = this.model.get('dataUpdateDates');
}
else{
//If the number of data objects in this data collection is 0, then set the data for the LineChart to null.
// And add a "no-activity" class to the chart.
data = null;
chartClasses += " no-activity";
}
//Create the line chart for data updates
var dataLineChart = new LineChart({
data: data,
formatFromSolrFacets: true,
cumulative: false,
id: "updates-chart",
className: chartClasses,
yLabel: "data files updated",
radius: 2,
width: this.$('.data-updates-chart').width(),
labelDate: "M-y"
});
//Render the LineChart and insert it into the container element
this.$('.data-updates-chart').html(dataLineChart.render().el);
},
//Draw a bar chart for the temporal coverage
drawCoverageChart: function(e, data){
//Get the width of the chart by using the parent container width
var parentEl = this.$('.temporal-coverage-chart');
var width = parentEl.width() || null;
// If results were found but none have temporal coverage, draw a default chart
if(!this.model.get('temporalCoverage')){
parentEl.html("<p class='subtle center'>There are no metadata documents that describe temporal coverage.</p>");
return;
}
var options = {
data: data,
formatFromSolrFacets: true,
id: "temporal-coverage-chart",
yLabel: "data packages",
yFormat: d3.format(",d"),
barClass: "packages",
roundedRect: true,
roundedRadius: 3,
barLabelClass: "packages",
width: width
};
var barChart = new BarChart(options);
parentEl.html(barChart.render().el);
},
drawCoverageChartTitle: function(){
if((!this.model.get('firstBeginDate')) || (!this.model.get('lastEndDate')) || !this.model.get("temporalCoverage") ) return;
//Create the range query
var yearRange = this.model.get('firstBeginDate').getUTCFullYear() + " - " + this.model.get('lastEndDate').getUTCFullYear();
//Find the year range element
this.$('#data-coverage-year-range').text(yearRange);
},
/*
* Shows that this person/group/node has no activity
*/
showNoActivity: function(){
if( this.model.get("metadataCount") === 0 && this.model.get("dataCount") === 0 ){
this.$(".show-loading .loading").remove();
this.$(".stripe").addClass("no-activity");
}
},
/**
* Convert number of bytes into human readable format
*
* @param integer bytes Number of bytes to convert
* @param integer precision Number of digits after the decimal separator
* @return string
*/
bytesToSize: function(bytes, precision){
var kilobyte = 1024;
var megabyte = kilobyte * 1024;
var gigabyte = megabyte * 1024;
var terabyte = gigabyte * 1024;
if(typeof bytes === "undefined") var bytes = this.get("size");
if ((bytes >= 0) && (bytes < kilobyte)) {
return bytes + ' B';
} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
return (bytes / kilobyte).toFixed(precision) + ' KB';
} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
return (bytes / megabyte).toFixed(precision) + ' MB';
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
return (bytes / gigabyte).toFixed(precision) + ' GB';
} else if (bytes >= terabyte) {
return (bytes / terabyte).toFixed(precision) + ' TB';
} else {
return bytes + ' B';
}
},
onClose: function () {
//Clear the template
this.$el.html("");
//Stop listening to changes in the model
this.stopListening(this.model);
//Reset the stats model
this.model = null;
},
renderUsageMetricsError: function() {
// Remove the Spinning icons and display error
var metricsEls = new Array();
metricsEls.push('.citations-metrics-list');
metricsEls.push('#user-downloads-chart');
metricsEls.push('#user-views-chart');
// for each of the usage metrics section
metricsEls.forEach(function(iconEl) {
var errorMessage = "";
if(iconEl === ".citations-metrics-list") {
errorMessage = "Something went wrong while getting the citation metrics.";
}
else if(iconEl === '#user-downloads-chart') {
errorMessage = "Something went wrong while getting the download metrics.";
}
else if(iconEl === "#user-views-chart") {
errorMessage = "Something went wrong while getting the view metrics.";
}
else {
errorMessage = "Something went wrong while getting the usage metrics.";
}
// remove the loading icon
$(iconEl).find('.metric-chart-loading').css("display", "none");
// display the error message
MetacatUI.appView.showAlert(
errorMessage,
"alert-error",
$(iconEl)
);
});
}
});
return StatsView;
});