Skip to content

Commit

Permalink
Merge pull request #566 from camicroscope/export-page
Browse files Browse the repository at this point in the history
Add an Export page
  • Loading branch information
birm committed Sep 10, 2022
2 parents 6029699 + ecc01af commit 989efab
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 6 deletions.
41 changes: 41 additions & 0 deletions apps/port/export.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<script src="../../core/Store.js"></script>
<title>Export Results [caMicroscope]</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
<style>
body{
padding:20px;
}
#output{
padding: 20px;
}
span{
display:inline-block;
}
.form-check-input{
padding:5px !important;
}
</style>
</head>
<body>

<h1>Export Results</h1>
<div class="form">
<label for="slide_id">Slide Ids (exact matches, comma delimited):</label>
<input type="text" id="slide_id" name="slide_id"><br>

<button id="populate_btn" onclick="populateList()" type="button">Get List of Results</button>

</div>
<br><br>
<h3>Select Results</h3>
<div id="output"></div>
<button id="convert_btn" onclick="downloadResults()" type="button">Download Selected Results</button>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8" crossorigin="anonymous"></script>
<script src="//code.jquery.com/jquery.min.js"></script>
<script src="./tree_table.js"></script>
<script src="./export.js"></script>
</body>
</html>
156 changes: 156 additions & 0 deletions apps/port/export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
const store = new Store('../../data/');

async function populateList() {
// clear any previous
document.getElementById('output').innerHTML = '';
console.log('populating list...');
nameField = 'name';
// get slide and associated result information
let slides = [];
let results = {};
let slideList = document.getElementById('slide_id').value;
slideList = slideList.replace(/\s+/g, '');
slideList = slideList.split(',');
for (let id of slideList) {
let slide = await store.getSlide(id);
slide = slide[0];
if (slide && slide['_id']) {
let s = {'id': slide['_id']['$oid'], 'name': slide['name'], 'type': 'slide', 'raw': slide};
console.log(s);
slides.push(s);
// get associated result types
r = [];
for (let a of await store.findMarkTypes(slide['_id']['$oid'], 'computer')) {
r.push({'id': a['_id']['analysis']['execution_id'], 'name': a['_id']['analysis']['name'], 'type': 'computer mark'});
}
for (let a of await store.findMarkTypes(slide['_id']['$oid'], 'human')) {
r.push({'id': a['_id']['analysis']['execution_id'], 'name': a['_id']['analysis']['name'], 'type': 'human mark'});
}
// todo -- is this right for heatmapType results?
for (let a of await store.findHeatmapType(slide['_id']['$oid'])) {
r.push({'id': a['provenance']['analysis']['execution_id'],
'name': a['provenance']['analysis']['execution_id'], 'type': 'heatmap'});
}
results[slide['_id']['$oid']] = r;
}
}

let headers = ['name', 'id', 'type'];
let t = document.createElement('table');
t.id = 'tree-table';
t.classList.add('table', 'table-hover', 'table-bordered');
// add headers
let table = document.createElement('tbody');
let headerTr = document.createElement('tr');
for (let z of headers) {
let th = document.createElement('th');
th.innerText = z || '?';
headerTr.appendChild(th);
}
// add select header special
let selectTh = document.createElement('th');
selectTh.innerText = 'Select';
headerTr.appendChild(selectTh);
table.append(headerTr);
// populate results
for (let x of slides) {
let parent = document.createElement('tr');
parent.setAttribute('data-id', x.id);
parent.setAttribute('data-parent', 0);
parent.setAttribute('data-level', 1);
for (let z of headers) {
let d = document.createElement('td');
d.innerText = x[z] || '?';
if (z==nameField) {
d.setAttribute('data-column', 'name');
}
parent.appendChild(d);
}
// add special checkbox
parentCheck = document.createElement('input');
parentCheck.classList.add('form-check-input');
parentCheck.type = 'checkbox';
parentCheck.indeterminate = true; // cool!
// TODO -- finish this. you'd want to add logic that sets this checkbox to true, false or indeterminate
// depending on children selection. also select/deselect all children on change of this.
// parent.appendChild(parentCheck);
table.appendChild(parent);
for (let y of results[x.id]) {
console.log(x.raw);
let child = document.createElement('tr');
child.setAttribute('data-id', x.id+'-'+y.id);
child.setAttribute('data-parent', x.id);
child.setAttribute('data-level', 2);
for (let z of headers) {
let d = document.createElement('td');
d.innerText = y[z] || '?';
if (z==nameField) {
d.setAttribute('data-column', 'name');
}
child.appendChild(d);
}
// special checkbox
childCheck = document.createElement('input');
childCheck.type = 'checkbox';
childCheck.classList.add('form-check-input');
childCheck.classList.add('result');
childCheck.setAttribute('data-target', x.id);
childCheck.setAttribute('data-self', y.id);
childCheck.setAttribute('data-slideInfo', JSON.stringify(x.raw));
childCheck.setAttribute('data-type', y.type);
childCheck.checked = true;
child.appendChild(childCheck);
table.appendChild(child);
}
}
t.appendChild(table);
document.getElementById('output').appendChild(t);
makeTreeTable('tree-table');
}

