Added GUANO metadata

This commit is contained in:
Samuel Ortion 2021-04-09 14:29:00 +02:00
parent 341a3e4c73
commit 01c7ce508e
24 changed files with 1040 additions and 69 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
public/storage public/storage
node_modules
public/test

View File

@ -17,24 +17,25 @@ include("$root/analytics/matomo.php");
<?php include("$root/menu.php"); ?> <?php include("$root/menu.php"); ?>
<?php include("$root/header.php"); ?> <?php include("$root/header.php"); ?>
<section> <section>
<h2>Contact</h2>
<article> <article>
<form action="sendmail.php" method="post"> <form action="sendmail.php" method="post">
<label for="fname">First Name</label> <label for="fname">First Name*</label>
<input type="text" id="fname" name="firstname" placeholder="Your first name.." required><br> <input type="text" id="fname" name="firstname" placeholder="Your first name.." required><br>
<label for="lname">Last Name</label> <label for="lname">Last Name*</label>
<input type="text" id="lname" name="lastname" placeholder="Your last name.." required><br> <input type="text" id="lname" name="lastname" placeholder="Your last name.." required><br>
<label for="email">Email</label> <label for="email">Email*</label>
<input type="email" id="email" name="email" placeholder="Your email.." required><br> <input type="email" id="email" name="email" placeholder="Your email.." required><br>
<label for="website">Website</label> <label for="website">Website</label>
<input type="url" id="website" name="website" placeholder="Your website.."><br> <input type="url" id="website" name="website" placeholder="Your website.."><br>
<label for="subject">Subject</label> <label for="subject">Subject*</label>
<input type="text" id="subject" name="subject" placeholder="Your subject.." required><br> <input type="text" id="subject" name="subject" placeholder="Your subject.." required><br>
<label for="message">Message</label> <label for="message">Message*</label>
<textarea id="message" name="message" placeholder="Write something.." required style="height:200px"></textarea><br> <textarea id="message" name="message" placeholder="Write something.." required style="height:200px"></textarea><br>
<input type="submit" value="Submit"><input type="reset" value="Reset"> <input type="submit" value="Submit"><input type="reset" value="Reset">

View File

