Welcome to BirdNET-stream !
- {% endblock %} -diff --git a/www/assets/app.js b/www/assets/app.js index 1d730eb..7ccbda1 100644 --- a/www/assets/app.js +++ b/www/assets/app.js @@ -7,6 +7,7 @@ // any CSS you import will output into a single css file (app.css in this case) import './styles/app.css'; +import './styles/menu.css'; // start the Stimulus application import './bootstrap'; diff --git a/www/assets/styles/app.css b/www/assets/styles/app.css index ae862dc..f0d573e 100644 --- a/www/assets/styles/app.css +++ b/www/assets/styles/app.css @@ -2,15 +2,39 @@ box-sizing: border-box; } +.container { + display: flex; + flex-direction: column; + position: relative; +} + +.column { + flex-direction: column; +} + +.row { + flex-direction: row; +} + +.behind { + position: relative; + z-index: -1; +} + +.above { + position: relative; + z-index: 1; +} + body { background-color: lightgray; margin: 0; padding: 0; + z-index: -10; } header { padding: 1em; - text-align: center; display: flex; flex-direction: row; /** Align text and center of image */ @@ -18,7 +42,7 @@ header { align-items: baseline; } -header img#logo { +header img.logo { width: 100px; height: 100px; } @@ -26,6 +50,7 @@ header img#logo { main { min-height: 100vh; padding: 5em; + z-index: 0; } footer { @@ -44,33 +69,7 @@ footer a:hover { font-style: italic; } -nav ul { - list-style-type: none; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - - background-color: #333; - margin: auto; - min-width: 100vw; -} - -nav ul li a, -.dropdown-button { - color: white; - text-decoration: none; - display: block; - padding: 1em 0.5em; -} - -nav ul li a.active, -nav ul li a:hover { - background-color: #999; - color: #101010 -} - -.dropdown-button:hover { +/* .dropdown-button:hover { background-color: #900; color: white } @@ -78,6 +77,7 @@ nav ul li a:hover { .dropdown:hover .dropdown-content { display: block; } +*/ .dropdown-content { display: none; @@ -95,4 +95,56 @@ canvas { .scientific-name { font-style: italic; +} + +.dataviz img { + max-width: 100%; + width: 100%; +} + +#statuses { + display: flex; + flex-direction: column; +} + +#statuses li { + list-style: none; + display: flex; + flex-direction: row; + justify-content: space-between; + +} + +.status .bullet { + border-radius: 50%; + background-color: #999; + width: 1em; + height: 1em; + display: inline-block; + position: relative; + top: 0.15em; + margin-right: 0.5em; + margin-left: 0.5em; +} + +.status.active .bullet { + background-color: #090; +} + +.status.inactive .bullet { + background-color: #900; +} + + +@media screen and (max-width: 700px) { + main { + padding: 1em; + } +} + +.overlay { + z-index: 10; + opacity: 100%; + background-color: rgba(255, 255, 255, 1); + position: relative; } \ No newline at end of file diff --git a/www/assets/styles/menu.css b/www/assets/styles/menu.css new file mode 100644 index 0000000..78fcba2 --- /dev/null +++ b/www/assets/styles/menu.css @@ -0,0 +1,129 @@ +nav { + position: fixed; + top: 0; + left: 0; + --nav-width: 20em; +} + +.toggler{ + z-index:2; + height: 50px; + width: 50px; + position: absolute; + cursor: pointer; + opacity: 0; +} + +.hamburger{ + position: absolute; + top: 0; + left: 0; + height: 40px; + width: 40px; + padding: 0.6rem; + display: flex; + align-items: center; + justify-content: center; + z-index: 1; +} + +.hamburger > div{ + position: relative; + top: 0; + left: 0; + background: black; + height: 2px; + width: 75%; + transition: all 0.4s ease; + color: #000; + +} + +.hamburger > div::before, +.hamburger > div::after{ + content: ''; + position: absolute; + top: -7px; + background: black; + width: 100%; + height: 2px; + transition: all 0.4s ease; +} + +.hamburger > div::after{ + top: 7px; +} + +.toggler:checked + .hamburger > div{ + background: rgba(0,0,0,0); +} + +.toggler:checked + .hamburger > div::before{ + top: 0; + transform: rotate(45deg); + background: black; +} + +.toggler:checked + .hamburger > div::after{ + top: 0; + transform: rotate(135deg); + background: black; +} + +.menu{ + height: 100vh; + width: 0; + visibility: hidden; +} + +.toggler:checked ~ .menu{ + width: fit-content; + height: fit-content; + background-color: rgba(255, 255, 255, 1)!important; +} + +.menu > ul{ + display: flex; + flex-direction: column; + position: fixed; + width: 0; + height: 100vmax; + padding-left: 1em; + padding-right: 1em; + margin-top: 2em; + visibility: hidden; + background-color: white; + z-index: 1; +} + +.menu > ul > li{ + list-style: none; + padding: 0.5rem; +} + +.menu > ul > li > a{ + color: black; + text-decoration: none; + font-size: 2rem; +} + +.toggler:checked ~ .fill { + background: white; + position: absolute; + top: 0; + left: 0; + height: 100vh; + width: var(--nav-width); +} + +.toggler:checked ~ .menu > ul{ + width: 20em; + transition: fit-content .5s ease; + opacity: 1; + transition: opacity .5s, visibility .5s, height .5s, width .5s; + visibility: visible; +} + +.toggler:checked ~ .menu > ul > li > a:hover{ + color: orange; +} \ No newline at end of file diff --git a/www/src/Controller/AboutController.php b/www/src/Controller/AboutController.php deleted file mode 100644 index 3bb9104..0000000 --- a/www/src/Controller/AboutController.php +++ /dev/null @@ -1,21 +0,0 @@ -render('about/index.html.twig', [ - - ]); - } -} \ No newline at end of file diff --git a/www/src/Controller/AuthController.php b/www/src/Controller/AuthController.php new file mode 100644 index 0000000..bdc8d4e --- /dev/null +++ b/www/src/Controller/AuthController.php @@ -0,0 +1,31 @@ +redirectToRoute("login"); + } + + /** + * @Route("/auth/login", name="login") + */ + public function login() + { + return $this->render('auth/login.html.twig', [ + + ]); + } +} \ No newline at end of file diff --git a/www/src/Controller/HomeController.php b/www/src/Controller/HomeController.php index ef0fbf1..150ad72 100644 --- a/www/src/Controller/HomeController.php +++ b/www/src/Controller/HomeController.php @@ -1,21 +1,78 @@ connection = $connection; return $this->render('index.html.twig', [ - + "stats" => $this->get_stats(), + "charts" => $this->last_chart_generated(), ]); } + + /** + * @Route("/about", name="about") + */ + public function about() + { + return $this->render('about/index.html.twig', [ + + ]); + } + + private function get_stats() + { + $stats = array(); + $stats["most-recorded-species"] = $this->get_most_recorded_species(); + $stats["last-detected-species"] = $this->get_last_recorded_species(); + return $stats; + } + + private function get_most_recorded_species() + { + $sql = "SELECT `scientific_name`, `common_name`, COUNT(*) AS contact_count + FROM `taxon` + INNER JOIN `observation` + ON `taxon`.`taxon_id` = `observation`.`taxon_id` + ORDER BY `contact_count` DESC LIMIT 1"; + $stmt = $this->connection->prepare($sql); + $result = $stmt->executeQuery(); + return $result->fetchAllAssociative()[0]; + } + + private function get_last_recorded_species() + { + $sql = "SELECT `scientific_name`, `common_name`, `date`, `audio_file`, `confidence` + FROM `observation` + INNER JOIN `taxon` + ON `observation`.`taxon_id` = `taxon`.`taxon_id` + ORDER BY `date` DESC LIMIT 1"; + $stmt = $this->connection->prepare($sql); + $result = $stmt->executeQuery(); + return $result->fetchAllAssociative()[0]; + } + + private function last_chart_generated() { + + $files = glob($this->getParameter('kernel.project_dir') . '/../var/charts/*.png'); + usort($files, function($a, $b) { + return filemtime($b) - filemtime($a); + }); + $last_chart = basename(array_pop($files)); + return $last_chart; + } + } \ No newline at end of file diff --git a/www/src/Controller/ServicesController.php b/www/src/Controller/ServicesController.php new file mode 100644 index 0000000..b404388 --- /dev/null +++ b/www/src/Controller/ServicesController.php @@ -0,0 +1,73 @@ + $service, + "status" => $this->systemd_service_status($service) + ); + }, $this->services_available); + return $this->render('services/status.html.twig', [ + 'status' => $status + ]); + } + + /** + * @Route("/service/manage/{action}", name="service_manager") + */ + public function service_manage($action, $service) + { + $error = ""; + if (in_array($action, $this->allowed_actions)) { + if (in_array($service, $this->services_available)) { + if(($output = $this->manage_systemd_service($action, $service)) != "true") { + $error = "Error while managing service"; + dump($output); + } + } else { + $error .= "Service not found"; + } + } else { + $error .= "Action not allowed"; + } + if ($error != "") { + return new Response($error, Response::HTTP_BAD_REQUEST); + } else { + return new Response("OK", Response::HTTP_OK); + } + } + + private function manage_systemd_service($action, $service) + { + $command = "./daemon/birdnet_manager.sh ".$action; + $workdir = $this->getParameter("kernel.project_dir") . "/../"; + $command = "cd ".$workdir." && ".$command; + echo $command; + $output = shell_exec($command); + return $output; + } + + private function systemd_service_status($service) + { + $command = "systemctl is-active ".$service; + $result = shell_exec($command); + return $result; + } +} \ No newline at end of file diff --git a/www/src/Controller/SpectroController.php b/www/src/Controller/SpectroController.php index 771b453..d407893 100644 --- a/www/src/Controller/SpectroController.php +++ b/www/src/Controller/SpectroController.php @@ -1,5 +1,4 @@ connection = $connection; - $date = date('Y-m-d'); - return $this->render('today/index.html.twig', [ - "date" => $date, - "species" => $this->recorded_species_by_date($date), - ]); + return $this->redirectToRoute("today_species"); } /** @@ -35,7 +29,7 @@ class TodayController extends AbstractController $date = date('Y-m-d'); return $this->render('today/index.html.twig', [ "date" => $date, - "species" => $this->recorded_species_by_date($date) + "results" => $this->recorded_species_by_date($date), ]); } @@ -92,7 +86,7 @@ class TodayController extends AbstractController FROM observation INNER JOIN taxon ON observation.taxon_id = taxon.taxon_id - WHERE strftime('%Y-%m-%d', `observation`.`date`) =:date + WHERE strftime('%Y-%m-%d', `observation`.`date`) = :date GROUP BY observation.taxon_id"; $stmt = $this->connection->prepare($sql); $stmt->bindValue(':date', $date); @@ -107,7 +101,7 @@ class TodayController extends AbstractController $stmt = $this->connection->prepare($sql); $stmt->bindValue(':id', $id); $result = $stmt->executeQuery(); - $taxon = $result->fetchAssociative(); + $taxon = $result->fetchAllAssociative()[0]; if (!$taxon) { return []; } diff --git a/www/templates/base.html.twig b/www/templates/base.html.twig index d72934e..2335d34 100644 --- a/www/templates/base.html.twig +++ b/www/templates/base.html.twig @@ -18,18 +18,18 @@
{% block body %} -Welcome to BirdNET-stream !
- {% endblock %} -Welcome to BirdNET-stream !
+ {% endblock %} +