Compare commits

..

12 Commits

Author SHA1 Message Date
2eb80e0da9 added url, apikey to lockscreen 2025-05-03 15:12:58 +02:00
dbcdce5296 set new gallery url 2025-05-03 15:07:08 +02:00
7482c329ed Nav fix 2025-05-03 14:36:48 +02:00
aafaf4dd9e Minor fixes with lockscreen 2025-05-03 14:34:09 +02:00
7b08d6e03f switch logger to db 2025-04-21 21:44:19 +02:00
fe5cbabd46 Fix spelling 2025-04-21 21:31:38 +02:00
141f75717b Fix burgernav icon 2025-04-21 21:25:24 +02:00
c38be00f73 Reintroduce burger nav 2025-04-21 21:24:52 +02:00
ccbcb94449 make user_select buttons dark 2025-04-21 21:08:39 +02:00
86b9595665 Add navlink to user_select 2025-04-21 21:04:10 +02:00
c6e441dc26 Refactor navbar to dynamically inject buttons 2025-04-21 21:02:11 +02:00
c89eb37361 Implement kiosk mode functionality and update external link handling in footer and credits 2025-04-21 21:01:43 +02:00
12 changed files with 124 additions and 69 deletions

View File

@ -20,7 +20,8 @@ const config = new ConfigManager(__path + '/config.json', true, {
database: 'hydrationhub' database: 'hydrationhub'
}, },
devmode: false, devmode: false,
devmode_fileupload: false devmode_fileupload: false,
galleryApiKey: '',
});//, log.core); // Disabled due to Cyclic dependencies with log handler (specifically-> devmode for loglevel) });//, log.core); // Disabled due to Cyclic dependencies with log handler (specifically-> devmode for loglevel)

View File

@ -13,7 +13,7 @@ const dotEnvExist = !fs.existsSync(dotEnvPath);
fs.writeFileSync(dotEnvPath, `DATABASE_URL="mysql://${config.global.mysql.user}:${config.global.mysql.password}@${config.global.mysql.host}:${config.global.mysql.port}/${config.global.mysql.database}"`); fs.writeFileSync(dotEnvPath, `DATABASE_URL="mysql://${config.global.mysql.user}:${config.global.mysql.password}@${config.global.mysql.host}:${config.global.mysql.port}/${config.global.mysql.database}"`);
log.core.info('Generated .env file for Prisma.'); log.core.info('Generated .env file for Prisma.');
if (dotEnvExist) { if (dotEnvExist) {
log.core.error('Please run "npx prisma db push" to synchronize the database.'); log.db.error('Please run "npx prisma db push" to synchronize the database.');
process.exit(1); process.exit(1);
} }

View File

@ -1,7 +1,8 @@
import express, { Request, Response } from 'express'; import express, { Request, Response } from 'express';
import config from '../../handlers/config.js';
function get(req: Request, res: Response) { function get(req: Request, res: Response) {
res.render("screensaver") res.render("screensaver", { apikey: config.global.galleryApiKey })
} }
export default { get }; export default { get };

View File

@ -20,7 +20,7 @@
margin-bottom: 0px; margin-bottom: 0px;
padding-bottom: 0px; padding-bottom: 0px;
text-align: center; text-align: center;
width: 95%; width: 140%;
vertical-align: middle; vertical-align: middle;
font-family: monospace; font-family: monospace;
} }
@ -47,3 +47,13 @@
95%, 95%,
100% {background-position:0 75%,0 25%,100% 75%,100% 25%} 100% {background-position:0 75%,0 25%,100% 75%,100% 25%}
} }
#credits {
position: absolute;
bottom: 1px;
left: 1px;
mix-blend-mode: difference;
color: white;
font-weight: bold;
}

13
static/js/kiosk_mode.js Normal file
View File

@ -0,0 +1,13 @@
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
// TODO: How to start kiosk mode?
if (true) {
console.info('Kiosk mode -> Disabled all external links');
document.querySelectorAll('a').forEach((link) => {
if (link.classList.contains('external-link')) {
link.style.pointerEvents = 'none';
}
});
}
}, 1000);
});

View File

