Initial chart commit

This commit is contained in:
ehpersonal38
2023-03-05 14:45:07 -05:00
parent eb9a6ea61d
commit 504942006b
4 changed files with 20975 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
<svg class="img-fluid" id="outputsvg" xmlns="http://www.w3.org/2000/svg" style="transform: matrix(1.3, 0, 0, 1.3, 0, 0); transform-origin: 50% 50%; cursor: move; transition: transform 200ms ease-in-out 0s;" width="120" height="120" viewBox="0 0 1200 1200"><g id="led6HDXxLpKB3rJBInqSAJ" fill="rgb(253,174,179)" style="transform: none; transform-origin: 50% 50%;"><g style="transform: none;"><path id="ppWkGCoaW" d="M143 1036 l-28 -24 -6 -169 -7 -168 52 -49 c28 -26 100 -90 159 -142 100 -87 111 -94 151 -94 39 0 50 6 127 74 72 64 86 72 101 62 9 -7 91 -78 182 -159 129 -115 171 -147 193 -147 l28 0 -5 396 -5 396 -28 24 -28 24 -429 0 -429 0 -28 -24z"></path></g></g><g id="l1PReg5IXY9KUxbReAvzebZ" fill="rgb(239,68,82)" style="transform: none; transform-origin: 50% 50%;"><g style="transform: none;"><path id="pRauFKI19" d="M100 649 l0 -73 48 -45 c137 -132 293 -261 314 -261 13 0 37 12 54 28 117 102 143 122 161 122 19 0 37 -15 241 -193 109 -94 139 -106 167 -64 8 13 13 35 11 48 -3 13 -5 27 -5 32 -1 4 -6 7 -11 7 -6 0 -84 65 -173 144 -210 187 -213 189 -240 182 -12 -3 -60 -40 -106 -81 -46 -41 -90 -75 -97 -75 -12 0 -87 62 -255 210 -119 106 -109 104 -109 19z"></path></g></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
var pluginTrendlineLinear={id:"trendlineLinear",afterDraw:function(a){var t,s;for(var e in a.scales)if("x"==e[0]?s=a.scales[e]:t=a.scales[e],s&&t)break;var n=a.chart.ctx;a.data.datasets.forEach(function(t,e){if(t.trendlineLinear&&a.isDatasetVisible(e)&&0!=t.data.length){var i=a.getDatasetMeta(e);addFitter(i,n,t,s,a.scales[i.yAxisID])}}),n.setLineDash([])}};function addFitter(t,e,i,a,s){var n=i.trendlineLinear.style||i.borderColor,r=i.trendlineLinear.width||i.borderWidth,o=i.trendlineLinear.lineStyle||"solid";n=void 0!==n?n:"rgba(169,169,169, .6)",r=void 0!==r?r:3;var l=new LineFitter,d=i.data.length-1,h=t.data[0]._model.x,u=t.data[d]._model.x,m=!1;i.data&&"object"==typeof i.data[0]&&(m=!0),i.data.forEach(function(t,e){if(null!=t)if("time"===a.options.type){var i=null!=t.x?t.x:t.t;l.add(new Date(i).getTime(),t.y)}else m?l.add(t.x,t.y):l.add(e,t)});var x=a.getPixelForValue(l.minx),c=a.getPixelForValue(l.maxx),f=s.getPixelForValue(l.f(l.minx)),g=s.getPixelForValue(l.f(l.maxx));m||(x=h,c=u);var p=t.controller.chart.chartArea.bottom,v=t.controller.chart.width;if(p<f){var X=f-p,L=f-g;f=p,x+=v*(X/L)}else if(p<g){X=g-p,L=g-f;g=p,c=v-(c-(v-v*(X/L)))}e.lineWidth=r,"dotted"===o&&e.setLineDash([2,3]),e.beginPath(),e.moveTo(x,f),e.lineTo(c,g),e.strokeStyle=n,e.stroke()}function LineFitter(){this.count=0,this.sumX=0,this.sumX2=0,this.sumXY=0,this.sumY=0,this.minx=1e100,this.maxx=-1e100}LineFitter.prototype={add:function(t,e){t=parseFloat(t),e=parseFloat(e),this.count++,this.sumX+=t,this.sumX2+=t*t,this.sumXY+=t*e,this.sumY+=e,t<this.minx&&(this.minx=t),t>this.maxx&&(this.maxx=t)},f:function(t){t=parseFloat(t);var e=this.count*this.sumX2-this.sumX*this.sumX;return(this.sumX2*this.sumY-this.sumX*this.sumXY)/e+t*((this.count*this.sumXY-this.sumX*this.sumY)/e)}},"undefined"!=typeof window&&window.Chart&&window.Chart.plugins.register(pluginTrendlineLinear);try{module.exports=exports=pluginTrendlineLinear}catch(t){}
+197
View File
@@ -80,6 +80,52 @@ $user = shell_exec("awk -F: '/1000/{print $1}' /etc/passwd");
$home = shell_exec("awk -F: '/1000/{print $6}' /etc/passwd");
$home = trim($home);
if(isset($_GET['comname'])) {
$birdName = $_GET['comname'];
$birdName = str_replace("_", " ", $birdName);
// Prepare a SQL statement to retrieve the detection data for the specified bird
$stmt = $db->prepare('SELECT Date, COUNT(*) AS Detections FROM detections WHERE Com_Name = :com_name AND Date BETWEEN DATE("now", "-30 days") AND DATE("now") GROUP BY Date');
// Bind the bird name parameter to the SQL statement
$stmt->bindValue(':com_name', $birdName);
// Execute the SQL statement and get the result set
$result = $stmt->execute();
// Fetch the result set as an associative array
$data = array();
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$data[$row['Date']] = $row['Detections'];
}
// Create an array of all dates in the last 14 days
$last14Days = array();
for ($i = 0; $i < 31; $i++) {
$last14Days[] = date('Y-m-d', strtotime("-$i days"));
}
// Merge the data array with the last14Days array
$data = array_merge(array_fill_keys($last14Days, 0), $data);
// Sort the data by date in ascending order
ksort($data);
// Convert the data to an array of objects
$data = array_map(function($date, $count) {
return array('date' => $date, 'count' => $count);
}, array_keys($data), $data);
// Close the database connection
$db->close();
// Return the data as JSON
echo json_encode($data);
die();
}
// from https://stackoverflow.com/questions/2690504/php-producing-relative-date-time-from-timestamps
function relativeTime($ts)
{
@@ -230,6 +276,7 @@ if(isset($_GET['ajax_detections']) && $_GET['ajax_detections'] == "true" ) {
<?php if(isset($_GET['display_limit']) && is_numeric($_GET['display_limit'])){ ?>
<tr class="relative" id="<?php echo $iterations; ?>">
<td class="relative"><a target="_blank" href="index.php?filename=<?php echo $todaytable['File_Name']; ?>"><img class="copyimage" title="Open in new tab" width=25 src="images/copy.png"></a>
<img class="copyimage" style="right:39px;cursor:pointer" title="View species stats" onclick="generateMiniGraph(this, '<?php echo $comname; ?>')" width=25 src="images/chart.svg">
<div class="centered_image_container">
<?php if(!empty($config["FLICKR_API_KEY"]) && strlen($image[2]) > 0) { ?>
@@ -327,6 +374,8 @@ die();
<button style="background-color: #9fe29b;padding:20px" onclick="hideDialog()">Close</button>
</dialog>
<script src="static/dialog-polyfill.js"></script>
<script src="static/Chart.bundle.js"></script>
<script src="static/chartjs-plugin-trendline.min.js"></script>
<script>
var dialog = document.querySelector('dialog');
dialogPolyfill.registerDialog(dialog);
@@ -497,3 +546,151 @@ window.addEventListener("load", function(){
});
</script>
<style>
.tooltip {
background-color: white;
border: 1px solid #ccc;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
padding: 10px;
transition: opacity 0.2s ease-in-out;
}
</style>
<script>
function generateMiniGraph(elem, comname) {
// Make an AJAX call to fetch the number of detections for the bird species
var xhr = new XMLHttpRequest();
xhr.open('GET', '/todays_detections.php?comname=' + comname);
xhr.onload = function() {
if (xhr.status === 200) {
var detections = JSON.parse(xhr.responseText);
console.log(detections)
// Create a div element for the chart window
var chartWindow = document.createElement('div');
chartWindow.className = "chartdiv"
chartWindow.style.position = 'fixed';
chartWindow.style.top = '0%';
chartWindow.style.left = '50%';
chartWindow.style.width = window.innerWidth < 700 ? '40%' : '20%';
chartWindow.style.height = window.innerWidth < 700 ? '25%' : '16%';
chartWindow.style.backgroundColor = '#fff';
chartWindow.style.zIndex = '9999';
chartWindow.style.overflow = 'auto';
chartWindow.style.borderRadius = '5px';
chartWindow.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)';
document.body.appendChild(chartWindow);
// Create a canvas element for the chart
var canvas = document.createElement('canvas');
canvas.width = chartWindow.offsetWidth;
canvas.height = chartWindow.offsetHeight;
chartWindow.appendChild(canvas);
// Create a new Chart.js chart
var ctx = canvas.getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: detections.map(item => item.date),
datasets: [{
label: 'Detections',
data: detections.map(item => item.count),
backgroundColor: '#9fe29b',
borderColor: '#77c487',
borderWidth: 1,
lineTension: 0.3, // Add smoothing to the line
pointRadius: 1, // Make the data points smaller
pointHitRadius: 10, // Increase the area around data points for mouse events
trendlineLinear: {
style: "rgba(55, 99, 64, 0.5)",
lineStyle: "solid",
width: 1.5
}
}]
},
options: {
layout: {
padding: {
right: 10
}
},
title: {
display: true,
text: 'Detections Over 30d'
},
legend: {
display: false
},
scales: {
xAxes: [{
display: false,
gridLines: {
display: false // Hide the gridlines on the x-axis
},
ticks: {
autoSkip: true,
maxTicksLimit: 2
}
}],
yAxes: [{
gridLines: {
display: false // Hide the gridlines on the y-axis
},
ticks: {
beginAtZero: true,
precision: 0,
stepSize: 1
}
}]
}
}
});
// Position the chart window to the left of the button
var buttonRect = elem.getBoundingClientRect();
var chartRect = chartWindow.getBoundingClientRect();
chartWindow.style.left = (buttonRect.left - chartRect.width - 10) + 'px';
// Calculate the top position of the chart to center it with the button
var buttonCenter = buttonRect.top + (buttonRect.height / 2);
var chartHeight = chartWindow.offsetHeight;
var chartTop = buttonCenter - (chartHeight / 2);
chartWindow.style.top = chartTop + 'px';
// Add a close button to the chart window
var closeButton = document.createElement('button');
closeButton.id = "chartcb";
closeButton.innerText = 'X';
closeButton.style.position = 'absolute';
closeButton.style.top = '5px';
closeButton.style.right = '5px';
closeButton.addEventListener('click', function() {
document.body.removeChild(chartWindow);
});
chartWindow.appendChild(closeButton);
}
};
xhr.send();
}
// TODO: add more margin to the right of the inside of the chart, add cursor icon to hover on the chart icon
// Listen for the scroll event on the window object
window.addEventListener('scroll', function() {
// Get all chart elements
var charts = document.querySelectorAll('.chartdiv');
// Loop through all chart elements and remove them
charts.forEach(function(chart) {
chart.parentNode.removeChild(chart);
});
});
</script>