function waitDialog() { bootbox.dialog({ title: "Clade Classification", message: '

Uploading data

45% Complete
' }); } //TODO: find correct parameter bootbox.animate = false; class Haplogroups { colors = ['#4E79A7', '#A0CBE8', '#F28E2B', '#FFBE7D', '#59A14F', '#8CD17D', '#B6992D', '#F1CE63', '#499894', '#86BCB6', '#E15759', '#FF9D9A', '#79706E', '#BAB0AC', '#D37295', '#FABFD2', '#B07AA1', '#D4A6C8', '#9D7660', '#D7B5A6' ]; chart; dataset; index = 0; constructor(id) { this.id = id; } setDataset(dataset) { this.dataset = dataset; } setIndex(index) { this.index = index; } draw() { this.destroy(); var group = this.dataset.groups[this.index]; var data = { labels: group.clades, datasets: [{ label: 'Samples', data: group.values, hoverOffset: 4, backgroundColor: group.colors ? group.colors : this.colors }] }; var config = { type: 'doughnut', data: data, options: { plugins: { legend: { labels: { boxWidth: 20 } } }, animation: { animateRotate: false } }, responsive: true, maintainAspectRatio: false }; this.chart = new Chart(document.getElementById(this.id), config); } destroy() { if (this.chart != undefined) { this.chart.destroy(); this.chart = undefined; } } } class SamplesTable { id; maxMutations = 8; table; samples; phylotree; filter = 'all'; server = ''; constructor(id) { this.id = id; } setSamples(samples) { this.samples = samples; } setPhylotree(phylotree) { this.phylotree = phylotree; } setServer(serverUrl) { this.serverUrl = serverUrl; } render() { this.destroy(); var self = this; this.table = $("#" + this.id).DataTable({ pageLength: 50, lengthChange: false, fixedHeader: { headerOffset: $('#navigation').outerHeight() }, data: samples, "columns": [{ data: "hasError", "render": function(data, type, row) { if (type == 'display') { return self.renderIcon(row); } else { return self.renderText(row); } }, width: "20px" }, { "data": "sample" }, { "data": "clade" }, { "render": function(data, type, row) { return self.renderProgressBar(row.quality); } }, { "data": "ns", width: "20px" }, { "data": "coverage" }, { "data": "ranges", "render": function(data) { return data.length + ' ranges'; } }, { "data": "annotatedPolymorphisms", "render": function(data, type) { if (type == 'display') { return self.formatMutations(data); } else { return self.renderMutations(data); } } }], order: [ [1, 'asc'] ], "createdRow": function(row, data, dataIndex) { if (data.errors.length > 0) { $(row).addClass('table-danger'); return; } if (data.warnings.length > 0) { $(row).addClass('table-warning'); return; } } }); var self = this; //check to bind it to a correct instance? $.fn.dataTable.ext.search.push( function(settings, data, dataIndex) { if (self.filter === "all" || data[0] == self.filter) { return true; } return false; } ); $('#' + this.id + ' tbody').on('click', 'tr', function() { var data = self.table.row(this).data(); new SamplesDetails(self.phylotree, data, self.serverUrl).show(); }); } setSampleFilter(filter) { this.filter = filter; if (this.table != undefined) { this.table.draw(); } } setMaxMutations(maxMutations) { this.maxMutations = maxMutations; if (this.table != undefined) { this.table.rows().invalidate().draw(); } } search(query){ this.table.search(query).draw() ; } formatMutations(data) { var result = ''; for (var i = 0; i < data.length && i < this.maxMutations; i++) { var label = data[i].nuc; var found = data[i].found; if (result != '') { result += ' '; } result += '' + label + ''; } if (data.length > this.maxMutations) { result += ' and ' + (data.length - this.maxMutations) + ' more'; } return result; } renderMutations(data) { var result = ''; for (var i = 0; i < data.length; i++) { var label = data[i].nuc; if (result != '') { result += ' '; } result += label; }; return result; } renderProgressBar(value) { var percentage = value * 100; return '
' + '
' + 'Quality: ' + value.toFixed(2) + '' + '
' + '
'; } renderIcon(data) { if (data.errors.length > 0) { return ''; } if (data.warnings.length > 0) { return ''; } return ''; } renderText(data) { if (data.errors.length > 0) { return 'error'; } if (data.warnings.length > 0) { return 'warning'; } return 'ok'; } //adjust column size on tab switch autoSize() { this.table.columns.adjust(); } destroy() { if (this.table) { this.table.destroy(); } } } class SamplesDetails { phylotree; selectedMutation = undefined; constructor(phylotree, data, serverUrl) { this.phylotree = phylotree; this.data = data; this.serverUrl = serverUrl; } show() { var self = this; var dialog = bootbox.dialog({ title: self.renderIcon(self.data) + ' ' + self.data.sample, onEscape: true, buttons: { close: { label: 'Close', className: 'btn-primary', callback: function() { } } }, message: '' + '
' + '
' + '
' + '
' + '
' + ' ' + self.formatDetails() + '
' + '
' + '
' + '
' + '
' + ' ' + self.renderMutationDetails() + '
' + '
' + '
' + '
' }); dialog.find("div.modal-dialog").addClass("scroll-modal-body-horizontal"); $(".mutation").on("click", function() { self.showMutationDetails(this, self.serverUrl); }); } showMutationDetails(source, server) { if (this.selectedMutation) { $(this.selectedMutation).removeClass("selected-mutation"); } this.selectedMutation = source; $(source).addClass("selected-mutation"); var mutation = $(source).data("mutation"); var clade = $(source).data("clade"); var url = server + '/phylogenies/' + this.phylotree + '/haplogroups/' + clade + '/mutations/' + mutation + '?minimal=true'; $("#details").attr('src', url); } renderMutationDetails() { return ''; } renderIcon(data) { if (data.errors.length > 0) { return ''; } if (data.warnings.length > 0) { return ''; } return ''; } formatDetails() { var topHitUrl = '/phylogenies/' + this.phylotree + '/haplogroups/' + this.data.clade; var topHit = '' + 'Top Hit
' + '' + this.data.clade + '' + ' (' + this.data.quality.toFixed(2) * 100 + '%)' + '

'; var expectedMutation = '' + 'Expected Mutations  ' + ' ' + ' ' + '
' + this.formatExpectedMutations() + '

'; var remainingMutations = '' + 'Remaining Mutations  ' + ' ' + ' ' + '
' + this.formatRemainingMutations() + '

'; var additionalHits = '' + '
' + this.formatHits() + '
'; var ranges = '' + 'Ranges
' + this.formatRange() + '

'; return this.renderWarningsAndErrors() + topHit + expectedMutation + remainingMutations + additionalHits + ranges; } formatExpectedMutations() { var result = ''; for (var i = 0; i < this.data.expectedMutations.length; i++) { var mutation = this.data.expectedMutations[i]; var label = mutation.nuc; var found = mutation.found; var id = mutation.position + '_' + mutation.ref + '_' + mutation.alt; if (result != '') { result += ' '; } result += '' + label + ''; }; return result; } formatRemainingMutations() { var result = ''; for (var i = 0; i < this.data.remainingMutations.length; i++) { var mutation = this.data.remainingMutations[i]; var label = mutation.nuc; var type = mutation.type; var id = mutation.position + '_' + mutation.ref + '_' + mutation.alt; if (result != '') { result += ' '; } result += '' + label + ''; }; return result; } formatRange() { var result = ''; for (var i = 0; i < this.data.ranges.length; i++) { var label = this.data.ranges[i].trim(); if (label != undefined && label != '') { if (result != '') { result += ' '; } result += '' + label + ''; } }; return result; } formatHits() { var result = '
' + '' + '
    '; for (var i = 0; i < this.data.otherClades.length; i++) { var hit = this.data.otherClades[i]; var quality = this.data.otherQualities[i]; var url = '/phylogenies/' + this.phylotree + '/haplogroups/' + hit; var link = '' + hit + ''; result += '
  1. ' + link + ' (' + quality.toFixed(2) * 100 + '%)
  2. '; }; result += '
' + '
' + '
'; return result; } renderWarningsAndErrors() { var result = ""; result += this.renderIssues(this.data.errors, "danger"); result += this.renderIssues(this.data.warnings, "warning"); result += this.renderIssues(this.data.infos, "info"); return result; } renderIssues(issues, type) { var result = ""; for (var i = 0; i < issues.length; i++) { var label = issues[i].trim(); result += ''; } return result; } } console.log("Loaded app.js");