You've already forked fm-dx-webserver
mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-02-26 14:11:59 +01:00
bugfixes & plugins WS & UI fixes
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fm-dx-webserver",
|
||||
"version": "1.2.8",
|
||||
"version": "1.2.8.1",
|
||||
"description": "FM DX Webserver",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -234,7 +234,9 @@ var dataToSend = {
|
||||
itu: '',
|
||||
dist: '',
|
||||
azi: '',
|
||||
id: ''
|
||||
id: '',
|
||||
reg: '',
|
||||
pi: '',
|
||||
},
|
||||
country_name: '',
|
||||
country_iso: 'UN',
|
||||
@@ -294,6 +296,7 @@ function handleData(wss, receivedData, rdsWss) {
|
||||
initialData.freq = (parsedValue / 1000).toFixed(3);
|
||||
dataToSend.freq = (parsedValue / 1000).toFixed(3);
|
||||
dataToSend.pi = '?';
|
||||
dataToSend.txInfo.reg = false;
|
||||
|
||||
rdsWss.clients.forEach((client) => {
|
||||
client.send("G:\r\nRESET-------\r\n\r\n");
|
||||
@@ -401,7 +404,9 @@ function handleData(wss, receivedData, rdsWss) {
|
||||
itu: currentTx.itu,
|
||||
dist: currentTx.distance,
|
||||
azi: currentTx.azimuth,
|
||||
id: currentTx.id
|
||||
id: currentTx.id,
|
||||
pi: currentTx.pi,
|
||||
reg: currentTx.reg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// index.js - Mod by Highpoint
|
||||
// Version for loading server-side plugins
|
||||
|
||||
// Library imports
|
||||
const express = require('express');
|
||||
const endpoints = require('./endpoints');
|
||||
@@ -15,7 +12,7 @@ const WebSocket = require('ws');
|
||||
const wss = new WebSocket.Server({ noServer: true });
|
||||
const chatWss = new WebSocket.Server({ noServer: true });
|
||||
const rdsWss = new WebSocket.Server({ noServer: true });
|
||||
const ExtraWss = new WebSocket.Server({ noServer: true });
|
||||
const pluginsWss = new WebSocket.Server({ noServer: true });
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const net = require('net');
|
||||
@@ -537,14 +534,14 @@ rdsWss.on('connection', (ws, request) => {
|
||||
});
|
||||
|
||||
//additional web socket for using plugins
|
||||
ExtraWss.on('connection', (ws, request) => {
|
||||
pluginsWss.on('connection', (ws, request) => {
|
||||
ws.on('message', message => {
|
||||
|
||||
const messageData = JSON.parse(message);
|
||||
const modifiedMessage = JSON.stringify(messageData);
|
||||
|
||||
//Broadcast the message to all other clients
|
||||
ExtraWss.clients.forEach(client => {
|
||||
pluginsWss.clients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(modifiedMessage); // Send the message to all clients
|
||||
}
|
||||
@@ -582,10 +579,10 @@ httpServer.on('upgrade', (request, socket, head) => {
|
||||
rdsWss.emit('connection', ws, request);
|
||||
});
|
||||
});
|
||||
} else if (request.url === '/extra') {
|
||||
} else if (request.url === '/data_plugins') {
|
||||
sessionMiddleware(request, {}, () => {
|
||||
ExtraWss.handleUpgrade(request, socket, head, (ws) => {
|
||||
ExtraWss.emit('connection', ws, request);
|
||||
pluginsWss.handleUpgrade(request, socket, head, (ws) => {
|
||||
pluginsWss.emit('connection', ws, request);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
@@ -599,25 +596,28 @@ app.use(express.static(path.join(__dirname, '../web'))); // Serve the entire web
|
||||
checkIPv6Support((isIPv6Supported) => {
|
||||
const ipv4Address = serverConfig.webserver.webserverIp === '0.0.0.0' ? 'localhost' : serverConfig.webserver.webserverIp;
|
||||
const ipv6Address = '::'; // This will bind to all available IPv6 interfaces
|
||||
|
||||
if (isIPv6Supported) {
|
||||
// Start server on both IPv4 and IPv6 addresses
|
||||
httpServer.listen(serverConfig.webserver.webserverPort, ipv4Address, () => {
|
||||
logInfo(`Web server has started on address \x1b[34mhttp://${ipv4Address}:${serverConfig.webserver.webserverPort}\x1b[0m.`);
|
||||
});
|
||||
const port = serverConfig.webserver.webserverPort;
|
||||
|
||||
httpServer.listen(serverConfig.webserver.webserverPort, ipv6Address, () => {
|
||||
logInfo(`Web server has started on address \x1b[34mhttp://[${ipv6Address}]:${serverConfig.webserver.webserverPort}\x1b[0m.`);
|
||||
});
|
||||
} else {
|
||||
// Start server only on IPv4 address
|
||||
httpServer.listen(serverConfig.webserver.webserverPort, ipv4Address, () => {
|
||||
if (configExists()) {
|
||||
logInfo(`Web server has started on address \x1b[34mhttp://${ipv4Address}:${serverConfig.webserver.webserverPort}\x1b[0m.`);
|
||||
const logServerStart = (address, isIPv6) => {
|
||||
const formattedAddress = isIPv6 ? `[${address}]` : address;
|
||||
logInfo(`Web server has started on address \x1b[34mhttp://${formattedAddress}:${port}\x1b[0m.`);
|
||||
};
|
||||
|
||||
const startServer = (address, isIPv6) => {
|
||||
httpServer.listen(port, address, () => {
|
||||
if (!isIPv6 && !configExists()) {
|
||||
logInfo(`Open your browser and proceed to \x1b[34mhttp://${address}:${port}\x1b[0m to continue with setup.`);
|
||||
} else {
|
||||
logInfo(`Open your browser and proceed to \x1b[34mhttp://${ipv4Address}:${serverConfig.webserver.webserverPort}\x1b[0m to continue with setup.`);
|
||||
logServerStart(address, isIPv6);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (isIPv6Supported) {
|
||||
startServer(ipv4Address, false); // Start on IPv4
|
||||
startServer(ipv6Address, true); // Start on IPv6
|
||||
} else {
|
||||
startServer(ipv4Address, false); // Start only on IPv4
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -50,42 +50,69 @@ function processData(data, piCode, rdsPs) {
|
||||
let txAzimuth;
|
||||
let maxDistance;
|
||||
let esMode = checkEs();
|
||||
let detectedByPireg = false; // To track if the station was found by pireg
|
||||
|
||||
// Helper function to calculate score and update matching station/city
|
||||
function evaluateStation(station, city, distance) {
|
||||
let weightDistance = distance.distanceKm;
|
||||
if (esMode && distance.distanceKm > 500) {
|
||||
weightDistance = Math.abs(distance.distanceKm - 1500);
|
||||
}
|
||||
let erp = station.erp && station.erp > 0 ? station.erp : 1;
|
||||
const score = (10 * Math.log10(erp * 1000)) / weightDistance; // Calculate score
|
||||
if (score > maxScore) {
|
||||
maxScore = score;
|
||||
txAzimuth = distance.azimuth;
|
||||
matchingStation = station;
|
||||
matchingCity = city;
|
||||
maxDistance = distance.distanceKm;
|
||||
}
|
||||
}
|
||||
|
||||
// First attempt: Try to match station using the piCode
|
||||
for (const cityId in data.locations) {
|
||||
const city = data.locations[cityId];
|
||||
if (city.stations) {
|
||||
for (const station of city.stations) {
|
||||
if (station.pi === piCode.toUpperCase() && !station.extra && station.ps && station.ps.toLowerCase().includes(rdsPs.replace(/ /g, '_').replace(/^_*(.*?)_*$/, '$1').toLowerCase())) {
|
||||
const distance = haversine(serverConfig.identification.lat, serverConfig.identification.lon, city.lat, city.lon);
|
||||
let weightDistance = distance.distanceKm
|
||||
if (esMode && (distance.distanceKm > 500)) {
|
||||
weightDistance = Math.abs(distance.distanceKm-1500);
|
||||
}
|
||||
let erp = (station.erp && station.erp > 0) ? station.erp : 1;
|
||||
const score = (10*Math.log10(erp*1000)) / weightDistance; // Calculate score
|
||||
if (score > maxScore) {
|
||||
maxScore = score;
|
||||
txAzimuth = distance.azimuth;
|
||||
matchingStation = station;
|
||||
matchingCity = city;
|
||||
maxDistance = distance.distanceKm;
|
||||
evaluateStation(station, city, distance);
|
||||
detectedByPireg = false; // Detected by pi, not pireg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no matching station is found, fallback to pireg
|
||||
if (!matchingStation) {
|
||||
for (const cityId in data.locations) {
|
||||
const city = data.locations[cityId];
|
||||
if (city.stations) {
|
||||
for (const station of city.stations) {
|
||||
if (station.pireg && station.pireg.toUpperCase() === piCode.toUpperCase() && !station.extra && station.ps && station.ps.toLowerCase().includes(rdsPs.replace(/ /g, '_').replace(/^_*(.*?)_*$/, '$1').toLowerCase())) {
|
||||
const distance = haversine(serverConfig.identification.lat, serverConfig.identification.lon, city.lat, city.lon);
|
||||
evaluateStation(station, city, distance);
|
||||
detectedByPireg = true; // Detected by pireg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the results if a station was found, otherwise return undefined
|
||||
if (matchingStation) {
|
||||
return {
|
||||
station: matchingStation.station.replace("R.", "Radio "),
|
||||
pol: matchingStation.pol.toUpperCase(),
|
||||
erp: (matchingStation.erp && matchingStation.erp > 0) ? matchingStation.erp : '?',
|
||||
erp: matchingStation.erp && matchingStation.erp > 0 ? matchingStation.erp : '?',
|
||||
city: matchingCity.name,
|
||||
itu: matchingCity.itu,
|
||||
distance: maxDistance.toFixed(0),
|
||||
azimuth: txAzimuth.toFixed(0),
|
||||
id: matchingStation.id,
|
||||
foundStation: true
|
||||
pi: matchingStation.pi,
|
||||
foundStation: true,
|
||||
reg: detectedByPireg // Indicates if it was detected by pireg
|
||||
};
|
||||
} else {
|
||||
return;
|
||||
|
||||
@@ -82,6 +82,10 @@ input[type="text"], textarea, input[type="password"] {
|
||||
caret-color: var(--color-4);
|
||||
}
|
||||
|
||||
input[type="password"]:not(#xdrd-password) {
|
||||
border-radius: 15px 0 0 15px;
|
||||
}
|
||||
|
||||
#tune-buttons input[type="text"] {
|
||||
width: 50%;
|
||||
height: 48px;
|
||||
|
||||
BIN
web/favicon.png
BIN
web/favicon.png
Binary file not shown.
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 5.9 KiB |
@@ -93,6 +93,9 @@
|
||||
<div class="flex-container">
|
||||
<div class="panel-33 hover-brighten tooltip" id="pi-code-container" data-tooltip="Clicking on the PI code will show the current station on a map.">
|
||||
<h2>PI CODE</h2>
|
||||
<div class="text-small text-gray highest-signal-container">
|
||||
<span id="data-regular-pi"> </span>
|
||||
</div>
|
||||
<span id="data-pi" class="text-big text-uppercase"></span>
|
||||
</div>
|
||||
|
||||
@@ -261,7 +264,7 @@
|
||||
<span id="data-station-city" style="font-size: 16px;"></span> <span class="text-small">[<span id="data-station-itu"></span>]</span>
|
||||
</h4>
|
||||
<span class="text-small">
|
||||
<span id="data-station-erp"></span> kW [<span id="data-station-pol"></span>] <span class="text-gray">•</span> <span id="data-station-distance"></span> km <span class="text-gray">•</span> <span id="data-station-azimuth"></span>°
|
||||
<span id="data-station-erp"></span> kW [<span id="data-station-pol"></span>] <span class="text-gray">•</span> <span id="data-station-distance"></span> km <span class="text-gray">•</span> <span id="data-station-azimuth"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -395,7 +398,7 @@
|
||||
<% } else { %>
|
||||
<form action="./login" method="post" id="login-form" class="top-25">
|
||||
<input type="password" id="password" name="password" placeholder="Password" style="width: 145px;" required>
|
||||
<button type="submit" class="br-0 top-10 tooltip" style="height: 46px; width: 50px; margin-left: 0;" role="button" aria-label="Log in" tabindex="0" data-tooltip="Log in">
|
||||
<button type="submit" class="br-0 top-10 tooltip" style="height: 46px; width: 50px; margin-left: -2px;border-radius: 0 15px 15px 0;" role="button" aria-label="Log in" tabindex="0" data-tooltip="Log in">
|
||||
<i class="fa-solid fa-right-to-bracket"></i>
|
||||
</button>
|
||||
</form>
|
||||
@@ -436,7 +439,7 @@
|
||||
<p class="m-0">
|
||||
FM-DX Webserver <span style="color: var(--color-3);" class="version-string"></span>
|
||||
</p>
|
||||
<p class="text-small m-0 color-3">by <a href="https://noobish.eu" target="_blank">Noobish</a>, <a href="https://fmdx.pl" target="_blank">kkonradpl</a> & the OpenRadio community.</p>
|
||||
<p class="text-small m-0 color-3">by <a href="https://fmdx.org" target="_blank">FMDX.org</a></p>
|
||||
<span class="text-small" style="color: var(--color-3);">[<a href="https://servers.fmdx.org/" target="_blank">Receiver Map</a>]</span>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
var currentDate = new Date('Sep 11, 2024 23:50:00');
|
||||
var currentDate = new Date('Sep 12, 2024 21:30:00');
|
||||
var day = currentDate.getDate();
|
||||
var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1
|
||||
var year = currentDate.getFullYear();
|
||||
var formattedDate = day + '/' + month + '/' + year;
|
||||
var currentVersion = 'v1.2.8 [' + formattedDate + ']';
|
||||
var currentVersion = 'v1.2.8.1 [' + formattedDate + ']';
|
||||
|
||||
getInitialSettings();
|
||||
removeUrlParameters(); // Call this function to remove URL parameters
|
||||
|
||||
@@ -827,7 +827,8 @@ const updateDataElements = throttle(function(parsedData) {
|
||||
updateTextIfChanged($('#data-station-itu'), parsedData.txInfo.itu);
|
||||
updateTextIfChanged($('#data-station-pol'), parsedData.txInfo.pol);
|
||||
updateTextIfChanged($('#data-station-distance'), parsedData.txInfo.dist);
|
||||
updateTextIfChanged($('#data-station-azimuth'), parsedData.txInfo.azi);
|
||||
updateHtmlIfChanged($('#data-station-azimuth'), parsedData.txInfo.azi + '°');
|
||||
updateHtmlIfChanged($('#data-regular-pi'), parsedData.txInfo.reg === true ? parsedData.txInfo.pi : ' ');
|
||||
$dataStationContainer.css('display', 'block');
|
||||
} else {
|
||||
$dataStationContainer.removeAttr('style');
|
||||
|
||||
@@ -64,37 +64,8 @@ $(document).ready(function() {
|
||||
$('#tuner-wireless').hide();
|
||||
$('#tuner-usb').show();
|
||||
}
|
||||
});
|
||||
|
||||
$('#login-form').submit(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Perform an AJAX request to the /login endpoint
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: './login',
|
||||
data: $(this).serialize(),
|
||||
success: function (data) {
|
||||
// Update the content on the page with the message from the response
|
||||
$('#login-message').text(data.message);
|
||||
setTimeout(function () {
|
||||
location.reload(true);
|
||||
}, 1750);
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
// Handle error response
|
||||
if (xhr.status === 403) {
|
||||
// Update the content on the page with the message from the error response
|
||||
$('#login-message').text(xhr.responseJSON.message);
|
||||
} else {
|
||||
// Handle other types of errors if needed
|
||||
console.error('Error:', status, error);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Assuming you have an anchor tag with id 'logout-link'
|
||||
$('.logout-link').click(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<img class="top-10" src="./images/openradio_logo_neutral.png" height="64px">
|
||||
<h2 class="text-monospace text-light">[ADMIN PANEL]</h2>
|
||||
</div>
|
||||
<div id="login-message"></div>
|
||||
<div class="panel-100" style="border-radius: 15px 15px 0 0;">
|
||||
<ul class="nav" role="tablist" style="border-radius: 15px 15px 0 0;">
|
||||
<li role="presentation" data-panel="dashboard" aria-selected="true">
|
||||
@@ -544,15 +543,17 @@
|
||||
<div class="panel-100 p-bottom-20">
|
||||
<h2>LOGIN</h2>
|
||||
<form action="./login" method="post" id="login-form">
|
||||
<input style="background-color: var(--color-2);" type="password" id="password" name="password" required>
|
||||
<button type="submit" class="br-0 w-100" style="height: 44px;">Login</button>
|
||||
<input type="password" id="password" name="password" placeholder="Password" style="width: 250px;" required>
|
||||
<button type="submit" class="br-0 top-10 tooltip" style="height: 46px; width: 50px; margin-left: -2px;border-radius: 0 15px 15px 0;" role="button" aria-label="Log in" tabindex="0" data-tooltip="Log in">
|
||||
<i class="fa-solid fa-right-to-bracket"></i>
|
||||
</button>
|
||||
</form>
|
||||
<div id="login-message"></div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<script src="js/init.js"></script>
|
||||
<script src="js/toast.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<script src="js/dropdown.js"></script>
|
||||
<script src="js/setup.js"></script>
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
<p class="m-0 text-gray">Leave the IP at 0.0.0.0 unless you explicitly know you have to change it.<br>Don't enter your public IP here.</p>
|
||||
<div class="flex-center top-25">
|
||||
<div class="form-group">
|
||||
<label for="webserver-ip">Webserver IP:</label>
|
||||
<label for="webserver-ip">Webserver IP</label>
|
||||
<input class="input-text w-150" type="text" name="webserver-ip" id="webserver-ip" placeholder="0.0.0.0">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="webserver-port">Webserver port:</label>
|
||||
<label for="webserver-port">Webserver port</label>
|
||||
<input class="input-text w-100" type="text" name="webserver-port" id="webserver-port" placeholder="8080">
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,7 +56,7 @@
|
||||
<h3>Tuner type:</h3>
|
||||
<p class="text-gray">Settings a proper device type ensures that the correct interface and settings will load.</p>
|
||||
<div class="form-group">
|
||||
<label for="themes"><i class="fa-solid fa-radio"></i> Device:</label>
|
||||
<label for="themes"><i class="fa-solid fa-radio"></i> Device</label>
|
||||
<div class="dropdown" id="device-selector" style="margin-right: 0;">
|
||||
<input type="text" placeholder="TEF6686 / TEA685x" id="device-type" readonly>
|
||||
<ul class="options">
|
||||
@@ -82,7 +82,7 @@
|
||||
<div id="tuner-usb" class="top-25">
|
||||
<p>It's time to choose your USB device.</p>
|
||||
<div class="form-group">
|
||||
<label for="com-devices"><i class="fa-brands fa-usb"></i> USB Device:</label>
|
||||
<label for="com-devices"><i class="fa-brands fa-usb"></i> USB Device</label>
|
||||
<div class="dropdown" style="width: 300px;margin-right: 0;">
|
||||
<input id="com-devices" type="text" name="com-devices" placeholder="Choose your USB device" readonly />
|
||||
<ul class="options" id="deviceList">
|
||||
@@ -97,15 +97,15 @@
|
||||
<p class="m-0 text-gray">If you are connecting your tuner <strong>wirelessly</strong>, enter the tuner IP. <br> If you use <strong>xdrd</strong>, use 127.0.0.1 as your IP.</p>
|
||||
<div class="flex-center top-25">
|
||||
<div class="form-group">
|
||||
<label for="xdrd-ip">xdrd ip address:</label>
|
||||
<label for="xdrd-ip">xdrd ip address</label>
|
||||
<input class="input-text w-150" type="text" name="xdrd-ip" id="xdrd-ip" placeholder="127.0.0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="xdrd-port">xdrd port:</label>
|
||||
<label for="xdrd-port">xdrd port</label>
|
||||
<input class="input-text w-100" type="text" name="xdrd-port" id="xdrd-port" placeholder="7373">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="xdrd-password">xdrd server password:</label>
|
||||
<label for="xdrd-password">xdrd server password</label>
|
||||
<input class="input-text w-150" type="password" name="xdrd-password" id="xdrd-password">
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,7 +122,7 @@
|
||||
|
||||
<div class="panel-100 p-bottom-20">
|
||||
<div class="form-group">
|
||||
<label for="audio-devices"><i class="fa-solid fa-headphones"></i> STREAM AUDIO FROM:</label>
|
||||
<label for="audio-devices"><i class="fa-solid fa-headphones"></i> Stream audio from</label>
|
||||
<div class="dropdown" style="width: 300px;">
|
||||
<input id="audio-devices" type="text" name="audio-devices" placeholder="Choose your audio device" readonly />
|
||||
<ul class="options" id="deviceList">
|
||||
@@ -137,7 +137,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="audio-devices"><i class="fa-solid fa-microphone-lines"></i> AUDIO CHANNELS:</label>
|
||||
<label for="audio-devices"><i class="fa-solid fa-microphone-lines"></i> Audio channels</label>
|
||||
<div class="dropdown" style="width: 300px;">
|
||||
<input id="audio-channels" type="text" name="audio-channels" placeholder="Stereo" readonly />
|
||||
<ul class="options">
|
||||
@@ -148,7 +148,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="audio-quality"><i class="fa-solid fa-wave-square"></i> AUDIO QUALITY:</label>
|
||||
<label for="audio-quality"><i class="fa-solid fa-wave-square"></i> Audio quality</label>
|
||||
<div class="dropdown" style="width: 300px;">
|
||||
<input id="audio-quality" type="text" name="audio-quality" placeholder="128k (standard)" readonly />
|
||||
<ul class="options">
|
||||
@@ -235,23 +235,27 @@
|
||||
<% } else { %>
|
||||
<div class="panel-100 no-bg">
|
||||
<img class="top-25" src="../images/openradio_logo_neutral.png" height="64px">
|
||||
<h2 class="text-monospace text-light">[ADMIN PANEL]</h2>
|
||||
<h2 class="text-monospace text-light">[Wizard]</h2>
|
||||
<p>You are currently not logged in as an administrator and therefore can't change the settings.</p>
|
||||
<p>Please login below.</p>
|
||||
</div>
|
||||
<div class="panel-100 p-bottom-20">
|
||||
<h2>LOGIN</h2>
|
||||
<form action="./login" method="post" id="login-form">
|
||||
<input style="background-color: var(--color-2);" type="password" id="password" name="password" required>
|
||||
<button type="submit" class="br-0 w-100" style="height: 44px;">Login</button>
|
||||
<input type="password" id="password" name="password" placeholder="Password" style="width: 250px; background-color: var(--color-2);" required>
|
||||
<button type="submit" class="br-0 top-10 tooltip" style="height: 46px; width: 50px; margin-left: -4px;border-radius: 0 15px 15px 0;" role="button" aria-label="Log in" tabindex="0" data-tooltip="Log in">
|
||||
<i class="fa-solid fa-right-to-bracket"></i>
|
||||
</button>
|
||||
</form>
|
||||
<div id="login-message"></div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
<script src="js/init.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<script src="js/dropdown.js"></script>
|
||||
<script src="js/toast.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<script src="js/setup.js"></script>
|
||||
<script src="js/wizard.js"></script>
|
||||
<script src="js/confighandler.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user