@ -23,13 +23,14 @@ function handleImage() {
// default galery; spring awakens // default galery; spring awakens
uuid: '01919dec-b2cd-7adc-8ca2-a071d1169cbc;01953de0-3aa7-71f1-bfff-cbf9488efa64', uuid: '01919dec-b2cd-7adc-8ca2-a071d1169cbc;01953de0-3aa7-71f1-bfff-cbf9488efa64',
unsplash: true, unsplash: true,
// orientation: 'landscape', orientation: 'landscape',
height: window.screen.availHeight, height: window.screen.availHeight,
width: window.screen.availWidth, width: window.screen.availWidth,
cropCenteringMode: 'sm' cropCenteringMode: 'sm',
apikey: apiKey
}; };
const apiUrl = `https://staging.thegreydiamond.de/projects/photoPortfolio/api/getRand.php?${new URLSearchParams(apiParams).toString()}`; const apiUrl = `https://photo.thegreydiamond.de/api/images/random.php?${new URLSearchParams(apiParams).toString()}`;
fetch(apiUrl) fetch(apiUrl)
.then((response) => response.json()) .then((response) => response.json())
@ -79,7 +80,7 @@ function handleImage() {
}, 1000); }, 1000);
// Set the credits // Set the credits
credits.innerHTML = `Photo by <a href="${data.user.links.html}" target="_blank">${data.user.name}</a>`; credits.innerHTML = `"${data.title}" by <a href="${data.user.links.html}" class="external-link" target="_blank">${data.user.name}</a>`;
credits.style.zIndex = 300000; credits.style.zIndex = 300000;
} }
}) })

View File