@ -76,6 +76,7 @@ try {
//$mail->isHTML(true); //Set email format to HTML //$mail->isHTML(true); //Set email format to HTML
$mail->Subject = $subject; $mail->Subject = $subject;
$mail->Body = $message; $mail->Body = $message;
$mail->Body .= "\nSended by $fname $lname <$email>\n";
// $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; // $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send(); $mail->send();

View File

@ -0,0 +1,73 @@
<?php
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
require "$root/database/credentials.php";
// Connect the database
try {
$db = new PDO("mysql:host=$host;dbname=$database;charset=utf8",
$user,
$password,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch (Exception $e) {
die("Error : ".$e->getMessage());
}
if (isset($_GET['record'])) {
$req = $db->prepare('SELECT * FROM records WHERE id=:id');
$req->execute(array(
"id"=>$_GET['record']
));
} else {
$req = $db->prepare('SELECT * FROM records ORDER BY date DESC LIMIT 1');
$req->execute();
}
if ($data = $req->fetch()) {
} else {
$_SESSION['error_msg'] = "Can't fetch data.";
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GUANO | Chiro-Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
</head>
<?php
include("$root/analytics/matomo.php");
?>
<body>
<?php include("$root/menu.php"); ?>
<?php include("$root/header.php"); ?>
<section>
<h2>GUANO v1.0</h2>
<?=isset($_SESSION['error_msg']) and $_SESSION['error_msg'] != "" ? '<div class="error">'.$_SESSION['error_msg'].'</div>' : "";?>
<a href="/articles">about GUANO</a>
<article id="guano">
GUANO|Version: 1.0<br><br>
Original Filename: <?=$data['file_name']?><br>
Timestamp: <?=$data['date']?> <?=$data['time']?><br>
Species Auto ID: None <br>
Species Manual ID: <em><?=$data['species']?> <?=$data['subspecies']?></em><br>
Tags: None <br>
Note: <?=(isset($data['remarks']) and $data['remarks'] != "") ? $data['remarks'] : "None"?><br>
TE: <?=(isset($data['time_expansion']) and $data['time_expansion'] != 0) ? $data['time_expansion'] : "Not defined"?><br>
Samplerate: <?=(isset($data['sample_rate']) and $data['sample_rate'] != 0) ? $data['sample_rate'] : "Not defined"?><br>
Length: <?=(isset($data['duration']) and $data['duration'] != "") ? $data['duration'] : "Not defined"?><br>
</article>
<button title="Copy to clipboard" onclick="clipboard_copy()">
<img src="/media/icons/copy.png" alt="clipboard copy">
</button>
</section>
<?php include("$root/footer.php"); ?>
</body>
<script src="/scripts/script.js"></script>
</html>

View File

@ -4,7 +4,6 @@ ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
session_start(); session_start();
$root = realpath($_SERVER["DOCUMENT_ROOT"]); $root = realpath($_SERVER["DOCUMENT_ROOT"]);
$version = "1.0";
require "$root/database/credentials.php"; require "$root/database/credentials.php";
// Connect the database // Connect the database
try { try {
@ -66,7 +65,8 @@ $result = $req->fetchAll();
<td> <td>
<a href="/explore/spectrograms/?record=<?=$row['id']?>"><?=$row['file_name']?></a> <a href="/explore/spectrograms/?record=<?=$row['id']?>"><?=$row['file_name']?></a>
<a href="/storage/records/<?=$row['file_name']?>" title="Download file"><i class="fa fa-download"></i></a> <a href="/storage/records/<?=$row['file_name']?>" title="Download file"><i class="fa fa-download"></i></a>
<a href="/larynx/?record=<?=$row['id']?>"><img src="/media/icons/wave.svg" alt="spectro analysis" title="Open with Larynx"></a> <a href="/larynx/?record=<?=$row['id']?>" title="Open with Larynx"><img src="/media/icons/wave.svg" alt="spectro analysis"></a>
<a href="/explore/guano?record=<?=$row['id']?>" title="See GUANO metadata"><img src="/media/icons/data.png" alt="database search"></a>
</td> </td>
<td><?=$username?></td> <td><?=$username?></td>
<td><?=$row['license']?></td> <td><?=$row['license']?></td>

View File

@ -0,0 +1,34 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
require "$root/database/credentials.php";
try {
$db = new PDO("mysql:host=$host;dbname=$database;charset=utf8",
$user,
$password,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch (Exception $e) {
die("Error : ".$e->getMessage());
}
$req = $db->prepare('SELECT * FROM images');
$req->execute();
$result = $req->fetchAll();
?>
<ul class="images">
<?php
foreach ($result as $row) {
?>
<li>
<div><img src="/storage/images/<?=$row['file_name']?>" alt="<?=$row['species']?>"></div>
</li>
<?php
}
?>
</ul>
<a href="?option=upload">Upload Image</a>
<script src="scripts/gallery.js"></script>
<?php

44
public/gallery/index.php Normal file
View File

@ -0,0 +1,44 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gallery | Chiro - Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
</head>
<?php
include("$root/analytics/matomo.php");
?>
<body>
<?php include("$root/menu.php");?>
<?php include("$root/header.php");?>
<section>
<h2>Gallery</h2>
<?=$_SESSION['error_msg']?>
<?=isset($_SESSION['error_msg']) and $_SESSION['error_msg'] != "" ? '<div class="error">'.$_SESSION['error_msg'].'</div>' : ""?>
<?php
$option = isset($_GET['option']) ? $_GET['option'] : "";
switch ($option) {
case 'upload':
include('upload.php');
break;
// case 'gallery':
// include('gallery.php');
// break;
default:
include('gallery.php');
}
?>
</section>
<?php include("$root/footer.php");?>
</body>
<script src="/scripts/script.js"></script>
</html>

View File

@ -0,0 +1,10 @@
images = document.getElementsByTagName('img');
for (img of images) {
img.addEventListener('click', function() {
if (img.classList.contains("fullscreen")) {
img.classList.remove('fullscreen');
} else {
img.classList.add('fullscreen');
}
});
}

74
public/gallery/upload.php Normal file
View File

@ -0,0 +1,74 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
function form() {
?>
<form action="upload.php" method="post" enctype="multipart/form-data">
<label for="file">Image*</label><br>
<input type="file" name="file" value="file" required><br>
<label for="species">Species</label>
<input type="text" name="species" id="species">
<input type="submit" name="submit" value="submit">
</form>
<?php
}
function db_entry($species, $filename) {
session_start();
global $root;
$location = $root."/storage/images/";
require "$root/database/credentials.php";
// Connect the database
try {
$db = new PDO("mysql:host=$host;dbname=$database;charset=utf8",
$user,
$password,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch (Exception $e) {
die("Error : ".$e->getMessage());
}
if (isset($_SESSION['username'])) {
$req = $db->prepare('SELECT id FROM authors WHERE username=:username');
$req->execute(array(
"username"=>$_SESSION['username']
));
if ($data = $req->fetch()) {
$author_id = $data['id'];
}
} else {
$_SESSION['error_msg'] .= "You need to be logged in to upload images.";
header("Location: /auth/login");
}
$req = $db->prepare('INSERT INTO images (species, file_name, author_id, entry_date) VALUES (:species, :file_name, :author_id, now())');
$req->execute(array(
"species"=>$species,
"file_name"=>$filename,
"author_id"=>$author_id
));
}
$_SESSION['error_msg'] = "";
if(isset($_POST['submit'])){
$location = $root."/storage/images/";
$name = $_FILES['file']['name'];
$temp_name = $_FILES['file']['tmp_name'];
if(isset($name) and !empty($name)){
$location = "$root/storage/images/";
if(move_uploaded_file($temp_name, $location.$name)){
echo 'File uploaded successfully';
db_entry(isset($_POST['species']) ? $_POST['species'] : "", $name);
header('Location: /gallery');
} else {
echo "Can't move your file.";
}
} else {
$_SESSION['error_msg'] .= 'You should select a file to upload !!';
}
} else {
form();
}
?>

View File

@ -46,6 +46,9 @@ include("$root/analytics/matomo.php");
<section> <section>
<h2>Larynx</h2> <h2>Larynx</h2>
<p>A web tool for bat sound analysis</p> <p>A web tool for bat sound analysis</p>
<a href="#larynx">
<div class="arrow bounce"></div>
</a>
</section> </section>
<div id="larynx"> <div id="larynx">
<h2>Larynx v<?=$version?></h2> <h2>Larynx v<?=$version?></h2>
@ -60,7 +63,7 @@ include("$root/analytics/matomo.php");
<div class="measures"> <div class="measures">
T: T:
<span id="cursor-time"></span> <span id="cursor-time"></span>
ms F: s F:
<span id="cursor-frequency"></span> <span id="cursor-frequency"></span>
kHz kHz
</div> </div>
@ -71,6 +74,10 @@ include("$root/analytics/matomo.php");
</div> </div>
</div> </div>
<p class="license"><?=$data['license']?> <?=$data['recordist_name']?></p> <p class="license"><?=$data['license']?> <?=$data['recordist_name']?></p>
<div class="settings">
<input type="checkbox" name="exp_x10" id="exp_x10">
<label for="exp_x10">exp x10</label>
</div>
</div> </div>
</div> </div>
<?php include("$root/footer.php");?> <?php include("$root/footer.php");?>

View File

@ -66,8 +66,12 @@ function measure(x, y) {
y = -(-(-y + spectro_y) - spectro_height); y = -(-(-y + spectro_y) - spectro_height);
let t = (x / spectro_width) * audio.duration; let t = (x / spectro_width) * audio.duration;
let f = (y / spectro_height) * 24; let f = (y / spectro_height) * 24;
document.getElementById('cursor-time').innerHTML = Math.round(t); let frequency_factor = 1;
document.getElementById('cursor-frequency').innerHTML = Math.round(f); if (document.getElementById('exp_x10').checked) {
frequency_factor = 10;
}
document.getElementById('cursor-time').innerHTML = Math.round(t / frequency_factor * 100) / 100;
document.getElementById('cursor-frequency').innerHTML = Math.round(f * frequency_factor * 100) / 100;
} }
let spectro = document.getElementById("wave-spectrogram"); let spectro = document.getElementById("wave-spectrogram");

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48"
height="48"
viewBox="0 0 12.7 12.7"
version="1.1"
id="svg8"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
sodipodi:docname="bottom_arrow.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="6.2964066"
inkscape:cx="2.1027989"
inkscape:cy="28.041802"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:window-width="1530"
inkscape:window-height="1011"
inkscape:window-x="50"
inkscape:window-y="32"
inkscape:window-maximized="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:#000000;stroke-width:1.96589;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 0.49104367,4.514826 6.3991297,11.112516 12.202494,4.4855177"
id="path833"
sodipodi:nodetypes="ccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/media/icons/copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
public/media/icons/data.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/media/icons/data.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -0,0 +1,464 @@
* {
align-self: baseline;
}
body {
margin: 0;
background-color: white;
}
header {
text-align: right;
padding: 0;
}
header a {
text-decoration: none;
color: black;
}
nav,
nav .container {
padding: 0;
margin: 0;
}
header .container,
nav .container {
display: flex;
justify-content: space-between;
}
header h1 {
font-size: 4em;
padding: 0;
margin: 0;
}
img.banner {
width: 100%;
height: auto;
}
section {
padding: 1em;
min-height: 100vh;
width: 50vw;
text-align: left;
margin: auto;
}
article {
width: 50vw;
text-align: left;
margin: auto;
}
article h1 {
font-size: 5em;
}
footer {
color: white;
text-align: center;
background-color: rgba(0, 0, 0, 0.9);
padding: 1em;
}
footer a {
text-decoration: none;
}
footer img {
height: 1em;
}
label {
width: 40em;
display: inline;
}
label span.info {
display: none;
}
label:hover span.info {
display: inline-block;
position: relative;
background: yellow;
padding: 0.5em;
border-radius: 5px;
}
input {
margin: 0.1em;
}
/* Style inputs with type="text", select elements and textareas */
input[type=text],
input[type=email],
input[type=url],
input[type=password],
input[type=number],
input[type=date],
input[type=time],
select,
textarea {
width: 100%;
/* Full width */
padding: 12px;
/* Some padding */
border: 1px solid #ccc;
/* Gray border */
border-radius: 4px;
/* Rounded borders */
box-sizing: border-box;
/* Make sure that padding and width stays in place */
margin-top: 6px;
/* Add a top margin */
margin-bottom: 16px;
/* Bottom margin */
resize: vertical
/* Allow the user to vertically resize the textarea (not horizontally) */
}
/* Style the submit button with a specific background color etc */
input[type=submit] {
background-color: #4CAF50;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type=reset] {
background-color: #af4c4c;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
/* When moving the mouse over the submit button, add a darker green color */
input[type=submit]:hover {
background-color: #45a049;
}
/* When moving the mouse over the reset button, add a darker red color */
input[type=reset]:hover {
background-color: #923737;
}
/* Add a background color and some padding around the form */
.container {
border-radius: 5px;
background-color: #f2f2f2;
padding: 1em;
}
nav {
border-bottom: 1px solid black;
position: flex;
display: block;
width: 100%;
background-color: white;
z-index: 10;
overflow: hidden;
overflow-wrap: break-word;
}
nav div {
padding: 1em;
}
nav.dark-theme {
background: black;
}
nav.dark-theme ul li {
color: white;
}
nav ul {
display: flex;
flex-direction: row;
}
nav ul a {
text-decoration: none;
}
nav ul li {
list-style: none;
color: black;
margin: 0.5em;
}
iframe::parent {
padding: 0;
margin: 0;
}
iframe {
width: 100%;
height: 750px;
}
#previewFrame {
width: 300px;
height: 200px;
resize: both;
zoom: 0.2;
-moz-transform: scale(0.5);
-moz-transform-origin: 0 0;
-o-transform: scale(0.5);
-o-transform-origin: 0 0;
-webkit-transform: scale(0.5);
-webkit-transform-origin: 0 0;
}
iframe html body {
font-size: 0.1em;
}
.container {
display: flex;
padding-top: 0;
padding-bottom: 0;
}
.container.row {
flex-direction: row;
}
.container.column {
flex-direction: column;
}
h3,
p {
padding: 1em;
width: auto;
}
p.large {
width: auto;
}
table {
border-radius: 5px;
width: 100%;
border-collapse: collapse;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 0.5em;
}
tr:nth-child(even) {
background-color: #dddddd;
}
table a {
text-decoration: none;
color: black;
}
table a:hover {
font-style: italic;
}
#searchbar {
display: flex;
flex-direction: row;
align-self: right;
}
ul.breadcrumb {
display: flex;
flex-basis: row;
}
ul.breadcrumb li {
list-style: url("/media/icons/arrow.svg");
margin-left: 2em;
}
ul.breadcrumb li.active {
font-weight: bold;
}
div.coordinates {
display: flex;
flex-direction: row;
}
div.coordinates input[type="text"] {
width: 25em;
}
.sci-name {
font-style: italic;
}
.error {
border: solid red;
border-radius: 5px;
padding: 0.5em;
background-color: rgba(255, 0, 0, 0.4)
}
.sound {
background-color: rgba(0, 255, 0, 0.5);
padding: 1em;
border-radius: 5px;
overflow: auto;
}
#spectrogram {
width: 100%;
max-width: 75vh;
}
button img {
max-height: 1em;
}
form#url-form {
display: none;
position: fixed;
top: 50%;
left: 35%;
width: 15em;
z-index: 1;
background-color: white;
padding: 1em;
border-radius: 5px;
border: 1px solid #ccc;
}
table#replies td {
background-color: white;
}
#larynx {
background-color: rgba(0, 0, 0, 0.8);
width: auto;
min-height: 100vh;
margin: 0;
color: white;
padding: 1em;
}
#larynx h2 {
text-align: center;
}
#larynx {
text-align: center;
}
#larynx .license {
text-align: left;
}
#larynx canvas {
width: 100vw;
position: relative;
left: 0;
}
#larynx .container {
background: transparent;
display: flex;
justify-content: space-between;
}
#larynx .settings {
display: flex;
}
#larynx .settings input, #larynx .settings label {
width: auto;
padding: 0em 1em;
}
table {
max-width: 100vw;
}
table#list {
position: absolute;
left: 0;
}
table img {
height: 1em;
}
.images img {
max-height: 10em;
}
.images li {
list-style: none;
}
.images .fullscreen {
display: block;
position: fixed;
/*top: 10%;*/
bottom: 0;
left: 50%;
max-width: 100vw;
max-height: 100vh;
transform: translate(-50%);
}
.images .fullscreen::parent {
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(9px);
position: fixed;
bottom: 0;
right: 0;
left: 0;
top: 0;
}
.arrow {
position: relative;
bottom: 0;
left: 50%;
margin-left:-20px;
width: 40px;
height: 40px;
background-image: url(/media/icons/bottom_arrow.svg);
background-size: contain;
}
.bounce {
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 20%, 50%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
article.guano {
font-family: "Sudo";
}

View File

@ -50,3 +50,30 @@ win.onscroll = function() {
// function hidePreview() { // function hidePreview() {
// iframe.style.display = "none"; // iframe.style.display = "none";
// } // }
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("collapsed");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
function clipboard_copy() {
/* Get the text field */
var copyText = document.getElementById("guano");
var r = document.createRange();
r.selectNode(copyText);
window.getSelection().removeAllRanges();
window.getSelection().addRange(r);
document.execCommand('copy');
window.getSelection().removeAllRanges();
}

View File

@ -167,6 +167,8 @@ nav {
width: 100%; width: 100%;
background-color: white; background-color: white;
z-index: 10; z-index: 10;
overflow: hidden;
overflow-wrap: break-word;
} }
nav div { nav div {
@ -381,6 +383,14 @@ table#replies td {
justify-content: space-between; justify-content: space-between;
} }
#larynx .settings {
display: flex;
}
#larynx .settings input, #larynx .settings label {
width: auto;
padding: 0em 1em;
}
table { table {
max-width: 100vw; max-width: 100vw;
} }
@ -393,3 +403,139 @@ table#list {
table img { table img {
height: 1em; height: 1em;
} }
.images img {
max-height: 10em;
}
.images li {
list-style: none;
}
.images .fullscreen {
display: block;
position: fixed;
/*top: 10%;*/
bottom: 0;
left: 50%;
max-width: 100vw;
max-height: 100vh;
transform: translate(-50%);
}
.images .fullscreen::parent {
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(9px);
position: fixed;
bottom: 0;
right: 0;
left: 0;
top: 0;
}
.arrow {
position: relative;
bottom: 0;
left: 50%;
margin-left:-20px;
width: 40px;
height: 40px;
background-image: url(/media/icons/bottom_arrow.svg);
background-size: contain;
}
.bounce {
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 20%, 50%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
article#guano {
font-family: "Consolas";
background-color: lightgray;
padding: 1em;
border-radius: 8px;
}
.collapsible {
background-color: lightgrey;
color: black;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.collapsed, .collapsible:hover {
background-color: grey;
}
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: #f1f1f1;
}
.collapsible:after {
content: '\02795'; /* Unicode character for "plus" sign (+) */
font-size: 13px;
color: #777;
float: right;
margin-left: 5px;
}
.collapsed:after {
content: "\2796"; /* Unicode character for "minus" sign (-) */
}
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 140px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 150%;
left: 50%;
margin-left: -75px;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}

