mirror of
https://github.com/glenndehaan/unifi-voucher-site.git
synced 2026-03-31 06:24:02 -04:00
Updated kiosk.json with new translation strings. Updated info.js to reflect the multiple kiosk voucher types. Deprecated the KIOSK_VOUCHER_TYPE environment variable. Implemented the KIOSK_VOUCHER_TYPES environment variable with support for multiple voucher types. Moved the kiosk images (logo.png and bg.jpg) to a kiosk image sub-folder. Redesign of the kiosk.ejs language selector to provide space for custom images. Implemented voucher types within kiosk.ejs. Utilize the bytes converter within voucher.ejs to reformat bytes labels. Updated the docker-compose.yml. Updated the README.md. Implemented /kiosk custom assets overrides. Implemented a type check for the voucher types from kiosk requests
This commit is contained in:
119
README.md
119
README.md
@@ -6,7 +6,9 @@ UniFi Voucher Site is a web-based platform for generating and managing UniFi net
|
||||
|
||||

|
||||
|
||||
> Upgrading from 5.x to 6.x? Please take a look at the [migration guide](#migration-from-5x-to-6x)
|
||||
> Upgrading from 6.x to 7.x? Please take a look at the [migration guide](#migration-from-6x-to-7x)
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
@@ -21,6 +23,8 @@ UniFi Voucher Site is a web-based platform for generating and managing UniFi net
|
||||
- **Localized Email/Print Templates** Fully localized templates, with support for multiple languages.
|
||||
- **Scan to Connect QR Codes** Quickly connect users via a phone's camera. (Available within Email and Print Layouts)
|
||||
|
||||
---
|
||||
|
||||
## Structure
|
||||
|
||||
- Node.js
|
||||
@@ -33,6 +37,8 @@ UniFi Voucher Site is a web-based platform for generating and managing UniFi net
|
||||
- Node Thermal Printer
|
||||
- QRCode
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- UniFi Network Controller (Cloud Key, Dream Machine, or Controller software)
|
||||
@@ -47,6 +53,8 @@ UniFi Voucher Site is a web-based platform for generating and managing UniFi net
|
||||
|
||||
> Note: When creating a Local UniFi account ensure you give 'Full Management' access rights to the Network controller. The 'Hotspot Role' won't give access to the API and therefore the application will throw errors.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Docker
|
||||
@@ -59,9 +67,8 @@ You can easily run UniFi Voucher Site using Docker. We provide two release track
|
||||
**Below is an example docker-compose.yml file that can help you get started:**
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
app:
|
||||
unifi-voucher-site:
|
||||
image: glenndehaan/unifi-voucher-site:latest
|
||||
ports:
|
||||
- "3000:3000"
|
||||
@@ -124,9 +131,10 @@ services:
|
||||
SMTP_PASSWORD: ''
|
||||
# Enable/disable the kiosk page on /kiosk
|
||||
KIOSK_ENABLED: 'false'
|
||||
# Kiosk Voucher Type, format: expiration in minutes (required),single-use or multi-use vouchers value - '0' is for multi-use (unlimited) - '1' is for single-use - 'N' is for multi-use (Nx) (optional),upload speed limit in kbps (optional),download speed limit in kbps (optional),data transfer limit in MB (optional)
|
||||
# Kiosk Voucher Types, format: expiration in minutes (required),single-use or multi-use vouchers value - '0' is for multi-use (unlimited) - '1' is for single-use - 'N' is for multi-use (Nx) (optional),upload speed limit in kbps (optional),download speed limit in kbps (optional),data transfer limit in MB (optional)
|
||||
# To skip a parameter just but nothing in between the comma's
|
||||
KIOSK_VOUCHER_TYPE: '480,1,,,'
|
||||
# After a voucher type add a semicolon, after the semicolon you can start a new voucher type
|
||||
KIOSK_VOUCHER_TYPES: '480,1,,,;'
|
||||
# Enable/disable the requirement for a guest to enter their name before generating a voucher
|
||||
KIOSK_NAME_REQUIRED: 'false'
|
||||
# Sets the application Log Level (Valid Options: error|warn|info|debug|trace)
|
||||
@@ -135,6 +143,9 @@ services:
|
||||
TRANSLATION_DEFAULT: 'en'
|
||||
# Enables/disables translation debugging, when enabled only translation keys are shown
|
||||
TRANSLATION_DEBUG: 'false'
|
||||
# Optional volume mapping to override assets
|
||||
volumes:
|
||||
- ./branding:/kiosk
|
||||
```
|
||||
|
||||
### Home Assistant Add-on
|
||||
@@ -153,6 +164,8 @@ To install the UniFi Voucher Site add-on for Home Assistant, follow these steps:
|
||||
4. Once the repository is added, you will find the "UniFi Voucher Site" add-on in the add-on store. Click on it.
|
||||
5. Click "Install" and wait for the installation to complete.
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
- Install Node.js 22.0 or higher.
|
||||
@@ -161,6 +174,8 @@ To install the UniFi Voucher Site add-on for Home Assistant, follow these steps:
|
||||
|
||||
Then open up your favorite browser and go to http://localhost:3000/
|
||||
|
||||
---
|
||||
|
||||
## Services
|
||||
|
||||
The project consists of two main services: Web and API.
|
||||
@@ -362,6 +377,8 @@ the different endpoints available in the API:
|
||||
request authorization header. The token must match the value of the `AUTH_INTERNAL_BEARER_TOKEN` environment variable. Without
|
||||
this token, access to the endpoint will be denied.
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
The UniFi Voucher Site provides three options for authenticating access to the web service.
|
||||
@@ -453,6 +470,8 @@ AUTH_DISABLE: 'true'
|
||||
|
||||
> Note: This disables the token based authentication on the API
|
||||
|
||||
---
|
||||
|
||||
## Print Functionality
|
||||
|
||||
The UniFi Voucher Site application includes built-in support for printing vouchers using 80mm receipt printers, offering a convenient way to distribute vouchers in physical format.
|
||||
@@ -511,6 +530,8 @@ Just like with PDF printing, navigate to the voucher and click on the "Print" bu
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Email Functionality
|
||||
|
||||
The UniFi Voucher Site includes a convenient email feature that allows you to send vouchers directly to users from the web interface. By configuring the SMTP settings, you can enable email sending and make it easy to distribute vouchers digitally.
|
||||
@@ -547,6 +568,8 @@ Once the SMTP environment variables are configured, the email feature will be av
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Kiosk Functionality
|
||||
|
||||
The UniFi Voucher Site includes a **Kiosk Mode**, allowing users to generate their own vouchers via a self-service interface. This is ideal for public areas, such as cafés, hotels, and co-working spaces, where users can obtain internet access without staff intervention.
|
||||
@@ -555,7 +578,7 @@ To enable the kiosk functionality, set the following environment variables:
|
||||
|
||||
```env
|
||||
KIOSK_ENABLED: 'true'
|
||||
KIOSK_VOUCHER_TYPE: '480,1,,,'
|
||||
KIOSK_VOUCHER_TYPES: '480,1,,,;'
|
||||
```
|
||||
|
||||
### Configuration
|
||||
@@ -564,7 +587,7 @@ KIOSK_VOUCHER_TYPE: '480,1,,,'
|
||||
- Set to `'true'` to enable the kiosk page, making it accessible at `/kiosk`.
|
||||
- Set to `'false'` to disable the kiosk functionality.
|
||||
|
||||
- **`KIOSK_VOUCHER_TYPE`**: Defines the voucher properties for kiosk-generated vouchers. The format consists of the following parameters:
|
||||
- **`KIOSK_VOUCHER_TYPES`**: Defines the voucher properties for kiosk-generated vouchers. The format consists of the following parameters:
|
||||
|
||||
```text
|
||||
expiration_in_minutes,single_use_or_multi_use,upload_speed_limit_kbps,download_speed_limit_kbps,data_transfer_limit_MB
|
||||
@@ -579,10 +602,56 @@ KIOSK_VOUCHER_TYPE: '480,1,,,'
|
||||
- **Download Speed Limit (optional)**: Maximum download speed in Kbps. Leave empty to disable.
|
||||
- **Data Transfer Limit (optional)**: Total data limit in MB. Leave empty to disable.
|
||||
|
||||
> **Multiple Voucher Types:**
|
||||
> You can define multiple voucher types by separating each configuration with a semicolon (`;`).
|
||||
> Example:
|
||||
>
|
||||
> ```text
|
||||
> 480,1,,,;1440,0,512,2048,1000
|
||||
> ```
|
||||
>
|
||||
> This defines two voucher types:
|
||||
>
|
||||
> 1. A single-use voucher valid for 480 minutes with no speed or data limits.
|
||||
> 2. A multi-use (unlimited) voucher valid for 1440 minutes, limited to 512 Kbps upload, 2048 Kbps download, and 1000 MB data.
|
||||
|
||||
- **`KIOSK_NAME_REQUIRED`**:
|
||||
- Set to `'true'` to enable the requirement for a guest to enter their name before generating a voucher.
|
||||
- Set to `'false'` to disable to allow generation of vouchers without a name.
|
||||
|
||||
### Custom Branding (Logo and Background)
|
||||
|
||||
You can customize the appearance of the kiosk page by providing your own `logo.png` and `bg.jpg` images.
|
||||
|
||||
To do this, use Docker volume mappings to mount your custom assets to the `/kiosk` directory inside the container. The application will use these files (if present) instead of the default ones.
|
||||
|
||||
#### Example
|
||||
|
||||
Suppose you have your custom images in a local directory called `branding/`:
|
||||
|
||||
```
|
||||
branding/
|
||||
├── logo.png
|
||||
└── bg.jpg
|
||||
```
|
||||
|
||||
You can configure this using Docker Compose:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
unifi-voucher-site:
|
||||
image: glenndehaan/unifi-voucher-site:latest
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
KIOSK_ENABLED: 'true'
|
||||
KIOSK_VOUCHER_TYPES: '480,1,,,;'
|
||||
volumes:
|
||||
- ./branding:/kiosk
|
||||
```
|
||||
|
||||
> **Note:** Ensure `logo.png` and `bg.jpg` are valid image files. Both are optional — only override the ones you want to customize.
|
||||
|
||||
### Usage
|
||||
|
||||
Once enabled, the kiosk page is available at:
|
||||
@@ -597,6 +666,8 @@ Users can visit this URL and generate a voucher without administrative intervent
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Translations
|
||||
|
||||
The UniFi Voucher Site supports multiple languages, and we're actively working to expand the list of available translations. To facilitate this, we use **Crowdin**, a platform that allows people from around the world to help translate and improve the localization of the project.
|
||||
@@ -620,6 +691,8 @@ Once you're there, you can choose your language and start contributing immediate
|
||||
|
||||
Your contributions will be automatically included in the next release after review.
|
||||
|
||||
---
|
||||
|
||||
## Screenshots
|
||||
|
||||
### Login (Desktop)
|
||||
@@ -646,12 +719,42 @@ Your contributions will be automatically included in the next release after revi
|
||||
### Voucher Details (Mobile)
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Release Notes
|
||||
|
||||
Detailed information on the changes in each release can be found on the [GitHub Releases](https://github.com/glenndehaan/unifi-voucher-site/releases) page. It is highly recommended to review the release notes before updating or deploying a new version, especially if you are upgrading from a previous version.
|
||||
|
||||
---
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### Migration from 6.x to 7.x
|
||||
|
||||
When upgrading from 6.x to 7.x, the following changes need to be made:
|
||||
|
||||
1. **`KIOSK_VOUCHER_TYPE` Renamed to `KIOSK_VOUCHER_TYPES`**
|
||||
|
||||
* The configuration variable **`KIOSK_VOUCHER_TYPE`** has been **renamed** to **`KIOSK_VOUCHER_TYPES`** in 7.x.
|
||||
* This change supports multiple voucher types and enhances configurability.
|
||||
|
||||
**Before (6.x):**
|
||||
|
||||
```env
|
||||
KIOSK_VOUCHER_TYPE='480,1,,,'
|
||||
```
|
||||
|
||||
**After (7.x):**
|
||||
|
||||
```env
|
||||
KIOSK_VOUCHER_TYPES='480,1,,,;'
|
||||
```
|
||||
|
||||
* Update your environment configuration to use the new `KIOSK_VOUCHER_TYPES` variable.
|
||||
* Ensure the values provided are valid and supported — refer to the [Kiosk Configuration](#configuration-3) for the complete list of accepted types and formatting rules.
|
||||
|
||||
> Make sure to remove the deprecated `KIOSK_VOUCHER_TYPE` and follow the structure outlined in the documentation to avoid misconfiguration issues during deployment.
|
||||
|
||||
### Migration from 5.x to 6.x
|
||||
|
||||
When upgrading from 5.x to 6.x, the following changes need to be made:
|
||||
@@ -789,6 +892,8 @@ No migration steps are required.
|
||||
|
||||
Versions before v1 do not have a direct migration path. If you are using a version earlier than v1, a fresh installation is required. Be sure to back up any important data before proceeding with a re-install.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
services:
|
||||
app:
|
||||
unifi-voucher-site:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
@@ -32,7 +32,7 @@ services:
|
||||
SMTP_USERNAME: ''
|
||||
SMTP_PASSWORD: ''
|
||||
KIOSK_ENABLED: 'false'
|
||||
KIOSK_VOUCHER_TYPE: '480,1,,,'
|
||||
KIOSK_VOUCHER_TYPES: '480,1,,,;'
|
||||
KIOSK_NAME_REQUIRED: 'false'
|
||||
LOG_LEVEL: 'info'
|
||||
TRANSLATION_DEBUG: 'false'
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
{
|
||||
"title": "WiFi Voucher",
|
||||
"language": "Language",
|
||||
"type": "Type",
|
||||
"multiUse": "Multi-use",
|
||||
"singleUse": "Single-use",
|
||||
"unlimitedUse": "Unlimited",
|
||||
"duration": "Duration",
|
||||
"dataLimit": "Data Limit",
|
||||
"downloadLimit": "Download Limit",
|
||||
"uploadLimit": "Upload Limit",
|
||||
"guestName": "Guest Name",
|
||||
"generate": "Generate WiFi Voucher",
|
||||
"generating": "Generating Voucher",
|
||||
|
||||
@@ -110,9 +110,10 @@ module.exports = () => {
|
||||
* Log kiosk status
|
||||
*/
|
||||
if(variables.kioskEnabled) {
|
||||
const kioskType = types(variables.kioskVoucherType, true);
|
||||
log.info(`[Kiosk] Enabled! ${variables.kioskNameRequired ? '(Guest Name Required!)' : ''}`);
|
||||
log.info(`[Kiosk][Type] ${time(kioskType.expiration)}, ${kioskType.usage === '1' ? 'single-use' : kioskType.usage === '0' ? 'multi-use (unlimited)' : `multi-use (${kioskType.usage}x)`}${typeof kioskType.upload === "undefined" && typeof kioskType.download === "undefined" && typeof kioskType.megabytes === "undefined" ? ', no limits' : `${typeof kioskType.upload !== "undefined" ? `, upload bandwidth limit: ${kioskType.upload} kb/s` : ''}${typeof kioskType.download !== "undefined" ? `, download bandwidth limit: ${kioskType.download} kb/s` : ''}${typeof kioskType.megabytes !== "undefined" ? `, quota limit: ${kioskType.megabytes} mb` : ''}`}`);
|
||||
types(variables.kioskVoucherTypes).forEach((type, key) => {
|
||||
log.info(`[Kiosk][Type][${key}] ${time(type.expiration)}, ${type.usage === '1' ? 'single-use' : type.usage === '0' ? 'multi-use (unlimited)' : `multi-use (${type.usage}x)`}${typeof type.upload === "undefined" && typeof type.download === "undefined" && typeof type.megabytes === "undefined" ? ', no limits' : `${typeof type.upload !== "undefined" ? `, upload bandwidth limit: ${type.upload} kb/s` : ''}${typeof type.download !== "undefined" ? `, download bandwidth limit: ${type.download} kb/s` : ''}${typeof type.megabytes !== "undefined" ? `, quota limit: ${type.megabytes} mb` : ''}`}`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,7 +40,7 @@ module.exports = {
|
||||
smtpUsername: config('smtp_username') || process.env.SMTP_USERNAME || '',
|
||||
smtpPassword: config('smtp_password') || process.env.SMTP_PASSWORD || '',
|
||||
kioskEnabled: config('kiosk_enabled') || (process.env.KIOSK_ENABLED === 'true') || false,
|
||||
kioskVoucherType: config('kiosk_voucher_type') || process.env.KIOSK_VOUCHER_TYPE || '480,1,,,',
|
||||
kioskVoucherTypes: config('kiosk_voucher_types') || process.env.KIOSK_VOUCHER_TYPES || '480,1,,,;',
|
||||
kioskNameRequired: config('kiosk_name_required') || (process.env.KIOSK_NAME_REQUIRED === 'true') || false,
|
||||
logLevel: config('log_level') || process.env.LOG_LEVEL || 'info',
|
||||
translationDefault: config('translation_default') || process.env.TRANSLATION_DEFAULT || 'en',
|
||||
|
||||
|
Before Width: | Height: | Size: 259 KiB After Width: | Height: | Size: 259 KiB |
BIN
public/images/kiosk/logo.png
Normal file
BIN
public/images/kiosk/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 328 KiB |
20
server.js
20
server.js
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Import base packages
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const crypto = require('crypto');
|
||||
const express = require('express');
|
||||
@@ -88,6 +89,13 @@ app.use((req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
/**
|
||||
* Override kiosk images dir if available
|
||||
*/
|
||||
if(fs.existsSync('/kiosk')) {
|
||||
app.use('/images/kiosk', express.static('/kiosk'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve static public dir
|
||||
*/
|
||||
@@ -155,6 +163,9 @@ if(variables.serviceWeb) {
|
||||
baseUrl: req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : '',
|
||||
error: req.flashMessage.type === 'error',
|
||||
error_text: req.flashMessage.message || '',
|
||||
timeConvert: time,
|
||||
bytesConvert: bytes,
|
||||
voucher_types: types(variables.kioskVoucherTypes),
|
||||
kiosk_name_required: variables.kioskNameRequired
|
||||
});
|
||||
});
|
||||
@@ -207,8 +218,15 @@ if(variables.serviceWeb) {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const typeCheck = (variables.kioskVoucherTypes).split(';').includes(req.body['voucher-type']);
|
||||
|
||||
if (!typeCheck) {
|
||||
res.cookie('flashMessage', JSON.stringify({type: 'error', message: 'Unknown Type!'}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/kiosk`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create voucher code
|
||||
const voucherCode = await unifi.create(types(variables.kioskVoucherType, true), 1, variables.kioskNameRequired ? req.body['voucher-note'] : null).catch((e) => {
|
||||
const voucherCode = await unifi.create(types(req.body['voucher-type'], true), 1, variables.kioskNameRequired ? req.body['voucher-note'] : null).catch((e) => {
|
||||
res.cookie('flashMessage', JSON.stringify({type: 'error', message: e}), {httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000)}).redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/kiosk`);
|
||||
});
|
||||
|
||||
|
||||
@@ -35,25 +35,13 @@
|
||||
<% } %>
|
||||
|
||||
<div class="fixed top-0 left-0 w-full h-full -z-20">
|
||||
<img src="<%= baseUrl %>/images/kiosk_bg.jpg" alt="Kiosk Background" class="w-full h-full object-cover"/>
|
||||
<img src="<%= baseUrl %>/images/kiosk/bg.jpg" alt="Kiosk Background" class="w-full h-full object-cover"/>
|
||||
</div>
|
||||
<div class="fixed top-0 left-0 w-full h-full -z-10 bg-white/70 dark:bg-black/70"></div>
|
||||
|
||||
<div class="w-full max-w-md bg-white dark:bg-gray-800 rounded-lg border border-black/5 dark:border-white/5 shadow-sm z-10 relative">
|
||||
<div class="p-4 border-b border-black/5 dark:border-white/5">
|
||||
<% if(typeof voucherCode === 'undefined') { %>
|
||||
<div class="absolute top-2 right-2">
|
||||
<form id="locale-form" action="<%= baseUrl %>/kiosk" method="get">
|
||||
<select id="locale" name="locale" class="max-w-28 block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 dark:text-white dark:bg-white/5 ring-1 ring-inset ring-gray-300 dark:ring-white/10 focus:ring-2 focus:ring-sky-600 sm:text-sm sm:leading-6 **:text-black">
|
||||
<% Object.keys(languages).forEach((l) => { %>
|
||||
<option value="<%= l %>-<%= l %>"<%= l === language ? ' selected' : '' %>><%= languages[l] %></option>
|
||||
<% }); %>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<img class="mx-auto h-24 w-auto" width="48" height="48" alt="UniFi Voucher Site Logo" src="<%= baseUrl %>/images/logo.png">
|
||||
<img class="mx-auto h-24 w-auto" width="48" height="48" alt="UniFi Voucher Site Logo" src="<%= baseUrl %>/images/kiosk/logo.png">
|
||||
<h1 class="mt-4 text-2xl font-semibold text-center text-gray-900 dark:text-white"><%= t('title') %></h1>
|
||||
|
||||
<% if(error) { %>
|
||||
@@ -75,7 +63,27 @@
|
||||
<div class="p-4">
|
||||
<% if(typeof voucherCode === 'undefined') { %>
|
||||
<div class="block">
|
||||
<form id="locale-form" class="mb-6" action="<%= baseUrl %>/kiosk" method="get">
|
||||
<label for="locale" class="block text-sm font-medium leading-6 text-gray-900 dark:text-white"><%= t('language') %></label>
|
||||
<div class="mt-2">
|
||||
<select id="locale" name="locale" class="mt-2 block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 dark:text-white dark:bg-white/5 ring-1 ring-inset ring-gray-300 dark:ring-white/10 focus:ring-2 focus:ring-sky-600 sm:text-sm sm:leading-6 **:text-black">
|
||||
<% Object.keys(languages).forEach((l) => { %>
|
||||
<option value="<%= l %>-<%= l %>"<%= l === language ? ' selected' : '' %>><%= languages[l] %></option>
|
||||
<% }); %>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
<form id="voucher-form" class="space-y-6" action="<%= baseUrl %>/kiosk?locale=<%= language %>-<%= language %>" method="post" enctype="multipart/form-data">
|
||||
<div class="<%= voucher_types.length < 2 ? 'hidden' : '' %>">
|
||||
<label for="voucher-type" class="block text-sm font-medium leading-6 text-gray-900 dark:text-white"><%= t('type') %></label>
|
||||
<div class="mt-2">
|
||||
<select id="voucher-type" name="voucher-type" class="mt-2 block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 dark:text-white dark:bg-white/5 ring-1 ring-inset ring-gray-300 dark:ring-white/10 focus:ring-2 focus:ring-sky-600 sm:text-sm sm:leading-6 **:text-black">
|
||||
<% voucher_types.forEach((type) => { %>
|
||||
<option value="<%= type.raw %>"><%= timeConvert(type.expiration) %>, <%= type.usage === '1' ? t('singleUse') : type.usage === '0' ? `${t('multiUse')} (${t('unlimitedUse')})` : `${t('multiUse')} (${type.usage}x)` %><%= typeof type.upload !== "undefined" ? `, ${t('uploadLimit')}: ${bytesConvert(type.upload, 1, true)}` : '' %><%= typeof type.download !== "undefined" ? `, ${t('downloadLimit')}: ${bytesConvert(type.download, 1, true)}` : '' %><%= typeof type.megabytes !== "undefined" ? `, ${t('dataLimit')}: ${bytesConvert(type.megabytes, 2)}` : '' %></option>
|
||||
<% }); %>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<% if(kiosk_name_required) { %>
|
||||
<div>
|
||||
<label for="voucher-note" class="block text-sm font-medium leading-6 text-gray-900 dark:text-white"><%= t('guestName') %></label>
|
||||
|
||||
@@ -267,7 +267,7 @@
|
||||
<div class="mt-2">
|
||||
<select id="voucher-type" name="voucher-type" class="mt-2 block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 dark:text-white dark:bg-white/5 ring-1 ring-inset ring-gray-300 dark:ring-white/10 focus:ring-2 focus:ring-sky-600 sm:text-sm sm:leading-6 **:text-black">
|
||||
<% voucher_types.forEach((type) => { %>
|
||||
<option value="<%= type.raw %>"><%= timeConvert(type.expiration) %>, <%= type.usage === '1' ? 'single-use' : type.usage === '0' ? 'multi-use (unlimited)' : `multi-use (${type.usage}x)` %><%= typeof type.upload === "undefined" && typeof type.download === "undefined" && typeof type.megabytes === "undefined" ? ', no limits' : '' %><%= typeof type.upload !== "undefined" ? `, upload bandwidth limit: ${type.upload} kb/s` : '' %><%= typeof type.download !== "undefined" ? `, download bandwidth limit: ${type.download} kb/s` : '' %><%= typeof type.megabytes !== "undefined" ? `, quota limit: ${type.megabytes} mb` : '' %></option>
|
||||
<option value="<%= type.raw %>"><%= timeConvert(type.expiration) %>, <%= type.usage === '1' ? 'single-use' : type.usage === '0' ? 'multi-use (unlimited)' : `multi-use (${type.usage}x)` %><%= typeof type.upload === "undefined" && typeof type.download === "undefined" && typeof type.megabytes === "undefined" ? ', no limits' : '' %><%= typeof type.upload !== "undefined" ? `, upload bandwidth limit: ${bytesConvert(type.upload, 1, true)}` : '' %><%= typeof type.download !== "undefined" ? `, download bandwidth limit: ${bytesConvert(type.download, 1, true)}` : '' %><%= typeof type.megabytes !== "undefined" ? `, quota limit: ${bytesConvert(type.megabytes, 2)}` : '' %></option>
|
||||
<% }); %>
|
||||
<% if(voucher_custom) { %>
|
||||
<option value="custom">Custom</option>
|
||||
|
||||
@@ -10,6 +10,7 @@ module.exports = {
|
||||
'AUTH_TOKEN',
|
||||
'UI_BACK_BUTTON',
|
||||
'PRINTER_TYPE',
|
||||
'PRINTER_IP'
|
||||
'PRINTER_IP',
|
||||
'KIOSK_VOUCHER_TYPE'
|
||||
]
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user