@ -23,4 +23,5 @@ hidden {
footer { footer {
margin-top: auto; margin-top: auto;
padding: 1rem !important;
} }

View File

@ -4,7 +4,7 @@
<section class="section container" id="mainSelect"> <section class="section container" id="mainSelect">
<h1 class="title">Benutzerverwaltung</h1> <h1 class="title">Benutzerverwaltung</h1>
<p class="heading"><button class="js-modal-trigger button" data-target="modal-js-example"> <p class="heading"><button class="js-modal-trigger button" data-target="modal-js-example">
Neuen Konakt anlegen Benutzer anlegen
</button></p> </button></p>
<table class="table is-striped is-fullwidth is-hoverable" data-dataSource="user" id="userTable" data-pageSize="10"> <table class="table is-striped is-fullwidth is-hoverable" data-dataSource="user" id="userTable" data-pageSize="10">
<thead> <thead>

View File

@ -2,10 +2,11 @@
<div class="content has-text-centered"> <div class="content has-text-centered">
<p> <p>
<i class="bi bi-cup-straw"></i> <i class="bi bi-cup-straw"></i>
<strong>HydrationHUB</strong> by <a target="_blank" rel="noopener noreferrer" href="https://pnh.fyi">[Project-name-here]</a>.<br> <strong>HydrationHUB</strong> by <a target="_blank" rel="noopener noreferrer" href="https://pnh.fyi" class="external-link">[Project-name-here]</a>.<br>
Running Version <span data-dataSource="version" data-dataAction="SPECIAL" class="is-skeleton">Load.</span> Running Version <span data-dataSource="version" data-dataAction="SPECIAL" class="is-skeleton">Load.</span>
</p> </p>
</div> </div>
</footer> </footer>
<script src="/static/apiWrapper.js"></script> <script src="/static/apiWrapper.js"></script>
<script src="/static/pageDriver.js"></script> <script src="/static/pageDriver.js"></script>
<script src="/static/js/kiosk_mode.js"></script>

View File

@ -2,8 +2,9 @@
<div class="navbar-brand"> <div class="navbar-brand">
<a class="navbar-item primary" href="/"> <a class="navbar-item primary" href="/">
<i class="bi bi-cup-straw"></i> <i class="bi bi-cup-straw"></i>
</a>
<a class="navbar-item primary is-hidden" id="nav_username" href="/">
<strong>Hey, <span id="nav_usernameContent"></span></strong>
</a> </a>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample"> <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample">
@ -15,61 +16,83 @@
</div> </div>
<div id="navbarBasicExample" class="navbar-menu"> <div id="navbarBasicExample" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/">Screensaver</a>
<a class="navbar-item" href="/user_select">user_select</a>
<a class="navbar-item" href="/product_select">product_select</a>
<a class="navbar-item" href="/test">Test <span class="tag is-info">Dev</span></a>
<!--<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">More</a>
<div class="navbar-dropdown">
<a class="navbar-item">About</a>
<a class="navbar-item is-selected">Jobs</a>
<a class="navbar-item">Contact</a>
<hr class="navbar-divider">
<a class="navbar-item">Report an issue</a>
</div>
</div>-->
</div>
<div class="navbar-end"> <div class="navbar-end">
<div class="navbar-item is-hidden" id="showOnLogin"> <div class="navbar-item" id="dynamic-navbar-buttons">
<strong>Hey, <span id="nav_username"></span></strong> <!-- Buttons will be dynamically injected here -->
<button class="button" onclick="window.location='/pay_up'" >Zur Abrechnung</button>
</div> </div>
<div class="navbar-item is-hidden" id="onlyShowRoot">
<button class="button" onclick="window.location='/admin/'" >Zur Administration</button>
</div>
<div class="navbar-item is-hidden" id="onlyShowAdmin">
<button class="button" onclick="window.location='/admin/'" >Zur Administration</button>
<button class="button" onclick="window.location='/'" >Abmelden</button>
</div> </div>
</div> </div>
<script> <script>
// Check if ?user is set document.addEventListener('DOMContentLoaded', () => {
if (window.location.search.includes('user')) { const navbarButtons = document.getElementById('dynamic-navbar-buttons');
// Show the sign up button const currentPath = window.location.pathname;
document.querySelector('#showOnLogin').classList.remove('is-hidden'); const queryParams = new URLSearchParams(window.location.search);
// Get the username from the cookie
username = document.cookie.split('; ').find(row => row.startsWith('name')).split('=')[1]; const buttonsConfig = {
// Set the username in the nav '/user_select': [
document.getElementById('nav_username').innerText = username; { text: '', icon: 'bi bi-gear', link: '/admin' },
{ text: '', icon: 'bi bi-house', link: '/user_select' }
],
'/product_select': [
{ text: 'Zur Abrechnung', link: '/pay_up' },
{ text: '', icon: 'bi bi-gear', link: '/admin' },
{ text: '', icon: 'bi bi-box-arrow-right', link: '/user_select' }
],
'/pay_up': [
{ text: '', icon: 'bi bi-gear', link: '/admin' },
{ text: '', icon: 'bi bi-box-arrow-right', link: '/user_select' }
],
'/admin': [
{ text: '', icon: 'bi bi-house', link: '/user_select' }
],
'/admin/products': [
{ text: '', icon: 'bi bi-arrow-return-left', link: '/admin' },
{ text: '', icon: 'bi bi-house', link: '/user_select' }
],
'/admin/users': [
{ text: '', icon: 'bi bi-arrow-return-left', link: '/admin' },
{ text: '', icon: 'bi bi-house', link: '/user_select' }
],
'/admin/report': [
{ text: '', icon: 'bi bi-arrow-return-left', link: '/admin' },
{ text: '', icon: 'bi bi-house', link: '/user_select' }
]
};
if (currentPath === '/product_select' && queryParams.has('user')) {
const username = document.cookie.split('; ').find(row => row.startsWith('name'))?.split('=')[1];
if (username) {
document.getElementById('nav_usernameContent').innerText = username; // Set greeting
document.getElementById('nav_username').classList.remove('is-hidden'); // Show greeting
}
} }
// Check if /user_select is the current page const buttons = buttonsConfig[currentPath] || [];
if (window.location.pathname == '/user_select') { buttons.forEach(button => {
// Show the sign up button const btn = document.createElement('button');
document.querySelector('#onlyShowRoot').classList.remove('is-hidden'); btn.className = 'button';
btn.onclick = () => window.location = button.link;
if (button.icon) {
const icon = document.createElement('i');
icon.className = button.icon;
btn.appendChild(icon);
} }
if (button.text) {
// If admin is contained in url btn.appendChild(document.createTextNode(button.text));
if (window.location.pathname.includes('admin')) {
// Show the sign up button
document.querySelector('#onlyShowAdmin').classList.remove('is-hidden');
} }
navbarButtons.appendChild(btn);
});
// Burger menu toggle
const burger = document.querySelector('.navbar-burger');
const menu = document.querySelector('.navbar-menu');
if (burger && menu) {
burger.addEventListener('click', () => {
burger.classList.toggle('is-active');
menu.classList.toggle('is-active');
});
}
});
</script> </script>
</div>
</nav> </nav>

View File

@ -10,8 +10,12 @@
<div id="date"></div> <div id="date"></div>
</div> </div>
<script>
const apiKey = "<%= it.apikey %>";
</script>
<script src="/static/apiWrapper.js"></script> <script src="/static/apiWrapper.js"></script>
<script src="/static/pageDriver.js"></script> <script src="/static/pageDriver.js"></script>
<script src="/static/js/lockscreenBgHandler.js"></script> <script src="/static/js/lockscreenBgHandler.js"></script>
<script src="/static/js/kiosk_mode.js"></script>
<%~ include("partials/base_foot.eta") %> <%~ include("partials/base_foot.eta") %>

View File

@ -6,7 +6,7 @@
</section> </section>
<hidden> <hidden>
<!-- Base Button --> <!-- Base Button -->
<button class="button is-link is-medium m-2" id="baseStruct">Username</button> <button class="button is-dark is-medium m-2" id="baseStruct">Username</button>
</hidden> </hidden>
<div class="modal" id="pinPadModal"> <div class="modal" id="pinPadModal">
<div class="modal-background"></div> <div class="modal-background"></div>