Feat : change specie detected (#62)
* Add changedetection function * Create birdnet_changeidentification.sh * Add files via upload * Use a modal box for display of the species * Allow filtering on safari ios * Reset the dropdown if cancelled * Fix : click outside modal box to cancel it in safari ios * Switch modal style to style.css * Switch modal style to style.css * Improves modal rendition on small screens * Use ./scripts/labels.txt instead of hardcoded home * Added physical cancel button * ensure user pi executes the scripts https://github.com/Nachtzuster/BirdNET-Pi/pull/62 * Specify exec if not explicit https://github.com/Nachtzuster/BirdNET-Pi/pull/62 * Try another way to define the variables https://github.com/Nachtzuster/BirdNET-Pi/pull/62 * Align shebang with other scripts https://github.com/Nachtzuster/BirdNET-Pi/pull/62 * Allow different HOME https://github.com/Nachtzuster/BirdNET-Pi/pull/62 * Update birdnet_changeidentification.sh * Align way to call sudo -u $user with other birdnet-pi code https://github.com/Nachtzuster/BirdNET-Pi/pull/62 * Align with proposal https://github.com/Nachtzuster/BirdNET-Pi/pull/62 * Successfully converted message https://github.com/Nachtzuster/BirdNET-Pi/pull/62 * Align "safe" variables logic to helpers.py * Make birdnet_changeidentification.sh executable * Force confidence to 1.001 * Set confidence to 0 https://github.com/Nachtzuster/BirdNET-Pi/pull/62
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 341.874 341.874" xml:space="preserve">
|
||||||
|
<path d="M341.338,56.544c-0.865-1.748-2.654-2.834-4.669-2.834c-0.243,0-0.471,0.016-0.662,0.035l-13.201,0.573l10.858-10.302
|
||||||
|
l0.248-0.132l2.895-3.426l-1.536-3.02c-0.887-1.743-2.67-2.826-4.654-2.826c-0.489,0-0.928,0.066-1.289,0.15l-35.572,6.485
|
||||||
|
c-0.648-0.844-1.308-1.672-1.984-2.479c-12.529-14.959-29.409-22.865-48.814-22.865c-4.852,0-9.917,0.497-15.056,1.476
|
||||||
|
c-36.111,6.882-53.736,34.2-72.396,63.122c-24.924,38.632-50.697,78.579-124.683,78.579c-6.337,0-13.028-0.301-19.886-0.896
|
||||||
|
c-0.695-0.061-1.358-0.091-1.97-0.091c-3.851,0-6.544,1.251-8.006,3.717c-2.208,3.727-0.062,7.647,0.969,9.531l0.142,0.261
|
||||||
|
c13.907,25.674,34.957,47.705,60.9,63.712c23.211,14.321,49.99,23.099,76.99,25.806v52.677c0,6.747,5.517,12.171,12.265,12.171
|
||||||
|
h28.832c0.799,0,1.593-0.092,2.373-0.243c0.783,0.158,1.593,0.243,2.422,0.243h28.832c3.66,0,7.256-1.609,9.62-4.359
|
||||||
|
c2.116-2.461,3.024-5.496,2.556-8.58c-1.294-8.509-12.61-11.532-22.768-11.532c-2.314,0-6.642,0.184-11.032,1.307l3.213-44.469
|
||||||
|
c3.401-0.65,6.804-1.365,10.205-2.186c46.987-11.342,72.971-42.049,86.494-65.814c16.654-29.266,23.972-64.827,20.076-97.568
|
||||||
|
c-0.326-2.739-0.727-5.427-1.202-8.063l27.382-21.343c1.025-0.608,1.824-1.513,2.262-2.59
|
||||||
|
C342.051,59.4,341.991,57.852,341.338,56.544z M173.964,301.607c-1-0.067-2.282-0.101-3.326-0.101c-2.314,0-6.727,0.18-11.117,1.303
|
||||||
|
l3.079-40.844c3.728-0.08,7.365-0.271,11.365-0.568V301.607z M137.724,201.387c-15.404,10.814-31.967,11.775-41.318-4.436
|
||||||
|
c-10.372,3.407-21.528,2.202-26.284-7.327c-1.491-2.988,0.775-5.469,2.189-5.541c52.375-2.654,99.886-43.521,118.922-86.605
|
||||||
|
c1.398-3.165,5.691-3.562,6.524-0.52C212.89,152.204,194.946,219.858,137.724,201.387z M242.354,87.651
|
||||||
|
c-9.213,0-16.682-7.469-16.682-16.682s7.469-16.682,16.682-16.682c9.213,0,16.682,7.469,16.682,16.682
|
||||||
|
S251.567,87.651,242.354,87.651z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -139,6 +139,38 @@ button:hover {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background-color: #fefefe;
|
||||||
|
margin: 15% auto;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #888;
|
||||||
|
width: 80%;
|
||||||
|
text-align: center; /* Center the content */
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.modal-content {
|
||||||
|
width: 95%;
|
||||||
|
margin: 10% auto;
|
||||||
|
}
|
||||||
|
#labelDropdown {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.topnav {
|
.topnav {
|
||||||
background-color: rgb(159, 226, 155);
|
background-color: rgb(159, 226, 155);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Executable
+120
@@ -0,0 +1,120 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This scripts allows to change the identification of a Birdnet-pi detection
|
||||||
|
|
||||||
|
#################
|
||||||
|
# SET VARIABLES #
|
||||||
|
#################
|
||||||
|
|
||||||
|
# Define HOME in case environment is not correctly set
|
||||||
|
HOME="${HOME:-/home/pi}"
|
||||||
|
|
||||||
|
# shellcheck disable=sc1091
|
||||||
|
source /etc/birdnet/birdnet.conf &>/dev/null
|
||||||
|
|
||||||
|
# Get arguments
|
||||||
|
OLDNAME="$1" #OLDNAME="Mésange_charbonnière-78-2024-05-02-birdnet-RTSP_1-18:14:08.mp3"
|
||||||
|
NEWNAME="$2" #NEWNAME="Lapinus atricapilla_Lapinu à tête noire"
|
||||||
|
|
||||||
|
# Set log level
|
||||||
|
OUTPUT_TYPE="${3:-debug}" # Set 3rd argument to debug to have all outputs
|
||||||
|
|
||||||
|
# Ask for user input if no arguments
|
||||||
|
if [ -z "$OLDNAME" ]; then read -r -p 'OLDNAME (finishing by mp3): ' OLDNAME; fi
|
||||||
|
if [ -z "$NEWNAME" ]; then read -r -p 'NEWNAME (sciname_commoname): ' NEWNAME; fi
|
||||||
|
|
||||||
|
# Fixed values
|
||||||
|
LABELS_FILE="$HOME/BirdNET-Pi/model/labels.txt"
|
||||||
|
DB_FILE="$HOME/BirdNET-Pi/scripts/birds.db"
|
||||||
|
DETECTIONS_TABLE="detections"
|
||||||
|
|
||||||
|
###################
|
||||||
|
# VALIDITY CHECKS #
|
||||||
|
###################
|
||||||
|
|
||||||
|
# Check if files exist
|
||||||
|
if [ ! -f "$LABELS_FILE" ]; then echo "$LABELS_FILE doesn't exist, exiting" && exit 1; fi
|
||||||
|
if [ ! -f "$DB_FILE" ]; then echo "$DB_FILE doesn't exist, exiting" && exit 1; fi
|
||||||
|
|
||||||
|
# Check if inputs are valid
|
||||||
|
if [[ "$1" != *".mp3" ]]; then
|
||||||
|
echo "The first argument should be a filename starting with the common name of the bird and finishing by mp3!"
|
||||||
|
echo "Instead, it is : $1"
|
||||||
|
exit 1
|
||||||
|
elif [[ "$2" != *"_"* ]]; then
|
||||||
|
echo "The second argument should be in the format : \"scientific name_common name\""
|
||||||
|
echo "Instead, it is : $2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if $NEWNAME is found in the file $LABELS_FILE
|
||||||
|
if ! grep -q "$NEWNAME" "$LABELS_FILE"; then
|
||||||
|
echo "Error: $NEWNAME not found in $LABELS_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the common name as the same as the first
|
||||||
|
OLDNAME_space="${OLDNAME//_/ }"
|
||||||
|
if [[ "${OLDNAME_space%%-*}" == "${NEWNAME#*_}" ]]; then
|
||||||
|
echo "Error: $OLDNAME has the same common name as $NEWNAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
##################
|
||||||
|
# EXECUTE SCRIPT #
|
||||||
|
##################
|
||||||
|
|
||||||
|
# Intro
|
||||||
|
[[ "$OUTPUT_TYPE" == "debug" ]] && echo "Starting to modify $OLDNAME to $NEWNAME"
|
||||||
|
|
||||||
|
# Get the line where the column "File_Name" matches exactly $OLDNAME
|
||||||
|
IFS='|' read -r OLDNAME_sciname OLDNAME_comname OLDNAME_date < <(sqlite3 "$DB_FILE" "SELECT Sci_Name, Com_Name, Date FROM $DETECTIONS_TABLE WHERE File_Name = '$OLDNAME' LIMIT 1;")
|
||||||
|
|
||||||
|
if [[ -z "$OLDNAME_sciname" ]]; then
|
||||||
|
echo "Error: No line matching $OLDNAME in $DB_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract the part before the _ from $NEWNAME
|
||||||
|
NEWNAME_comname="${NEWNAME#*_}"
|
||||||
|
NEWNAME_sciname="${NEWNAME%%_*}"
|
||||||
|
|
||||||
|
# Replace spaces with underscores, and ' with "" (same logic as helpers.py)
|
||||||
|
NEWNAME_comname_safe="$(echo "$NEWNAME_comname" | tr -d "'" | tr ' ' '_')"
|
||||||
|
OLDNAME_comname_safe="$(echo "$OLDNAME_comname" | tr -d "'" | tr ' ' '_')"
|
||||||
|
|
||||||
|
# Replace OLDNAME_comname_safe with NEWNAME_comname_safe in OLDNAME
|
||||||
|
NEWNAME_filename="${OLDNAME//$OLDNAME_comname_safe/$NEWNAME_comname_safe}"
|
||||||
|
|
||||||
|
[[ "$OUTPUT_TYPE" == "debug" ]] && echo "This script will change the identification $OLDNAME from $OLDNAME_comname to ${NEWNAME#*_}"
|
||||||
|
|
||||||
|
########################
|
||||||
|
# EXECUTE : MOVE FILES #
|
||||||
|
########################
|
||||||
|
|
||||||
|
# Check if the file exists
|
||||||
|
FILE_PATH="$HOME/BirdSongs/Extracted/By_Date/$OLDNAME_date/$OLDNAME_comname_safe/$OLDNAME"
|
||||||
|
if [[ -f $FILE_PATH ]]; then
|
||||||
|
# Ensure the new directory exists
|
||||||
|
NEW_DIR="$HOME/BirdSongs/Extracted/By_Date/$OLDNAME_date/$NEWNAME_comname_safe"
|
||||||
|
mkdir -p "$NEW_DIR"
|
||||||
|
|
||||||
|
# Move and rename the file
|
||||||
|
mv "$FILE_PATH" "$NEW_DIR/$NEWNAME_filename"
|
||||||
|
mv "$FILE_PATH".png "$NEW_DIR/$NEWNAME_filename".png
|
||||||
|
|
||||||
|
[[ "$OUTPUT_TYPE" == "debug" ]] && echo "Files moved!"
|
||||||
|
else
|
||||||
|
echo "Error: File $FILE_PATH does not exist"
|
||||||
|
fi
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# EXECUTE : UPDATE DATABASE FILES #
|
||||||
|
###################################
|
||||||
|
|
||||||
|
# Update the database
|
||||||
|
sqlite3 "$DB_FILE" "UPDATE $DETECTIONS_TABLE SET Sci_Name = '$NEWNAME_sciname', Com_Name = '$NEWNAME_comname', Confidence = '0', File_Name = '$NEWNAME_filename' WHERE File_Name = '$OLDNAME';"
|
||||||
|
|
||||||
|
[[ "$OUTPUT_TYPE" == "debug" ]] && echo "Database entry removed"
|
||||||
|
|
||||||
|
[[ "$OUTPUT_TYPE" == "debug" ]] && echo "All done!"
|
||||||
+142
-2
@@ -9,6 +9,7 @@ ini_set('display_errors',1);
|
|||||||
require_once 'scripts/common.php';
|
require_once 'scripts/common.php';
|
||||||
$home = get_home();
|
$home = get_home();
|
||||||
$config = get_config();
|
$config = get_config();
|
||||||
|
$user = get_user();
|
||||||
|
|
||||||
$db = new SQLite3('./scripts/birds.db', SQLITE3_OPEN_READONLY);
|
$db = new SQLite3('./scripts/birds.db', SQLITE3_OPEN_READONLY);
|
||||||
$db->busyTimeout(1000);
|
$db->busyTimeout(1000);
|
||||||
@@ -67,6 +68,28 @@ if(isset($_GET['excludefile'])) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isset($_GET['getlabels'])) {
|
||||||
|
$labels = file('./scripts/labels.txt', FILE_IGNORE_NEW_LINES);
|
||||||
|
echo json_encode($labels);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($_GET['changefile']) && isset($_GET['newname'])) {
|
||||||
|
ensure_authenticated('You must be authenticated to delete files.');
|
||||||
|
if (preg_match('~^.*(\.\.\/).+$~', $_GET['changefile'])) {
|
||||||
|
echo "Error";
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
$oldname = basename(urldecode($_GET['changefile']));
|
||||||
|
$newname = urldecode($_GET['newname']);
|
||||||
|
if (!exec("sudo -u ".$user." ".$home."/BirdNET-Pi/scripts/birdnet_changeidentification.sh \"$oldname\" \"$newname\" log_errors 2>&1", $output)) {
|
||||||
|
echo "OK";
|
||||||
|
} else {
|
||||||
|
echo "Error : " . implode(", ", $output) . "<br>";
|
||||||
|
}
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
$shifted_path = $home."/BirdSongs/Extracted/By_Date/shifted/";
|
$shifted_path = $home."/BirdSongs/Extracted/By_Date/shifted/";
|
||||||
|
|
||||||
if(isset($_GET['shiftfile'])) {
|
if(isset($_GET['shiftfile'])) {
|
||||||
@@ -163,6 +186,7 @@ if (get_included_files()[0] === __FILE__) {
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function deleteDetection(filename,copylink=false) {
|
function deleteDetection(filename,copylink=false) {
|
||||||
if (confirm("Are you sure you want to delete this detection from the database?") == true) {
|
if (confirm("Are you sure you want to delete this detection from the database?") == true) {
|
||||||
const xhttp = new XMLHttpRequest();
|
const xhttp = new XMLHttpRequest();
|
||||||
@@ -253,6 +277,120 @@ function toggleShiftFreq(filename, shiftAction, elem) {
|
|||||||
xhttp.send();
|
xhttp.send();
|
||||||
elem.setAttribute("src","images/spinner.gif");
|
elem.setAttribute("src","images/spinner.gif");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeDetection(filename,copylink=false) {
|
||||||
|
const xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.onload = function() {
|
||||||
|
const labels = JSON.parse(this.responseText);
|
||||||
|
let dropdown = '<input type="text" id="filterInput" placeholder="Type to filter..."> <button id="cancelButton">Cancel</button> <br><select id="labelDropdown" size="5" style="display: block; margin: 0 auto;"></select>';
|
||||||
|
|
||||||
|
// Check if the modal already exists
|
||||||
|
let modal = document.getElementById('myModal');
|
||||||
|
if (!modal) {
|
||||||
|
// Create a modal box
|
||||||
|
modal = document.createElement('div');
|
||||||
|
modal.setAttribute('id', 'myModal');
|
||||||
|
modal.setAttribute('class', 'modal');
|
||||||
|
|
||||||
|
// Create a content box
|
||||||
|
let content = document.createElement('div');
|
||||||
|
content.setAttribute('class', 'modal-content');
|
||||||
|
|
||||||
|
// Add a title to the modal box
|
||||||
|
let title = document.createElement('h2');
|
||||||
|
title.textContent = 'Please select the correct specie here:';
|
||||||
|
content.appendChild(title);
|
||||||
|
|
||||||
|
// Add the dropdown to the content
|
||||||
|
let selectElement = document.createElement('div');
|
||||||
|
selectElement.innerHTML = dropdown;
|
||||||
|
content.appendChild(selectElement);
|
||||||
|
|
||||||
|
// Append the content to the modal
|
||||||
|
modal.appendChild(content);
|
||||||
|
|
||||||
|
// Append the modal to the body
|
||||||
|
document.body.appendChild(modal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the modal
|
||||||
|
modal.style.display = "block";
|
||||||
|
|
||||||
|
// Populate the dropdown list
|
||||||
|
let dropdownList = document.getElementById('labelDropdown');
|
||||||
|
labels.forEach(label => {
|
||||||
|
let option = document.createElement('option');
|
||||||
|
option.value = label;
|
||||||
|
option.text = label;
|
||||||
|
dropdownList.appendChild(option);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add an event listener to the modal box to hide it when clicked outside
|
||||||
|
document.addEventListener('click', function(event) {
|
||||||
|
if (event.target == modal) {
|
||||||
|
modal.style.display = "none";
|
||||||
|
dropdownList.selectedIndex = -1; // Reset the dropdown selection
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add an event listener to the input box to filter the dropdown list
|
||||||
|
document.getElementById('filterInput').addEventListener('keyup', function() {
|
||||||
|
let filter = this.value.toUpperCase();
|
||||||
|
let options = dropdownList.options;
|
||||||
|
// Clear the dropdown list
|
||||||
|
while (dropdownList.firstChild) {
|
||||||
|
dropdownList.removeChild(dropdownList.firstChild);
|
||||||
|
}
|
||||||
|
// Populate the dropdown list with the filtered labels
|
||||||
|
labels.forEach(label => {
|
||||||
|
if (label.toUpperCase().indexOf(filter) > -1) {
|
||||||
|
let option = document.createElement('option');
|
||||||
|
option.value = label;
|
||||||
|
option.text = label;
|
||||||
|
dropdownList.appendChild(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add an event listener to the cancel button to hide the modal box
|
||||||
|
document.getElementById('cancelButton').addEventListener('click', function() {
|
||||||
|
modal.style.display = "none";
|
||||||
|
dropdownList.selectedIndex = -1; // Reset the dropdown selection
|
||||||
|
});
|
||||||
|
|
||||||
|
dropdownList.addEventListener('change', function() {
|
||||||
|
const newname = this.value;
|
||||||
|
// Check if the default option is selected
|
||||||
|
if (newname === '') {
|
||||||
|
return; // Exit the function early
|
||||||
|
}
|
||||||
|
if (confirm("Are you sure you want to change the specie identified in this detection to " + newname + "?") == true) {
|
||||||
|
const xhttp2 = new XMLHttpRequest();
|
||||||
|
xhttp2.onload = function() {
|
||||||
|
if(this.responseText == "OK"){
|
||||||
|
if(copylink == true) {
|
||||||
|
alert("Successfully converted");
|
||||||
|
window.top.close();
|
||||||
|
} else {
|
||||||
|
alert("Successfully converted");
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert(this.responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhttp2.open("GET", "play.php?changefile="+filename+"&newname="+newname, true);
|
||||||
|
xhttp2.send();
|
||||||
|
}
|
||||||
|
// Hide the modal box and reset the dropdown selection
|
||||||
|
modal.style.display = "none";
|
||||||
|
this.selectedIndex = -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
xhttp.open("GET", "play.php?getlabels=true", true);
|
||||||
|
xhttp.send();
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
@@ -479,7 +617,8 @@ echo "<table>
|
|||||||
echo "<tr>
|
echo "<tr>
|
||||||
<td class=\"relative\">
|
<td class=\"relative\">
|
||||||
|
|
||||||
<img style='cursor:pointer;right:90px' src='images/delete.svg' onclick='deleteDetection(\"".$filename_formatted."\")' class=\"copyimage\" width=25 title='Delete Detection'>
|
<img style='cursor:pointer;right:120px' src='images/delete.svg' onclick='deleteDetection(\"".$filename_formatted."\")' class=\"copyimage\" width=25 title='Delete Detection'>
|
||||||
|
<img style='cursor:pointer;right:85px' src='images/bird.svg' onclick='changeDetection(\"".$filename_formatted."\")' class=\"copyimage\" width=25 title='Change Detection'>
|
||||||
<img style='cursor:pointer;right:45px' onclick='toggleLock(\"".$filename_formatted."\",\"".$type."\", this)' class=\"copyimage\" width=25 title=\"".$title."\" src=\"".$imageicon."\">
|
<img style='cursor:pointer;right:45px' onclick='toggleLock(\"".$filename_formatted."\",\"".$type."\", this)' class=\"copyimage\" width=25 title=\"".$title."\" src=\"".$imageicon."\">
|
||||||
<img style='cursor:pointer' onclick='toggleShiftFreq(\"".$filename_formatted."\",\"".$shiftAction."\", this)' class=\"copyimage\" width=25 title=\"".$shiftTitle."\" src=\"".$shiftImageIcon."\"> $date $time<br>$confidence<br>
|
<img style='cursor:pointer' onclick='toggleShiftFreq(\"".$filename_formatted."\",\"".$shiftAction."\", this)' class=\"copyimage\" width=25 title=\"".$shiftTitle."\" src=\"".$shiftImageIcon."\"> $date $time<br>$confidence<br>
|
||||||
|
|
||||||
@@ -553,7 +692,8 @@ echo "<table>
|
|||||||
echo "<tr>
|
echo "<tr>
|
||||||
<td class=\"relative\">
|
<td class=\"relative\">
|
||||||
|
|
||||||
<img style='cursor:pointer;right:90px' src='images/delete.svg' onclick='deleteDetection(\"".$filename_formatted."\", true)' class=\"copyimage\" width=25 title='Delete Detection'>
|
<img style='cursor:pointer;right:120px' src='images/delete.svg' onclick='deleteDetection(\"".$filename_formatted."\", true)' class=\"copyimage\" width=25 title='Delete Detection'>
|
||||||
|
<img style='cursor:pointer;right:85px' src='images/bird.svg' onclick='changeDetection(\"".$filename_formatted."\")' class=\"copyimage\" width=25 title='Change Detection'>
|
||||||
<img style='cursor:pointer;right:45px' onclick='toggleLock(\"".$filename_formatted."\",\"".$type."\", this)' class=\"copyimage\" width=25 title=\"".$title."\" src=\"".$imageicon."\">
|
<img style='cursor:pointer;right:45px' onclick='toggleLock(\"".$filename_formatted."\",\"".$type."\", this)' class=\"copyimage\" width=25 title=\"".$title."\" src=\"".$imageicon."\">
|
||||||
<img style='cursor:pointer' onclick='toggleShiftFreq(\"".$filename_formatted."\",\"".$shiftAction."\", this)' class=\"copyimage\" width=25 title=\"".$shiftTitle."\" src=\"".$shiftImageIcon."\">$date $time<br>$confidence<br>
|
<img style='cursor:pointer' onclick='toggleShiftFreq(\"".$filename_formatted."\",\"".$shiftAction."\", this)' class=\"copyimage\" width=25 title=\"".$shiftTitle."\" src=\"".$shiftImageIcon."\">$date $time<br>$confidence<br>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user