diff --git a/homepage/images/check.svg b/homepage/images/check.svg
new file mode 100644
index 000000000..a12292f51
--- /dev/null
+++ b/homepage/images/check.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/homepage/static/generateMiniGraph.js b/homepage/static/generateMiniGraph.js
new file mode 100644
index 000000000..11ddd8ace
--- /dev/null
+++ b/homepage/static/generateMiniGraph.js
@@ -0,0 +1,116 @@
+function generateMiniGraph(elem, comname, days = 30) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', '/todays_detections.php?comname=' + encodeURIComponent(comname) + '&days=' + days);
+ xhr.onload = function() {
+ if (xhr.status === 200) {
+ var detections = JSON.parse(xhr.responseText);
+ if (typeof(window.chartWindow) !== 'undefined') {
+ document.body.removeChild(window.chartWindow);
+ window.chartWindow = undefined;
+ }
+ var chartWindow = document.createElement('div');
+ chartWindow.className = 'chartdiv';
+ document.body.appendChild(chartWindow);
+
+ var canvas = document.createElement('canvas');
+ canvas.width = chartWindow.offsetWidth;
+ canvas.height = chartWindow.offsetHeight - 40;
+ chartWindow.appendChild(canvas);
+
+ 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,
+ pointRadius: 1,
+ pointHitRadius: 10,
+ trendlineLinear: {
+ style: 'rgba(55, 99, 64, 0.5)',
+ lineStyle: 'solid',
+ width: 1.5
+ }
+ }]
+ },
+ options: {
+ layout: { padding: { right: 10 } },
+ title: { display: true, text: 'Detections Over ' + days + 'd' },
+ legend: { display: false },
+ scales: {
+ xAxes: [{
+ display: true,
+ gridLines: { display: true },
+ ticks: {
+ autoSkip: true,
+ maxTicksLimit: 6,
+ callback: value => value.substring(5)
+ }
+ }],
+ yAxes: [{
+ gridLines: { display: false },
+ ticks: { beginAtZero: true, precision: 0, maxTicksLimit: 5 }
+ }]
+ }
+ }
+ });
+
+ var buttonRect = elem.getBoundingClientRect();
+ var chartRect = chartWindow.getBoundingClientRect();
+ if (window.innerWidth < 700) {
+ chartWindow.style.left = 'calc(75% - ' + (chartRect.width / 2) + 'px)';
+ } else {
+ chartWindow.style.left = (buttonRect.right + 10) + 'px';
+ }
+
+ var buttonCenter = buttonRect.top + (buttonRect.height / 2);
+ var chartHeight = chartWindow.offsetHeight;
+ var chartTop = buttonCenter - (chartHeight / 2);
+ chartWindow.style.top = chartTop + 'px';
+
+ 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', () => {
+ document.body.removeChild(chartWindow);
+ window.chartWindow = undefined;
+ });
+ chartWindow.appendChild(closeButton);
+
+ var selector = document.createElement('select');
+ [30, 180, 360, 720, 1080].forEach(opt => {
+ var option = document.createElement('option');
+ option.value = opt;
+ option.text = opt + 'd';
+ if (opt === days) option.selected = true;
+ selector.appendChild(option);
+ });
+ selector.addEventListener('change', function() {
+ generateMiniGraph(elem, comname, parseInt(this.value));
+ });
+ selector.style.position = 'absolute';
+ selector.style.bottom = '5px';
+ selector.style.left = '5px';
+ chartWindow.appendChild(selector);
+
+ window.chartWindow = chartWindow;
+ }
+ };
+ xhr.send();
+}
+
+window.addEventListener('scroll', function() {
+ var charts = document.querySelectorAll('.chartdiv');
+ charts.forEach(chart => {
+ chart.parentNode.removeChild(chart);
+ window.chartWindow = undefined;
+ });
+});
diff --git a/homepage/views.php b/homepage/views.php
index a137c7854..501989eaf 100644
--- a/homepage/views.php
+++ b/homepage/views.php
@@ -173,6 +173,7 @@ function update_species_list($filename, $species, $add) {
+
";
}
@@ -203,6 +204,10 @@ function update_species_list($filename, $species, $add) {
$species_list="whitelist";
include('./scripts/species_list.php');
}
+ if($_GET['view'] == "Species Management"){
+ ensure_authenticated();
+ include('scripts/species_tools.php');
+ }
if($_GET['view'] == "File"){
echo "";
}
diff --git a/scripts/backup_data.sh b/scripts/backup_data.sh
index c001a982f..529196254 100755
--- a/scripts/backup_data.sh
+++ b/scripts/backup_data.sh
@@ -171,6 +171,7 @@ optional=("/home/$BIRDNET_USER/BirdNET-Pi/apprise.txt"
"/home/$BIRDNET_USER/BirdNET-Pi/scripts/blacklisted_images.txt"
"/home/$BIRDNET_USER/BirdNET-Pi/scripts/disk_check_exclude.txt"
"/home/$BIRDNET_USER/BirdNET-Pi/exclude_species_list.txt"
+"/home/$BIRDNET_USER/BirdNET-Pi/confirmed_species_list.txt"
"/home/$BIRDNET_USER/BirdNET-Pi/include_species_list.txt")
[ $ACTION == "backup" ] && backup_check
diff --git a/scripts/clear_all_data.sh b/scripts/clear_all_data.sh
index ee9d88d02..bed85a58e 100755
--- a/scripts/clear_all_data.sh
+++ b/scripts/clear_all_data.sh
@@ -23,6 +23,7 @@ echo "Re-creating necessary directories"
[ -d ${PROCESSED} ] || sudo -u ${USER} mkdir -p ${PROCESSED}
sudo -u ${USER} ln -fs $(dirname $my_dir)/exclude_species_list.txt $my_dir
+sudo -u ${USER} ln -fs $(dirname $my_dir)/confirmed_species_list.txt $my_dir
sudo -u ${USER} ln -fs $(dirname $my_dir)/include_species_list.txt $my_dir
sudo -u ${USER} ln -fs $(dirname $my_dir)/whitelist_species_list.txt $my_dir
sudo -u ${USER} ln -fs $(dirname $my_dir)/homepage/* ${EXTRACTED}
diff --git a/scripts/install_services.sh b/scripts/install_services.sh
index 38690a198..4ef3e1098 100755
--- a/scripts/install_services.sh
+++ b/scripts/install_services.sh
@@ -65,6 +65,7 @@ create_necessary_dirs() {
[ -L ${EXTRACTED}/spectrogram.png ] || sudo -u ${USER} ln -sf ${RECS_DIR}/StreamData/spectrogram.png ${EXTRACTED}/spectrogram.png
sudo -u ${USER} ln -fs $my_dir/exclude_species_list.txt $my_dir/scripts
+ sudo -u ${USER} ln -fs $my_dir/confirmed_species_list.txt $my_dir/scripts
sudo -u ${USER} ln -fs $my_dir/include_species_list.txt $my_dir/scripts
sudo -u ${USER} ln -fs $my_dir/whitelist_species_list.txt $my_dir/scripts
sudo -u ${USER} ln -fs $my_dir/homepage/* ${EXTRACTED}
diff --git a/scripts/overview.php b/scripts/overview.php
index 534809db4..8026acd6a 100644
--- a/scripts/overview.php
+++ b/scripts/overview.php
@@ -600,127 +600,8 @@ function startAutoRefresh() {
}
+
+
+
diff --git a/scripts/todays_detections.php b/scripts/todays_detections.php
index b2bedb39c..3f70a4322 100644
--- a/scripts/todays_detections.php
+++ b/scripts/todays_detections.php
@@ -550,126 +550,8 @@ function refreshTodayStats() {
+