Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions graph.css
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,19 @@ input.feed-tag-checkbox-left, input.feed-tag-checkbox-right{
#legend [data-legend-series] a{
outline: none;
}

#download-buttons form{
margin: 0;
padding: 0;
}
#download-buttons form button {
width: 100%;
text-align: left;
}
.csvoptions{
width: auto;
}

@media(max-width: 512px) {
#legend .col {
position: relative; left: 0;
Expand Down
21 changes: 21 additions & 0 deletions graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,7 @@ function printcsv()
var line = [];
var lastvalue = [];
var start_time = feedlist[0].data[0][0];
var end_time = feedlist[feedlist.length-1].data[feedlist[feedlist.length-1].data.length-1][0];
var showName=false;
var showTag=false;

Expand Down Expand Up @@ -998,6 +999,26 @@ function printcsv()
}
}
$("#csv").val(csvout);

// populate download form
for (f in feedlist) {
var meta = feedlist[f];

$("[data-download]").each(function(i,elem){
$form = $(this);
var path = $form.find('[data-path]').val();
var action = $form.find('[data-action]').val();
var format = $form.find('[data-format]').val();
$form.attr('action', path + action + '.' + format);
$form.find('[name="ids"]').val(meta.id);
$form.find('[name="start"]').val(start_time);
$form.find('[name="end"]').val(end_time);
$form.find('[name="headers"]').val('names');
$form.find('[name="timeformat"]').val(csvtimeformat);
$form.find('[name="interval"]').val(view.interval);
$form.find('[name="nullvalues"]').val(csvnullvalues);
});
}
}

//----------------------------------------------------------------------------------------
Expand Down
119 changes: 118 additions & 1 deletion graph_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

function graph_controller()
{
global $session,$route,$mysqli,$redis;
global $session,$route,$mysqli,$redis, $path;

// Check if group module is installed
$group = false;
Expand Down Expand Up @@ -70,7 +70,124 @@ function graph_controller()
else if ($group && $route->action=="groupgraph") {
$result = view("Modules/graph/group_view.php", array("session" => $session["write"], 'group_support' => 1));
}
// Download data
else if ($route->action === 'download') {
$ids = explode(',', get('ids'));
$start = get('start');
$end = get('end');
$shownull = get('shownull');
$headers = get('headers'); // tags|names|none
$format = get('timeformat'); // datestr|unix|seconds
$nullvalues = get('nullvalues'); // lastvalue|remove|show

$interval = get('interval');
$skipmissing = get('skipmissing');
$limitinterval = get('limitinterval');

// @todo: make use of new multi id data endpoint
$id = $ids[0];
$url = sprintf($path. "/feed/data.json?id=%s&start=%s&end=%s&interval=%s&skipmissing=%s&limitinterval=%s",
$id, $start, $end, $interval, $skipmissing, $limitinterval
);
$input_data = json_decode(file_get_contents($url),true);
$lastvalue = null;
// create array with correctly formatted values
$data = array();
if (!isset($input_data['success'])) {
foreach($input_data as $row){
list($time, $value) = $row;
$time /= 1000;
if ($format === 'datestr') {
$time = date('c', $time);
} elseif ($format === 'seconds') {
$time = $time - $start;
}
$add_data = true;
if (is_null($value)) {
if ($nullvalues !== 'remove') {
if ($nullvalues === 'show') {
$value = null;
} elseif ($nullvalues === 'lastvalue') {
$value = $lastvalue;
}
} elseif ($nullvalues === 'remove') {
// dont add data to output
$add_data = false;
}
} else {
$lastvalue = $value;
}
if ($add_data) $data[] = array($time, $value, $row[0]);
}
}

// filename for download
$filename = "graph_data_" . date('Ymd') . '.' . $route->format;
header("Content-Disposition: attachment; filename=\"$filename\"");

// @todo: multi id api endpoint for aget.json
$url2 = sprintf($path. "/feed/aget.json?id=%s", $id);
$meta = json_decode(file_get_contents($url2), true);

// feed titles
if (isset($meta['success'])) {
$title = $meta['message'];
$unit = '';
} else {
if ($headers === 'tags') {
$title = $meta['tag'];
} else {
$title = implode(':', array($meta['tag'], $meta['name']));
}
$unit = $meta['unit'];
}

if ($route->format === 'csv') {
if (isset($input_data['success'])) {
return 'Error: ' . $input_data['message'];
}
// build csv column headings
if ($headers!=='none') {
if ($format === 'datestr') {
$col_titles[] = '"Date-time string"';
} elseif ($format === 'seconds') {
$col_titles[] = '"Seconds since start"';
} else {
$col_titles[] = '"Unix timestamp"';
}
}
$col_titles[] = '"' . $title . ' (' . $unit . ')"';
// join column headings with comma
$lines[] = implode(',', $col_titles);

// get csv data
foreach($data as $col){
$lines[] = implode(',', array($col[0], $col[1]));
}

// join all the lines with line break
return implode("\n", $lines);

} elseif($route->format === 'json') {
if (isset($input_data['success'])) return $input_data;

// return data as json object
// data returned in data property
$json['title'] = $title;
$json['name'] = $meta['name'];
$json['tag'] = $meta['tag'];
$json['id'] = $meta['id'];
$json['unit'] = $meta['unit'];
foreach($data as $val) {
$json['data'][] = array(
'timestamp'=> $val[2],
'formatted'=> $val[0],
'value'=> $val[1]
);
}
return array($json);
}
}
else {
$result = view("Modules/graph/view.php", array("session" => $session["write"]));
}
Expand Down
40 changes: 40 additions & 0 deletions view.php
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,49 @@
</select>
</div>

<div id="download-buttons" class="csvoptions btn-group input-prepend">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<?php echo _('Download') ?>
<span class="caret" style="border-top-color:black!important"></span>
</a>
<ul class="dropdown-menu">
<li>
<form id="download_csv" data-download>
<input type="hidden" data-format value="csv">
<input type="hidden" data-path value="<?php echo $path ?>">
<input type="hidden" data-action value="graph/download">
<input type="hidden" name="ids">
<input type="hidden" name="start">
<input type="hidden" name="end">
<input type="hidden" name="headers">
<input type="hidden" name="timeformat">
<input type="hidden" name="interval">
<input type="hidden" name="nullvalues">
<button class="btn btn-link csvoptions">CSV</button>
</form>
</li>
<li>
<form id="download_json" data-download>
<input type="hidden" data-format value="json">
<input type="hidden" data-path value="<?php echo $path ?>">
<input type="hidden" data-action value="graph/download">
<input type="hidden" name="ids">
<input type="hidden" name="start">
<input type="hidden" name="end">
<input type="hidden" name="headers">
<input type="hidden" name="timeformat">
<input type="hidden" name="interval">
<input type="hidden" name="nullvalues">
<button class="btn btn-link csvoptions">JSON</button>
</form>
</li>
</ul>
</div>

<div class="input-append"><!-- just to match the styling of the other items -->
<button onclick="copyToClipboardCustomMsg(document.getElementById('csv'), 'copy-csv-feedback','Copied')" class="csvoptions btn hidden" id="copy-csv" type="button"><?php echo _('Copy') ?> <i class="icon-share-alt"></i></button>
</div>

<span id="copy-csv-feedback" class="csvoptions"></span>

<textarea id="csv" style="width:98%; height:500px; display:none; margin-top:10px"></textarea>
Expand Down