View File

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload Image" name="submit">
</form>
</body>
</html>

View File

@ -1,33 +0,0 @@
<?php
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
$target_dir = $root."/storage/records";
echo $target_dir;
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
$MAXIMUM_FILESIZE = 10000 * 1024 * 1024;
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
if (is_uploaded_file($_FILES['fileToUpload']['tmp_name'])) {
$safe_filename = preg_replace(
array("/\s+/", "/[^-\.\w]+/"),
array("_", ""),
trim($_FILES['fileToUpload']['name']));
if ($_FILES['fileToUpload']['size'] <= $MAXIMUM_FILESIZE)
{
$isMove = move_uploaded_file (
_FILES['fileToUpload']['tmp_name'],
$dir_base.$safe_filename);
if ($isMove) {
echo "File moved";
} else {
echo "File not moved";
}
} else {
echo "Maximum file size exceeded";
}
}
}
?>

View File

@ -10,6 +10,7 @@
<input type="file" name="file" value="file" required><br> <input type="file" name="file" value="file" required><br>
<label for="spchoice">Species*</label><br> <label for="spchoice">Species*</label><br>
<input type="radio" name="spchoice" value="species" id="spchoice" checked> <input type="radio" name="spchoice" value="species" id="spchoice" checked>
<label for="spchoice">Species identified</label>
<input type="text" name="species" value="<?=isset($_COOKIE['species']) ? $_COOKIE['species'] : "" ?>" id="species" placeholder="Enter a species.."> <input type="text" name="species" value="<?=isset($_COOKIE['species']) ? $_COOKIE['species'] : "" ?>" id="species" placeholder="Enter a species..">
<br> <br>
<span id="hint"></span> <span id="hint"></span>
@ -52,6 +53,21 @@
<label for="remarks">Remarks</label> <label for="remarks">Remarks</label>
<textarea id="remarks" name="remarks"></textarea><br> <textarea id="remarks" name="remarks"></textarea><br>
<button type="button" class="collapsible">Optional Entries</button>
<div class="content">
<label for="make">Recorder manufacturer</label>
<input type="text" name="make" id="make">
<label for="model">Recorder model</label>
<input type="text" name="model" id="model">
<label for="serial">Recorder Serial Number</label>
<input type="text" name="serial" id="serial">
<label for="sample_rate">Samplerate (kHz)</label>
<input type="number" name="sample_rate" id="sample_rate" value="384">
<label for="time_expansion">Time Expansion Factor</label>
<input type="number" name="time_expansion" id="time_expansion" value="10">
</div>
<input type="submit" name="submit" value="submit"> <input type="submit" name="submit" value="submit">
</form> </form>
<script src="scripts/ajax_species_suggestion.js"></script> <script src="scripts/ajax_species_suggestion.js"></script>