async function downloadResults() {
let checks = document.querySelectorAll('.result:checked');
let marks = [];
let heatmaps = [];
for (let c of checks) {
console.log(c.dataset);
let parentSlide = JSON.parse(checks[0].dataset.slideinfo);
if (c.dataset.type == 'human mark' || c.dataset.type == 'human mark') {
let mark = await store.getMarkByIds([c.dataset.self], c.dataset.target);
for (m of mark) {
m.provenance.image = parentSlide;
marks.push(m);
}
console.log(mark);
} else if (c.dataset.type == 'heatmap' ) {
let hm = await store.getHeatmap(c.dataset.parent, c.dataset.target);
for (h of hm) {
h.provenance.image = parentSlide;
heatmaps.push(h);
}
}
}
console.log(marks, heatmaps);
if (marks.length) {
var element = document.createElement('a');
element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(marks)));
element.setAttribute('download', 'camic_export_marks.json');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
if (heatmaps.length) {
var element = document.createElement('a');
element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(heatmaps)));
element.setAttribute('download', 'camic_export_heatmaps.json');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
// tell the user that data is missing
if (!heatmaps.length && !marks.length) {
alert('No data selected for download.');
}
}
2 changes: 1 addition & 1 deletion apps/port/index.html → apps/port/import.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html>
<head>
<script src="../../core/Store.js"></script>
<script src="./port.js"></script>
<script src="./import.js"></script>
<script src="./xml2geo.js"></script>
<link rel="stylesheet" href="./style.css">
<title>Import and Export [caMicroscope]</title>
Expand Down
File renamed without changes.
64 changes: 64 additions & 0 deletions apps/port/tree_table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
function makeTreeTable(id) {
var
$table = $('#' + id);
var rows = $table.find('tr');

rows.each(function(index, row) {
var
$row = $(row);
var level = $row.data('level');
var id = $row.data('id');
var $columnName = $row.find('td[data-column="name"]');
var children = $table.find('tr[data-parent="' + id + '"]');

if (children.length) {
var expander = $columnName.prepend('' +
'<span class="treegrid-expander glyphicon glyphicon-chevron-right">&#9660;</span>' +
'');

children.hide();

expander.on('click', function(e) {
var $target = $(e.target);
if ($target.hasClass('glyphicon-chevron-right')) {
$target
.removeClass('glyphicon-chevron-right')
.addClass('glyphicon-chevron-down');

children.show();
} else {
$target
.removeClass('glyphicon-chevron-down')
.addClass('glyphicon-chevron-right');

reverseHide($table, $row);
}
});
}

$columnName.prepend('' +
'<span class="treegrid-indent" style="width:' + 25 * level + 'px"></span>' +
'');
});

// Reverse hide all elements
reverseHide = function(table, element) {
var
$element = $(element);
var id = $element.data('id');
var children = table.find('tr[data-parent="' + id + '"]');

if (children.length) {
children.each(function(i, e) {
reverseHide(table, e);
});

$element
.find('.glyphicon-chevron-down')
.removeClass('glyphicon-chevron-down')
.addClass('glyphicon-chevron-right');

children.hide();
}
};
}
13 changes: 8 additions & 5 deletions apps/table.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
<li class="nav-item link">
<a class="nav-link" href="./dev-workbench/workbench.html"> <i class="fas fa-pencil-ruler"></i> Workbench</a>
</li>
<li class="nav-item link">
<a class="nav-link" href="./port/export.html"> <i class="fas fa-solid fa-file-export"></i> Export</a>
</li>
<li class="nav-item link" style="font-family: sans-serif;">
<a class="nav-link" href="./signup/signup.html"> <i class="fas fa-user-plus"></i> Signup</a>
</li>
Expand Down Expand Up @@ -136,7 +139,7 @@ <h1 class="h1">caMicroscope</h1>
onclick="(()=>{location.reload();return false;})()"> <i class="fas fa-sync-alt"></i>
Reload</button>
</div>
<div>
<div>
<div id="slideUploadButton" class="btn-group float-right pl-md-2 pt-2">
<button type="button" class="btn btn-primary " data-bs-toggle="modal"
data-bs-target="#upload-dialog" onclick="hidePostButton(); hideCheckButton(); resetUploadForm();" > <i class="fas fa-upload"></i> Upload</button>
Expand All @@ -149,12 +152,12 @@ <h1 class="h1">caMicroscope</h1>
</div>
</div>
</div>


</div>
</div>
</div>



<div class="modal fade" id="upload-dialog" tabindex="-1" role="dialog"
Expand Down Expand Up @@ -285,7 +288,7 @@ <h5 class="modal-title" id="slideNameChangeModalLabel">Slide name change confirm
</div>
</div>
</div>
<!-- popup -->
<!-- popup -->
<div id="popup-container"></div>
</div>

Expand All @@ -295,7 +298,7 @@ <h5 class="modal-title" id="slideNameChangeModalLabel">Slide name change confirm
<footer class="text-center text-white bg-dark p-3">
<p class="p">Copyright © 2021 caMicroscope</p>
</footer>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous"></script>
<script src="./table.js"></script>
</body>
Expand Down

0 comments on commit 989efab

Please sign in to comment.