Updated upload form

This commit is contained in:
Samuel Ortion 2021-04-19 20:34:09 +02:00
parent ca1959a672
commit 7e2c6c122c
17 changed files with 840 additions and 194 deletions

View File

@ -3,9 +3,9 @@
-- https://www.phpmyadmin.net/
--
-- Host: localhost
-- Generation Time: Mar 30, 2021 at 01:11 PM
-- Server version: 10.5.9-MariaDB
-- PHP Version: 7.4.17RC1
-- Generation Time: Apr 19, 2021 at 01:52 PM
-- Server version: 10.3.27-MariaDB-0+deb10u1
-- PHP Version: 7.3.27-1~deb10u1
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
@ -37,6 +37,12 @@ CREATE TABLE `records` (
`species` varchar(125) NOT NULL,
`subspecies` varchar(125) NOT NULL,
`sound_type` varchar(25) NOT NULL,
`duration` varchar(5) NOT NULL,
`make` varchar(125) NOT NULL,
`model` varchar(125) NOT NULL,
`serial` varchar(125) NOT NULL,
`sample_rate` int(11) NOT NULL,
`time_expansion` int(11) NOT NULL,
`country` varchar(125) NOT NULL,
`lat` varchar(20) NOT NULL,
`lng` varchar(20) NOT NULL,
@ -49,8 +55,16 @@ CREATE TABLE `records` (
-- Dumping data for table `records`
--
INSERT INTO `records` (`id`, `entry_timestamp`, `author_id`, `recordist_name`, `file_name`, `license`, `species`, `subspecies`, `sound_type`, `country`, `lat`, `lng`, `date`, `time`, `remarks`) VALUES
(2, 20210330072954, 9, 'Samuel ORTION', 'PaRecAR628069_20200526_040726.wav', 'CC-by-nc-sa-4.0', 'Pipistrellus kuhlii', '', 'echolocation', 'France', '47.87840601525087', ' 0.21813243633005192', '2020-05-26', '04:07:00', '');
INSERT INTO `records` (`id`, `entry_timestamp`, `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
(2, 20210330072954, 9, 'Samuel ORTION', 'PaRecAR628069_20200526_040726.wav', 'CC-by-nc-sa-4.0', 'Pipistrellus kuhlii', '', 'echolocation', '', '', '', '', 0, 0, 'France', '47.87840601525087', ' 0.21813243633005192', '2020-05-26', '04:07:00', ''),
(7, 20210402110750, 9, 'Samuel ORTION', 'Ca721035-2021-Pass0-Z1-PaRecAR628069_20210401_205009_000.wav', 'CC-by-nc-sa-4.0', 'Pipistrellus kuhlii', '', 'echolocation', '', '', '', '', 0, 0, 'France', '47.87844315583611', ' 0.21815478801727298', '2021-04-01', '20:50:00', ''),
(8, 20210402112550, 9, 'Samuel ORTION', 'PaRecAR628069_20200526_040726.wav', 'CC-by-nc-sa-4.0', 'Pipistrellus kuhlii', '', 'echolocation,buzz', '', '', '', '', 0, 0, 'France', '47.878432361997255', ' 0.21816551685333252', '2021-04-01', '20:50:00', 'Capture buzz of *Pipistrellus kuhlii* recorded with an ActiveRecorder, using Fixed Point Vigie-Chiro Protocole.'),
(9, 20210402162625, 9, 'Samuel ORTION', 'Car910130-2021-Pass0-Z1-PaRecAR628069_20210330_211159_000.wav', 'CC-by-nc-sa-4.0', 'Pipistrellus pipistrellus', 'pipistrellus', 'echolocation,buzz', '', '', '', '', 0, 0, 'France', '47.878435959943786', ' 0.21813869476318362', '2021-04-01', '21:11:00', ''),
(10, 20210403183148, 9, 'Samuel ORTION', 'Ca721035-2021-Pass0-Z1-PaRecAR628069_20210402_220748_000.wav', 'CC-by-nc-sa-4.0', 'Myotis nattereri', '', 'echolocation', '', '', '', '', 0, 0, 'France', '47.8783855886695', ' 0.2181065082550049', '2021-04-02', '22:07:00', ''),
(11, 20210404093748, 9, 'Samuel ORTION', 'Ca721035-2021-Pass0-Z1-PaRecAR628069_20210402_220751_000.wav', 'CC-by-nc-sa-4.0', 'Myotis nattereri', '', 'echolocation', '', '', '', '', 0, 0, 'France', '47.87840357841592', ' 0.2181118726730347', '2021-04-02', '22:07:00', ''),
(12, 20210417120638, 9, 'Samuel ORTION', 'Car721035-2021-Pass0-Z2-PaRecAR628069_20210416_212007_000.wav', 'CC-by-nc-sa-4.0', 'Pipistrellus kuhlii', '', 'echolocation', '00:43', 'TeensyRecorder', '', 'AR628069', 384, 10, 'France', '47.87842501611575', ' 0.21816015243530276', '2021-12-04', '22:20:00', ''),
(13, 20210418084710, 9, 'Samuel ORTION', 'Car721035-2021-Pass0-Z2-PaRecAR628069_20210417_213223-noise-reducted.wav', 'CC-by-nc-sa-4.0', 'Pipistrellus kuhlii', '', 'echolocation,social-cry', '00:11', 'TeensyRecorder', '', 'AR628069', 384, 10, 'France', '47.8784430058485', ' 0.2181494235992432', '2021-04-17', '21:32:00', 'Premier enregistrement de cette pipistrelle à Saint-Gervais-en-Belin, identification à confirmer.'),
(14, 20210418091139, 9, 'Samuel ORTION', 'Car721035-2021-Pass0-Z2-PaRecAR628069_20210417_220248_000.wav', 'CC-by-nc-sa-4.0', 'Pipistrellus kuhlii', '', 'echolocation', '00:32', 'TeensyRecorder', '', 'AR628069', 384, 10, 'France', '47.8784322120096', ' 0.2181494235992432', '2021-04-17', '22:02:00', '');
--
-- Indexes for dumped tables
@ -70,7 +84,7 @@ ALTER TABLE `records`
-- AUTO_INCREMENT for table `records`
--
ALTER TABLE `records`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=15;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

View File

@ -67,9 +67,10 @@ include("$root/analytics/owa.php");
<td><em><?=$row['species']?></em></td>
<td>
<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" aria-hidden="true"></i></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>
<a href="/explore/record/edit/?id=<?=$row['id']?>" title="Edit record metadata"><i class="fa fa-edit " ></i></a>
</td>
<td><?=$username?></td>
<td><?=$row['license']?></td>

View File

@ -0,0 +1,84 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
session_reset();
$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['id'])){
?>
<!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>Edit | Chiro - Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<?php
include("$root/analytics/matomo.php");
include("$root/analytics/owa.php");
?>
<body>
<?php include("$root/menu.php");?>
<?php include("$root/header.php");?>
<section>
<h2>Edit</h2>
<?php
$req = $db->prepare('SELECT * FROM records WHERE id=:id');
$req->execute(array(
"id"=>$_GET['id']
));
if ($data = $req->fetch()){
?>
<form action="update.php" method="post">
<label for="file_name">File Name*</label>
<input type="text" id="file_name"value="<?=$data['file_name']?>" readonly>
<label for="coordinates">Coordinates*</label>
<input type="text" id="coordinates" value="<?=$data['lat']?>, <?=$data['lng']?>" readonly>
<label for="date">Date*</label>
<input type="date" name="date" id="date" value="<?=$data['date']?>">
<label for="time">Time*</label>
<input type="time" name="time" id="time" value="<?=$data['time']?>">
<label for="recordist-name">Recordist Name*</label>
<input type="text" name="recordist-name" id="recordist-name" value="<?=$data['recordist_name']?>" required>
<label for="species">Species*</label>
<input type="text" name="species" id="species" value="<?=$data['species']?>">
<label for="subpsecies">Subspecies</label>
<input type="text" name="subpseices" id="subspecies" value="<?=$data['subspecies']?>">
<label for="make">Recorder Manufacturer</label>
<input type="text" name="make" id="make" value="<?=$data['make']?>">
<label for="model">Recorder Model</label>
<input type="text" name="model" id="model" value="<?=$data['model']?>">
<label for="serial">Recorder Serial Number</label>
<input type="text" name="serial" id="serial" value="<?=$data['serial']?>">
</form>
<?php
} else {
$_SESSION['error_msg'] = "Can't fetch information on record with id '".$_GET['id']."'.";
}
echo $_SESSION['error_msg'];
?>
</section>
<?php include("$root/footer.php");?>
</body>
<script src="/scripts/script.js"></script>
</html>
<?php
}

View File

View File

@ -1,34 +0,0 @@
<link rel="import" href="./bower_components/polymer/polymer.html">
<link rel="import" href="./g-spectrogram-controls.html">
<link rel="import" href="./g-oscillator.html">
<link href='http://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>
<polymer-element name="g-spectrogram" attributes="controls log fftsize labels ticks oscillator speed color">
<template>
<style>
canvas {
position: absolute;
width: 100%;
height: 100%;
}
g-spectrogram-controls {
position: absolute;
}
</style>
<canvas id="canvas"></canvas>
<canvas id="labels"></canvas>
<template if="{{controls}}">
<g-spectrogram-controls
log="{{log}}"
labels="{{labels}}"
speed="{{speed}}"
ticks="{{ticks}}"
color="{{color}}">
</g-spectrogram-controls>
</template>
<template if="{{oscillator}}">
<g-oscillator log={{log}} speed={{speed}}></g-oscillator>
</template>
</template>
<script src="g-spectrogram.js"></script>
</polymer-element>

View File

@ -93,7 +93,7 @@ include("$root/analytics/matomo.php");
<script src="https://unpkg.com/wavesurfer.js/dist/plugin/wavesurfer.spectrogram.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/addons/p5.sound.js"></script>
<script src="scripts/g-spectro.js"></script>
<script src="scripts/spectro.js"></script>
<!-- <script src="scripts/piano.js"></script> -->
</html>

View File

@ -89,7 +89,7 @@ include("$root/analytics/matomo.php");
<!-- <script src="https://unpkg.com/wavesurfer.js/dist/plugin/wavesurfer.spectrogram.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/addons/p5.sound.js"></script> -->
<script src="scripts/spectro.js"></script>
<script src="scripts/script.js"></script>
<!-- <script src="scripts/piano.js"></script> -->
</html>

View File

@ -1,5 +1,6 @@
let analyser;
let context;
let source;
let fftsize = 2048;
let oscillator = true;
let log;
@ -21,7 +22,7 @@ let instantaneousFPS = 0;
let audio = document.getElementById('audio');
document.getElementById("launch-larynx").addEventListener('click', function () {
document.getElementById("launch-larynx").addEventListener('click', function() {
loadSound(audio.src)
startLarynx();
});
@ -29,9 +30,21 @@ document.getElementById("launch-larynx").addEventListener('click', function () {
function loadSound(url) {
let AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
context = new AudioContext();
let source = context.createMediaElementSource(audio);
request = new XMLHttpRequest();
request.open('GET', audio.src, true);
request.responseType = 'arraybuffer';
request.addEventListener('load', bufferSound, false);
request.send();
}
function bufferSound(event) {
request = event.target;
isource = context.createBufferSource();
isource.buffer = context.createBuffer(request.response, false);
source = isource;
}
function startLarynx() {
analyser = context.createAnalyser();
render();
@ -259,5 +272,4 @@ function labelsChanged() {
} else {
clearAxesLabels();
}
}
}

View File

@ -0,0 +1,155 @@
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Spectrum Example</title>
</head>
<body>
<audio id="audio-element"
src="/storage/records/E._serotinus_(presumée)-Sarthe-Juillet2020.wav"
controls="true"
style="width: 512px;">
</audio>
<div><canvas id="fft" width="512" height="200"></canvas></div>
<script>
var canvas = document.getElementById('fft'),
ctx = canvas.getContext('2d'),
channels,
rate,
frameBufferLength,
fft;
function loadedMetadata() {
channels = audio.mozChannels;
rate = audio.mozSampleRate;
frameBufferLength = audio.mozFrameBufferLength;
fft = new FFT(frameBufferLength / channels, rate);
}
function audioAvailable(event) {
var fb = event.frameBuffer,
t = event.time, /* unused, but it's there */
signal = new Float32Array(fb.length / channels),
magnitude;
for (var i = 0, fbl = frameBufferLength / 2; i < fbl; i++ ) {
// Assuming interlaced stereo channels,
// need to split and merge into a stero-mix mono signal
signal[i] = (fb[2*i] + fb[2*i+1]) / 2;
}
fft.forward(signal);
// Clear the canvas before drawing spectrum
ctx.clearRect(0,0, canvas.width, canvas.height);
for (var i = 0; i < fft.spectrum.length; i++ ) {
// multiply spectrum by a zoom value
magnitude = fft.spectrum[i] * 4000;
// Draw rectangle bars for each frequency bin
ctx.fillRect(i * 4, canvas.height, 3, -magnitude);
}
}
var audio = document.getElementById('audio-element');
audio.addEventListener('MozAudioAvailable', audioAvailable, false);
audio.addEventListener('loadedmetadata', loadedMetadata, false);
// FFT from dsp.js, see below
var FFT = function(bufferSize, sampleRate) {
this.bufferSize = bufferSize;
this.sampleRate = sampleRate;
this.spectrum = new Float32Array(bufferSize/2);
this.real = new Float32Array(bufferSize);
this.imag = new Float32Array(bufferSize);
this.reverseTable = new Uint32Array(bufferSize);
this.sinTable = new Float32Array(bufferSize);
this.cosTable = new Float32Array(bufferSize);
var limit = 1,
bit = bufferSize >> 1;
while ( limit < bufferSize ) {
for ( var i = 0; i < limit; i++ ) {
this.reverseTable[i + limit] = this.reverseTable[i] + bit;
}
limit = limit << 1;
bit = bit >> 1;
}
for ( var i = 0; i < bufferSize; i++ ) {
this.sinTable[i] = Math.sin(-Math.PI/i);
this.cosTable[i] = Math.cos(-Math.PI/i);
}
};
FFT.prototype.forward = function(buffer) {
var bufferSize = this.bufferSize,
cosTable = this.cosTable,
sinTable = this.sinTable,
reverseTable = this.reverseTable,
real = this.real,
imag = this.imag,
spectrum = this.spectrum;
if ( bufferSize !== buffer.length ) {
throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length;
}
for ( var i = 0; i < bufferSize; i++ ) {
real[i] = buffer[reverseTable[i]];
imag[i] = 0;
}
var halfSize = 1,
phaseShiftStepReal,
phaseShiftStepImag,
currentPhaseShiftReal,
currentPhaseShiftImag,
off,
tr,
ti,
tmpReal,
i;
while ( halfSize < bufferSize ) {
phaseShiftStepReal = cosTable[halfSize];
phaseShiftStepImag = sinTable[halfSize];
currentPhaseShiftReal = 1.0;
currentPhaseShiftImag = 0.0;
for ( var fftStep = 0; fftStep < halfSize; fftStep++ ) {
i = fftStep;
while ( i < bufferSize ) {
off = i + halfSize;
tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
real[off] = real[i] - tr;
imag[off] = imag[i] - ti;
real[i] += tr;
imag[i] += ti;
i += halfSize << 1;
}
tmpReal = currentPhaseShiftReal;
currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
}
halfSize = halfSize << 1;
}
i = bufferSize/2;
while(i--) {
spectrum[i] = 2 * Math.sqrt(real[i] * real[i] + imag[i] * imag[i]) / bufferSize;
}
};
</script>
</body>
</html>

View File

View File

@ -1,6 +1,6 @@
* {
align-self: baseline;
overflow: auto;
padding: 0;
margin: 0;
}
body {
@ -58,7 +58,7 @@ article {
}
article h1 {
font-size: 5em;
font-size: 5em
}
footer {
@ -79,7 +79,7 @@ footer img {
label {
width: 40em;
display: inline;
display: inline-block;
}
label span.info {
@ -87,43 +87,49 @@ label span.info {
}
label:hover span.info {
display: inline-block;
display: inline;
position: relative;
background: yellow;
padding: 0.5em;
border-radius: 5px;
}
input {
margin: 0.1em;
label {
float: left;
clear: none;
display: inline;
padding: 0px 1em 0px 8px;
}
/* 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],
input,
select,
textarea {
width: 100%;
/* width: fit-content; */
/* Full width */
padding: 12px;
margin: 0;
/* 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;
margin-bottom: 1em;
/* Bottom margin */
resize: vertical
/* Allow the user to vertically resize the textarea (not horizontally) */
;
}
input[type=radio],
input[type=checkbox] {
display: inline;
width: auto;
height: auto;
}
/* Style the submit button with a specific background color etc */
@ -134,6 +140,7 @@ input[type=submit] {
border: none;
border-radius: 4px;
cursor: pointer;
/* width: auto; */
}
input[type=reset] {
@ -143,6 +150,7 @@ input[type=reset] {
border: none;
border-radius: 4px;
cursor: pointer;
width: auto;
}
/* When moving the mouse over the submit button, add a darker green color */
@ -234,13 +242,13 @@ iframe html body {
padding-bottom: 0;
}
/* .container.row {
.container.row {
flex-direction: row;
}
.container.column {
flex-direction: column;
} */
}
h3,
p {
@ -387,10 +395,12 @@ table#replies td {
display: flex;
}
#larynx .settings input, #larynx .settings label {
#larynx .settings input,
#larynx .settings label {
width: auto;
padding: 0em 1em;
}
table {
max-width: 100vw;
}
@ -422,38 +432,45 @@ table img {
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;
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;
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;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 20%, 50%, 100% {
0%,
20%,
50%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
@ -468,76 +485,79 @@ article#guano {
.collapsible {
background-color: lightgrey;
color: black;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
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;
.collapsed,
.collapsible:hover {
background-color: grey;
}
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: #f1f1f1;
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;
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 (-) */
content: '\2796';
/* Unicode character for "minus" sign (-) */
}
.tooltip {
position: relative;
display: inline-block;
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;
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;
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;
visibility: visible;
opacity: 1;
}
/* The container <div> - needed to position the dropdown content */
@ -545,15 +565,16 @@ article#guano {
position: relative;
display: inline-block;
color: black;
padding: 0;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
background-color: #f2f2f2;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
display: none;
position: absolute;
background-color: #f2f2f2;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
}
.dropdown-content ul {
@ -561,29 +582,36 @@ article#guano {
flex-direction: column;
padding: 0;
}
/* Links inside the dropdown */
.dropdown-content li a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: #f1f1f1}
.dropdown-content a:hover {
background-color: #f1f1f1
}
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: flex;
position: fixed;
display: flex;
position: fixed;
}
/* Change the background color of the dropdown button when the dropdown content is shown */
.dropdown:hover .dropbtn {
background-color: #3e8e41;
background-color: #3e8e41;
}
.search img, .larynx img, .mystery img, .list img, .spectro img {
.search img,
.larynx img,
.mystery img,
.list img,
.spectro img {
max-height: 15vw
}
@ -594,32 +622,18 @@ article#guano {
grid-auto-rows: minmax(100px, auto);
}
.search {
}
.search {}
.larynx {
}
.larynx {}
.mystery {
}
.mystery {}
.list {
}
.list {}
.spectro {
}
.spectro {}
#map {
height: 50vh;
width: 50vw;
}
i, .fa {
i,
.fa {
height: 0.1em;
color: black;
}
@ -653,3 +667,81 @@ i, .fa {
background: red;
color: white;
}
section.observation {
height: 100%;
width: 100%;
display: flex;
position: absolute;
top: 20em;
left: 0;
width: auto;
flex-direction: row;
height: auto;
padding: 0;
margin: 0;
}
section .container {
padding: 0;
margin: 0;
}
section.observation {
max-width: 100%;
}
section.observation #map {
cursor: crosshair;
border-radius: 0;
width: 50vw;
height: 100% !important;
}
section.observation form .container.column {
display: flex;
flex-direction: column;
}
section.observation .container {
display: flex;
}
section.observation .metadata {
padding: 1em;
width: 47.5vw;
left: 0;
right: 0;
overflow: auto;
}
section.observation input,
section.observation select,
section.observation textarea,
section.observation label {
max-width: 80%;
}
section.observation .collapsible {
background-color: lightgrey;
width: 80%;
margin-bottom: 1em;
border-radius: 4px;
}
section.observation label {
width: auto;
display: block;
}
#map {
object-fit: contain;
}
#map img {
max-height: none;
}
.fa {
height: 1em;
}

View File

@ -24,9 +24,6 @@ $root = realpath($_SERVER["DOCUMENT_ROOT"]);
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload | Chiro - Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin=""/>
</head>
<?php
include("$root/analytics/owa.php");
@ -47,11 +44,14 @@ include("$root/analytics/matomo.php");
} else if ($_GET['step'] == 'verify') {
include("verify.php");
}
else if ($_GET['step'] == 'upload') {
include("upload.php");
}
else {
include("location.php");
}
} else {
include("location.php");
include("upload.php");
}
?>
</section>

View File

@ -1,4 +1,3 @@
let span = document.getElementById('latlng');
let coordinates = span.innerHTML;
@ -8,12 +7,9 @@ let latlng = L.LatLng(lat, lng);
var mymap = L.map('checkmap').setView([lat, lng], 13);
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: 'pk.eyJ1IjoidW5jbGVzYW11bHVzIiwiYSI6ImNrbXVmanF1bzEwd2Mybm82Nzlobm42bHAifQ.fKY7fUnY-MpzZUcseao0zg'
}).addTo(mymap);
let marker = L.marker([lat, lng], draggable=false).addTo(mymap);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
let marker = L.marker([lat, lng], draggable = false).addTo(mymap);

View File

@ -1,21 +1,16 @@
var mymap = L.map('map').setView([0, 0], 13).setZoom(1);
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: 'pk.eyJ1IjoidW5jbGVzYW11bHVzIiwiYSI6ImNrbXVmanF1bzEwd2Mybm82Nzlobm42bHAifQ.fKY7fUnY-MpzZUcseao0zg'
}).addTo(mymap);
var map = L.map('map').setView([51.505, -0.09], 13).setZoom(2);
var marker = L.marker([0, 0], draggable=true).addTo(mymap);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {
foo: 'bar',
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
}).addTo(map);
var marker = L.marker([0, 0], draggable = true).addTo(map);
var LatLng = marker.getLatLng();
let coordinates_input = document.getElementById('latlng');
function onMapClick(e) {
marker.setLatLng(e.latlng);
LatLng = marker.getLatLng();
@ -25,4 +20,4 @@ function onMapClick(e) {
coordinates_input.value = lat + ', ' + lng;
}
mymap.on('click', onMapClick);
map.on('click', onMapClick);

243
public/upload/submit.php Normal file
View File

@ -0,0 +1,243 @@
<?php
function db_entry() {
$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());
}
// /* Create Table if not exists */
// $sql = file_get_contents($root."/database/create_record.sql");
// $db->exec($sql);
$req = $db->prepare('SELECT id FROM `authors` WHERE username=:username');
$req->execute(array(
"username"=>$_SESSION['username']
));
if ($data = $req->fetch())
{
$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 {
$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(
"id"=>$id,
"recordist_name"=>$_SESSION['observation']['recordist-name'],
"file_name"=>$_SESSION['observation']['file'],
"license"=>$_SESSION['observation']['license'],
"species" => $_SESSION['observation']['species'],
"subspecies"=>$_SESSION['observation']['subspecies'],
"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'],
"lat"=>$_SESSION['observation']['lat'],
"lng"=>$_SESSION['observation']['lng'],
"date"=>$_SESSION['observation']['date'],
"time"=>$_SESSION['observation']['time'],
"remarks"=>$_SESSION['observation']['remarks']
));
} catch (Exception $e) {
die("Error : ".$e->getMessage());
}
$req = $db->prepare('SELECT LAST_INSERT_ID() AS id;');
$req->execute();
if ($data = $req->fetch()) {
header('Location: '."/explore/record/?id=".$data['id']);
} else {
header('Location: '."/");
}
}
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
$target_dir = $root."/storage/records/";
$fileName = $_FILES['file']['name'];
$target_file = $target_dir.basename($_FILES['file']['name']);
$uploadOk = 1;
$fileSize = $_FILES['file']['size'];
$temp = explode('.', $fileName);
$fileExtension = strtolower(end($temp));
$_SESSION['error_msg'] = "";
if (isset($_POST['submit']))
{
// /!\ Need to check if it is .wav.
$file_extension_allowed = ['wav'];
if (! in_array($fileExtension, $file_extension_allowed))
{
$_SESSION['error_msg'] .= "This file extension is not allowed; please upload a WAV file.\n";
}
if ($fileSize > 10*1024*1024)
{
$_SESSION['error_msg'] .= "The file size must be below 10MB. \n";
}
print_r($target_file);
if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file))
{
echo "The file ". htmlspecialchars(basename($_FILES['file']['name']))." has been uploaded.";
} else {
echo "Sorry, there was an error uploading your file";
}
$_SESSION['observation']['file'] = basename($_FILES['file']['name']);
if (isset($_POST['latlng'])) {
$latlng = $_POST['latlng'];
$_SESSION['observation']['latlng'] = $latlng;
$_SESSION['observation']['lat'] = explode(',', $latlng)[0];
$_SESSION['observation']['lng'] = explode(',', $latlng)[1];
} else {
$_SESSION['error_msg'] .= "Incorrect coordinates, please try again.";
}
if (isset($_POST['spchoice']))
{
if ($_POST['spchoice'] == "unknown") {
$_SESSION['observation']['species'] = "unknown";
$_SESSION['observation']['subspecies'] = "";
setcookie('species', $_SESSION['observation']['species'], time() + 86400 * 365.2, "/");
} else {
if (isset($_POST['species']))
{
$_SESSION['observation']['species'] = $_POST['species'];
setcookie('species', $_SESSION['observation']['species'], time() + 86400 * 365.2, "/");
} else
{
$_SESSION['error_msg'].= "Error, incorrect species name.\n";
}
if (isset($_POST['subspecies']))
{
$_SESSION['observation']['subspecies'] = $_POST['subspecies'];
setcookie('subspecies', $_SESSION['observation']['subspecies'], time() + 86400 * 365.2, "/");
} else
{
$_SESSION['observation']['subspecies'] = "";
}
}
}
if (isset($_POST['recording-license']))
{
$_SESSION['observation']['license'] = $_POST['recording-license'];
setcookie('license', $_SESSION['observation']['license'], time() + 86400 * 365.2, "/");
} else
{
$_SESSION['error_msg'] .= "Incorrect license\n";
}
if (isset($_POST['name']))
{
$_SESSION['observation']['recordist-name'] = $_POST['name'];
setcookie('name', $_SESSION['observation']['recordist-name'], time() + 86400 * 365.2, "/");
} else {
$_SESSION['error_msg'] .= "Incorrect Recordist Name.\n";
}
if (isset($_POST['loc-country']))
{
$_SESSION['observation']['country'] = $_POST['loc-country'];
} else
{
$_SESSION['error_msg'] .= "Incorrect Country. \n";
}
if (isset($_POST['recording-date']))
{
$_SESSION['observation']['date'] = $_POST['recording-date'];
} else
{
$_SESSION['error_msg'] .= "Incorrect date. \n";
}
if (isset($_POST['recording-time']))
{
$_SESSION['observation']['time'] = $_POST['recording-time'];
} else
{
$_SESSION['error_msg'] .= "Incorrect time. \n";
}
if (isset($_POST['sound-type-option']))
{
$_SESSION['observation']['type'] = $_POST['sound-type-option'];
} else
{
$_SESSION['error_msg'] .= "Incorrect sound type. \n";
}
if (isset($_POST['quality']))
{
$_SESSION['observation']['quality'] = $_POST['quality'];
} else
{
$_SESSION['error_msg'] .= "Incorrect quality value.\n";
}
if (isset($_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'];
}
} else {
$_SESSION['error_msg'] = "Form not submitted.\n";
}
if ($_SESSION['error_msg'] == "") {
db_entry();
} else {
header('Location: /upload');
}

88
public/upload/upload.php Normal file

File diff suppressed because one or more lines are too long