View File

@ -73,7 +73,7 @@ if (isset($_POST['submit']))
if (isset($_POST['name'])) if (isset($_POST['name']))
{ {
$_SESSION['observation']['recordist-name'] = $_POST['name']; $_SESSION['observation']['recordist-name'] = $_POST['name'];
setcookie('name', $_SESSION['observation']['name'], time() + 86400 * 365.2, "/"); setcookie('name', $_SESSION['observation']['recordist-name'], time() + 86400 * 365.2, "/");
} else { } else {
$_SESSION['error_msg'] .= "Incorrect Recordist Name.\n"; $_SESSION['error_msg'] .= "Incorrect Recordist Name.\n";
} }
@ -116,6 +116,27 @@ if (isset($_POST['submit']))
{ {
$_SESSION['observation']['remarks'] = $_POST['remarks']; $_SESSION['observation']['remarks'] = $_POST['remarks'];
} }
/* Optional entries */
if (isset($_POST['make']))
{
$_SESSION['observation']['make'] = $_POST['make'];
}
if (isset($_POST['model']))
{
$_SESSION['observation']['model'] = $_POST['model'];
}
if (isset($_POST['serial']))
{
$_SESSION['observation']['serial'] = $_POST['serial'];
}
if (isset($_POST['sample_rate']))
{
$_SESSION['observation']['sample_rate'] = $_POST['sample_rate'];
}
if (isset($_POST['time_expansion']))
{
$_SESSION['observation']['time_expansion'] = $_POST['time_expansion'];
}
} }

