forked from AABoyles/MicrobeTrace
-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
62 changed files
with
121,195 additions
and
8,107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
npm-debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,7 @@ | ||
FROM node:8 | ||
|
||
# Copy dependency info | ||
COPY package*.json /usr/src/app/ | ||
|
||
# Change working directory | ||
FROM node:11.12.0 | ||
WORKDIR /usr/src/app/ | ||
|
||
# Install dependencies | ||
COPY package*.json ./ | ||
RUN npm install | ||
|
||
# Copy source code | ||
COPY . /usr/src/app/ | ||
|
||
# Expose API port to the outside | ||
COPY . . | ||
EXPOSE 5000 | ||
|
||
# Launch application | ||
CMD ["npm","start"] |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
/ | ||
index.html | ||
package.json | ||
manifest.json | ||
node_modules/chosen-js/chosen-sprite.png | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
<div class="view-controls"> | ||
<button type="button" id="aggregation-settings-toggle" class="btn btn-light btn-sm" title="Toggle Aggregation Settings"> | ||
<span class="oi oi-cog"></span> | ||
</button> | ||
<button type="button" class="btn btn-light btn-sm" data-toggle="modal" data-target="#aggregation-export-modal" title="Export Aggregation data"> | ||
<span class="oi oi-data-transfer-download"></span> | ||
</button> | ||
</div> | ||
|
||
<div id="aggregation" class="table-sm"></div> | ||
|
||
<div id="aggregation-settings-pane" class="left-pane"> | ||
<ul class="nav nav-tabs" role="tablist"> | ||
<li class="nav-item active"> | ||
<a href="#aggregation-settings" id="aggregation-tab" class="nav-link active" aria-controls="aggregation" role="tab" data-toggle="tab">Aggregation</a> | ||
</li> | ||
</ul> | ||
<div class="tab-content"> | ||
<div class="tab-pane fade show active" role="tabpanel" aria-labelledby="aggregation-tab"> | ||
<div class="form-group row" title="What data would you like to aggregate?"> | ||
<div class="col-4">Data</div> | ||
<div class="col-8"> | ||
<div class="btn-group btn-group-toggle btn-group-sm w-100" data-toggle="buttons"> | ||
<label class="btn btn-light col active"> | ||
<input type="radio" name="aggregate-dataset" data-value="node" autocomplete="off" checked> Nodes | ||
</label> | ||
<label class="btn btn-light col"> | ||
<input type="radio" name="aggregate-dataset" data-value="link" autocomplete="off"> Links | ||
</label> | ||
<label class="btn btn-light"> | ||
<input type="radio" name="aggregate-dataset" data-value="cluster" autocomplete="off"> Clusters | ||
</label> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="form-group row" title="What data field would you like to aggregate on?"> | ||
<div class="col-4">Variable</div> | ||
<div class="col-8"> | ||
<select id="aggregate-variable" class="custom-select custom-select-sm"></select> | ||
</div> | ||
</div> | ||
<div class="form-group row" title="Would you like to group variables that are close together?"> | ||
<div class="col-4">Binning</div> | ||
<div class="col-8"> | ||
<div class="btn-group btn-group-toggle btn-group-sm w-100" data-toggle="buttons"> | ||
<label class="btn btn-light col active"> | ||
<input type="radio" name="aggregate-binning" data-value="off" autocomplete="off" checked> Unbinned | ||
</label> | ||
<label class="btn btn-light col"> | ||
<input type="radio" name="aggregate-binning" data-value="on" autocomplete="off"> Binned | ||
</label> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="form-group row" id="aggregate-bins-row" title="How many bins would you like to sort that data into?"> | ||
<div class="col-4">Number of Bins</div> | ||
<div class="col-8"> | ||
<input id="aggregate-bins" class="custom-select custom-select-sm" type="number" min="1" value="10" step="1"></input> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div id="aggregation-export-modal" class="modal fade" tabindex="-1" role="dialog" data-backdrop="false"> | ||
<div class="modal-dialog" role="document"> | ||
<div class="modal-content"> | ||
<div class="modal-header"> | ||
<h5 class="modal-title">Export Aggregation</h5> | ||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> | ||
<span aria-hidden="true">×</span> | ||
</button> | ||
</div> | ||
<div class="modal-body"> | ||
<div class="form-group row"> | ||
<div class="col-9"> | ||
<input type="text" id="export-aggregation-file-name" class="form-control form-control-sm" placeholder="Filename" /> | ||
</div> | ||
<div class="col-3"> | ||
<select id="export-aggregation-file-type" class="form-control form-control-sm"> | ||
<option selected>csv</option> | ||
<option>xlsx</option> | ||
<option>json</option> | ||
</select> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="modal-footer"> | ||
<button type="button" class="btn btn-error" data-dismiss="modal">Cancel</button> | ||
<button type="button" id="aggregation-export" class="btn btn-primary" data-dismiss="modal">Export</button> | ||
</div> | ||
</div><!-- /.modal-content --> | ||
</div><!-- /.modal-dialog --> | ||
</div><!-- /.modal --> | ||
|
||
<script> | ||
(function(){ | ||
|
||
let data = []; | ||
|
||
let aggregation = new Tabulator("#aggregation", { | ||
height: "calc(100% - 60px) !important", | ||
layout: "fitColumns" | ||
}); | ||
|
||
function updateColumns(){ | ||
let dataset = $('input[name=aggregate-dataset]:checked').data('value'); | ||
$('#aggregate-variable').html( | ||
session.data[dataset + 'Fields'] | ||
.map(l => `<option value="${l}">${app.titleize(l)}</option>`) | ||
.join('\n') | ||
).val(dataset === 'cluster' ? 'ID' : 'cluster'); | ||
} | ||
|
||
function updateTable(){ | ||
let dataset = $('input[name=aggregate-dataset]:checked').data('value'); | ||
let column = $('#aggregate-variable').val(); | ||
let binned = $('[name="aggregate-binning"]:checked').data('value') === 'on'; | ||
let values = []; | ||
data = []; | ||
let rawdata = app['getVisible' + dataset[0].toUpperCase() + dataset.slice(1) + 's'](); | ||
let n = rawdata.length; | ||
if(binned){ | ||
let values = rawdata.map(r => r[column]).sort((a, b) => a - b); | ||
let perBin = Math.ceil(n/$('#aggregate-bins').val()); | ||
values.forEach((row, i) => { | ||
let bin = data[Math.floor(i/perBin)]; | ||
if(bin){ | ||
bin.n++; | ||
bin.max = row; | ||
bin[column] = bin.min + '-' + bin.max; | ||
} else { | ||
data.push({ | ||
n: 1, | ||
min: row, | ||
max: row | ||
}); | ||
} | ||
}); | ||
console.log(data); | ||
} else { | ||
rawdata.forEach(row => { | ||
let val = row[column]; | ||
if(values.includes(val)){ | ||
data[values.indexOf(val)].n++; | ||
} else { | ||
values.push(val); | ||
let newRow = {}; | ||
newRow[column] = val; | ||
newRow.n = 1; | ||
data.push(newRow); | ||
} | ||
}); | ||
} | ||
data.forEach(row => row.percent = (row.n/n*100).toLocaleString() + '%'); | ||
aggregation.setColumns([ | ||
{title: app.titleize(dataset + ' ' + column), field: column}, | ||
{title: 'Number of ' + app.titleize(dataset) + 's', field: 'n'}, | ||
{title: 'Percentage', field: 'percent', headerSort: false} | ||
]); | ||
aggregation.setData(data); | ||
if(!binned){ | ||
aggregation.setSort([ | ||
{column: 'n', dir: 'desc'}, | ||
{column: column, dir: 'asc'} | ||
]); | ||
} | ||
} | ||
|
||
$('#aggregation-settings-toggle').click(function(){ | ||
let pane = $('#aggregation-settings-pane'); | ||
if(pane.is(':visible')){ | ||
pane.animate({left: '-400px'}, function(){ pane.hide(); }); | ||
} else { | ||
pane.show(0, function(){ pane.animate({left: '0px'}); }); | ||
} | ||
}); | ||
|
||
$('input[name="aggregate-dataset"]').on('change', e => { | ||
updateColumns(); | ||
updateTable(); | ||
}); | ||
|
||
$('#aggregate-variable').on('change', updateTable); | ||
|
||
$('[name="aggregate-binning"]').on('change', function(){ | ||
let val = $(this).data('value'); | ||
if(val == 'on'){ | ||
$('#aggregate-bins-row').css('display', 'flex'); | ||
} else { | ||
$('#aggregate-bins-row').slideUp(); | ||
} | ||
updateTable(); | ||
}); | ||
|
||
$('#aggregate-bins').on('change', updateTable); | ||
|
||
$('#aggregation-export').click(function(){ | ||
let format = $('#export-aggregation-file-type').val(); | ||
let name = $('#export-aggregation-file-name').val(); | ||
if(format === 'csv'){ | ||
let blob = new Blob([Papa.unparse(data)], {type: 'text/csv;charset=utf-8'}); | ||
saveAs(blob, name + '.' + format); | ||
} else if(format === 'xlsx'){ | ||
let wb = XLSX.utils.book_new(); | ||
let ws = XLSX.utils.json_to_sheet(data); | ||
XLSX.utils.book_append_sheet(wb, ws, name); | ||
XLSX.writeFile(wb, name + '.' + format); | ||
} else { | ||
let blob = new Blob([JSON.stringify(data)], {type: 'application/json;charset=utf-8'}); | ||
saveAs(blob, name + '.' + format); | ||
} | ||
}); | ||
|
||
$('#aggregation').parent().css('z-index', 1000); | ||
|
||
$(window) | ||
.on('link-threshold-change', updateTable); | ||
|
||
updateColumns(); | ||
updateTable(); | ||
})(); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.