View File

@ -30,8 +30,34 @@ if ($data = $req->fetch())
{ {
$id = $data['id']; $id = $data['id'];
} }
/** Retrieve .wav duration*/
$filepath = "$root/storage/records/".$_SESSION['observation']['file'];
function wavDur($file) {
$fp = fopen($file, 'r');
if (fread($fp,4) == "RIFF") {
fseek($fp, 20);
$rawheader = fread($fp, 16);
$header = unpack('vtype/vchannels/Vsamplerate/Vbytespersec/valignment/vbits',$rawheader);
$pos = ftell($fp);
while (fread($fp,4) != "data" && !feof($fp)) {
$pos++;
fseek($fp,$pos);
}
$rawheader = fread($fp, 4);
$data = unpack('Vdatasize',$rawheader);
$sec = $data['datasize']/$header['bytespersec'];
$minutes = intval(($sec / 60) % 60);
$seconds = intval($sec % 60);
return str_pad($minutes,2,"0", STR_PAD_LEFT).":".str_pad($seconds,2,"0", STR_PAD_LEFT);
}
}
$t = wavDur($filepath);
print_r($t);
try { try {
$req = $db->prepare('INSERT INTO `records` (author_id, recordist_name, file_name, license, species, subspecies, sound_type, country, lat, lng, date, time, remarks) VALUES ( :id, :recordist_name, :file_name, :license, :species, :subspecies, :sound_type, :country, :lat, :lng, :date, :time, :remarks)'); $req = $db->prepare('INSERT INTO `records` (author_id, recordist_name, file_name, license, species, subspecies, sound_type, duration, make, model, serial, sample_rate, time_expansion, country, lat, lng, date, time, remarks) VALUES ( :id, :recordist_name, :file_name, :license, :species, :subspecies, :sound_type, :duration, :make, :model, :serial, :sample_rate, :time_expansion, :country, :lat, :lng, :date, :time, :remarks)');
$req->execute(array( $req->execute(array(
"id"=>$id, "id"=>$id,
"recordist_name"=>$_SESSION['observation']['recordist-name'], "recordist_name"=>$_SESSION['observation']['recordist-name'],
@ -40,12 +66,18 @@ try {
"species" => $_SESSION['observation']['species'], "species" => $_SESSION['observation']['species'],
"subspecies"=>$_SESSION['observation']['subspecies'], "subspecies"=>$_SESSION['observation']['subspecies'],
"sound_type"=>implode(',', $_SESSION['observation']['type']), "sound_type"=>implode(',', $_SESSION['observation']['type']),
"duration"=>$t,
"make"=>isset($_SESSION['observation']['make']) ? $_SESSION['observation']['make'] : "",
"model"=>isset($_SESSION['osbservation']['model']) ? $_SESSION['osbservation']['model'] : "",
"serial"=>isset($_SESSION['observation']['serial']) ? $_SESSION['observation']['serial'] : "",
"sample_rate"=>isset($_SESSION['observation']['sample_rate']) ? $_SESSION['observation']['sample_rate'] : 384,
"time_expansion"=>isset($_SESSION['observation']['time_expansion']) ? $_SESSION['observation']['time_expansion'] : 10,
"country"=>$_SESSION['observation']['country'], "country"=>$_SESSION['observation']['country'],
"lat"=>$_SESSION['observation']['lat'], "lat"=>$_SESSION['observation']['lat'],
"lng"=>$_SESSION['observation']['lng'], "lng"=>$_SESSION['observation']['lng'],
"date"=>$_SESSION['observation']['date'], "date"=>$_SESSION['observation']['date'],
"time"=>$_SESSION['observation']['time'], "time"=>$_SESSION['observation']['time'],
"remarks"=>$_SESSION['observation']['remarks'], "remarks"=>$_SESSION['observation']['remarks']
)); ));
} catch (Exception $e) { } catch (Exception $e) {
die("Error : ".$e->getMessage()); die("Error : ".$e->getMessage());

View File

@ -66,7 +66,7 @@
</script> </script>
<form action="submitobservation.php" method="post"> <form action="submitobservation.php" method="post">
<input type="checkbox" id="allok" name="allok"> <input type="checkbox" id="allok" name="allok" required>
<label for="allok">All informations are ok.</label><br> <label for="allok">All informations are ok.</label><br>
<input type="submit" name="submit" value="submit"> <input type="submit" name="submit" value="submit">
</form> </form>