Compare commits

..

4 Commits

Author SHA1 Message Date
dillard f8addb95f1 Rebrand to QRForge (local only - do not push before domain confirmed)
Applies the approved QRForge brand kit throughout the app:
- New logo/icon SVGs, favicon set (ico/svg/png), apple-touch-icon, all
  copied from the approved brand kit into src/dist/img/brand/. Old
  Symbol_WhiteBlue.png/DynamicQRCode_Original.png removed (unused after
  the swap).
- Sidebar brand image/text, login and change-password page logos, all
  <title> tags, manifest.json name/theme-color, and the PWA icons
  (dist/img/icon-192.png/icon-512.png, same filenames so no other
  reference needed to change) updated to QRForge branding and the
  #2563EB brand blue.
- New about.php page (+ sidebar link): credits the original upstream
  fork (Giandonato Inverso) and chillerlan/php-qrcode, links to the free
  qr.ensembia.com try-out, the commercial www.qrforge.eu product page,
  and this GitHub repo for self-hosters.
- Footer now reads "QRForge" + "About / credits" + "Version 3.0"
  (replaces the inherited "PHP Qrcode Generator by Giandonato Inverso" /
  "Version 2.3.0" line - full credit moved to the About page instead).
- README.md rewritten: current feature set (all 16 static qr types,
  presets, scanner, PWA, location search, roles), qr.ensembia.com as the
  free try-out, www.qrforge.eu as the commercial product page, corrected
  Docker Compose setup steps (.env is required now, the old README still
  described the single-file demo setup from the original upstream fork).

IMPORTANT: not pushed to origin/gitea. Per user instruction, no push
until qrforge.eu domain registration is confirmed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo3DiRRpmz2DXjD7Uzhc8u
2026-07-11 02:48:05 +02:00
dillard bffd9a315b Fase 3 feedback round 4: group filename with owner in the qr forms
Filename now sits in the same row as Owner instead of the crowded
top row shared with format/frame text/frame font/frame font size/icon.
Freeing that column lets those fields shift left and use the space
better. Applied to both the shared static-form partial
(qrcode_options.php) and the dynamic-form's separate copy of the same
fields (form_dynamic_add.php) - the two have diverged since Fase 3 and
don't share markup. Edit forms (form_static_edit.php/form_dynamic_edit.php)
already had filename/owner side by side, no change needed there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo3DiRRpmz2DXjD7Uzhc8u
2026-07-11 02:40:22 +02:00
dillard 23c30db5e0 Fase 3 feedback round 3: sidebar icons, thumbnail preview, location search
- Sidebar submenu bullets (List all/Add new/Batch create) swapped from
  far fa-circle to fas fa-angle-right - the outlined circle read as an
  unchecked radio button, per feedback.
- List-page qr thumbnails now sit in a fixed 100x100 box with
  object-fit:contain instead of width/height attrs, so taller images
  (e.g. icon-above-qr) no longer get squashed into a square. Thumbnails
  are now clickable, opening a shared Bootstrap modal with the full-size
  image (same data-toggle/data-target pattern already used for the
  delete-confirmation modal).
- Location QR form gets an address search box backed by OpenStreetMap
  Nominatim (dist/js/location-search.js): free-text query, pick a result,
  it fills in latitude/longitude. No API key needed; the browser talks to
  nominatim.openstreetmap.org directly, called out in the field's help
  text since queries leave the self-hosted server.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo3DiRRpmz2DXjD7Uzhc8u
2026-07-11 02:18:34 +02:00
dillard 175cbb91bf Fase 3 feedback round 2: live color preview, bigger top icon, dashboard links
- Style preview now updates immediately when picking a color via the
  colorpicker widget. It sets the input value through jQuery's synthetic
  trigger(), which a native addEventListener('change', ...) never sees -
  bound the listener through jQuery instead so both native and
  colorpicker-driven changes refresh the preview.
- Icon-above-QR max height raised from 25% to 62.5% of QR height (~2.5x
  bigger per feedback); the existing 60%-width cap now becomes the
  practical limit for most icons. Verified generated QR still decodes.
- Dashboard's "Dynamic Qr codes" and "Static QR codes" info-boxes now link
  to their list pages. "Total qr codes"/"Total Scans" left as-is - no
  combined-list or scan-report page exists yet to link them to.
- Random-style button now has a "Randomize" label to match its row-mates
  (Load preset/Save as preset/Style preview), instead of an empty spacer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo3DiRRpmz2DXjD7Uzhc8u
2026-07-11 02:09:58 +02:00
40 changed files with 506 additions and 162 deletions
+60 -56
View File
@@ -1,65 +1,69 @@
<p align="center"><img src="https://www.giandonatoinverso.it/qrcode/dist/img/DynamicQRCode_Original.png"></p> <p align="center"><img src="src/dist/img/brand/logo.svg" alt="QRForge" width="320"></p>
**PHP Dynamic Qr code** is a script that allows the generation and saving of dynamic and static QR codes. It has a clean, responsive, and user-friendly design. It is based on [AdminLte](https://adminlte.io/), the "Best open source admin dashboard & control panel theme. Built on top of Bootstrap" and [Core PHP Admin Panel](https://github.com/chetans9/core-php-admin-panel), a simple Admin Panel written in core PHP that contains an implementation of general features you might need in your website admin panel like: record management (CRUD), secure authentication, pagination, filters. <p align="center"><strong>Self-hosted, open-source QR code generator.</strong></p>
[LIVE DEMO](https://qrcode.giandonatoinverso.dev/) **QRForge** creates and manages static and dynamic QR codes from a clean,
responsive control panel. It's a security-hardened, actively maintained fork
of the original [PHP Dynamic Qr code](https://github.com/giandonatoinverso/PHP-Dynamic-Qr-code)
project by Giandonato Inverso, built on [AdminLTE](https://adminlte.io/).
username: admin - **Try it free:** [qr.ensembia.com](https://qr.ensembia.com) - fully functional OSS test
instance, register your own account any time.
password: admin - **Commercial VIP edition** (self-service create-rights, logo-embedded QR codes):
[www.qrforge.eu](https://www.qrforge.eu).
[DOCUMENTATION](https://giandonatoinverso.it/qrcode/documentation) - **Self-host it yourself:** this repository, MIT-licensed.
# Features # Features
- **#1 Dynamic Qr code generator on GitHub with a database to store Qr codes** - Dynamic QR codes with a database-backed URL shortener
- Create unlimited Qr codes - Create, edit, delete, enable/disable the redirect
- Docker compose support - Download any time, bulk download/delete
- Control panel with 2 access levels - Batch-generate from a CSV file
- Multi-account - 16 static QR code types: Text, Email, Phone, SMS, WhatsApp, Skype, Location,
- Dashboard with advanced statistics on Qr codes created and on scans vCard, Event/calendar, Bookmark, WiFi (incl. WPA3), PayPal, Bitcoin, 2FA,
- Bulk download, bulk delete App Link (Android intent / universal links), Bluetooth
- Dynamic Qr code - QR code styling: 6 export formats, foreground/background color, 4 precision
- Create, modify, and delete Qr codes levels, 10 sizes, optional label text below the code (custom font + size),
- You can download your Qr codes when you want optional icon shown above the code, save/load your own style presets
- URL shortener with redirect - Address search (OpenStreetMap Nominatim) for Location QR codes
- Enable or disable the link redirect - Built-in QR scanner (camera or image upload, decodes entirely client-side)
- Static Qr code - Installable as a PWA
- Text QR Code - Role-based access: `super` (full access + user management), `admin`
- Email QR Code (scoped to their own codes and sub-users), `user` (read-only, with
- Phone QR Code optional per-account create rights and view toggles set by an admin)
- Sms QR Code - Dashboard with QR/scan statistics and a 7-day activity chart
- Whatsapp QR Code - CSRF protection, login rate limiting, session hardening, audit log
- Skype QR Code - Docker Compose setup, both a dev image and a production Nginx + PHP-FPM image
- Location QR Code
- Vcard QR Code
- Event/calendar QR Code
- Bookmark QR Code
- Wifi QR Code
- Paypal QR Code
- Bitcoin QR Code
- Customization of Qr codes
- 6 formats for images
- Foreground color
- Background color
- 4 levels of precision
- 10 sizes
- Responsive bootstrap-based design
- Easy to understand and expand code
- Full OOP with classes and well-documented
## What is included # What is included
- PHP files - PHP 8.4 application source
- .sql file with sample data - Database schema + migrations
- JS files - Docker Compose files (dev and production)
- CSS files - CSS/JS assets
- Docker compose file
## Setup with docker compose # Setup with Docker Compose
1. download docker-compose.yml file
2. Start docker stack 1. Clone this repository.
```bash 2. Copy `.env.example` to `.env` and set a real `DATABASE_PASSWORD` /
docker compose build --no-cache && docker compose up -d `MYSQL_ROOT_PASSWORD`.
``` 3. Start the stack:
3. Open your browser at http://localhost:80 and login with (username: superadmin, password: superadmin) ```bash
docker compose up -d --build
```
4. Open `http://localhost` and log in with `superadmin` / `superadmin`. You'll
be required to set a new password on first login.
For a production deployment behind a reverse proxy, use
`docker-compose.prod.yml` (Nginx + PHP-FPM) instead of the dev stack.
# Credits
- Originally forked from [PHP Dynamic Qr code](https://github.com/giandonatoinverso/PHP-Dynamic-Qr-code)
by Giandonato Inverso.
- QR code rendering powered by [chillerlan/php-qrcode](https://github.com/chillerlan/php-qrcode).
- Admin panel UI built on [AdminLTE](https://adminlte.io/).
# License
MIT - see [LICENSE](LICENSE).
+101
View File
@@ -0,0 +1,101 @@
<?php
require_once 'includes/bootstrap.php';
require_once BASE_PATH . '/includes/auth_validate.php';
?>
<!DOCTYPE html>
<html lang="en">
<title>About - QRForge</title>
<head>
<?php include './includes/head.php'; ?>
</head>
<body class="hold-transition sidebar-mini layout-fixed layout-navbar-fixed layout-footer-fixed">
<div class="wrapper">
<!-- Navbar -->
<?php include './includes/navbar.php'; ?>
<!-- /.navbar -->
<!-- Main Sidebar Container -->
<?php include './includes/sidebar.php'; ?>
<!-- /.Main Sidebar Container -->
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0 text-dark">About</h1>
</div><!-- /.col -->
</div><!-- /.row -->
</div><!-- /.container-fluid -->
</div>
<!-- /.content-header -->
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<div class="card card-primary">
<div class="card-body text-center">
<img src="dist/img/brand/logo-stacked.svg" alt="QRForge" style="max-width: 220px; margin: 20px 0;">
<p class="text-muted">Self-hosted static and dynamic QR code generator. Version 3.0.</p>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">Commercial version</h3>
</div>
<div class="card-body">
<p>
This is the free, open-source (MIT) edition of QRForge. It runs unmodified
as a live, fully functional try-out at
<a href="https://qr.ensembia.com" target="_blank">qr.ensembia.com</a> -
register a free account there any time.
</p>
<p>
The commercial VIP edition (paid create-rights and logo-embedded QR codes)
is a separate product built on the same OSS core - see
<a href="https://www.qrforge.eu" target="_blank">www.qrforge.eu</a> for
pricing and details.
</p>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">Self-hosting</h3>
</div>
<div class="card-body">
<p>
Prefer to run your own instance? QRForge is MIT-licensed and available on
GitHub:
<a href="https://github.com/dillardblom/QR-app-selfhosted" target="_blank">github.com/dillardblom/QR-app-selfhosted</a>.
</p>
</div>
</div>
<div class="card">
<div class="card-header">
<h3 class="card-title">Credits</h3>
</div>
<div class="card-body">
<p>
Originally forked from
<a href="https://github.com/giandonatoinverso/PHP-Dynamic-Qr-code" target="_blank">PHP Qrcode Generator by Giandonato Inverso</a>.
</p>
<p>
QR code rendering is powered by the
<a href="https://github.com/chillerlan/php-qrcode" target="_blank">chillerlan/php-qrcode</a>
library.
</p>
</div>
</div>
</div><!--/. container-fluid -->
</section><!-- /.content -->
</div><!-- /.content-wrapper -->
<!-- Footer and scripts -->
<?php include './includes/footer.php'; ?>
</body>
</html>
+1 -1
View File
@@ -99,7 +99,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qrcode Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>
+2 -2
View File
@@ -47,13 +47,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Change password - Qrcode Generator</title> <title>Change password - QRForge</title>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
<body class="login-page" style="min-height: 512.391px;"> <body class="login-page" style="min-height: 512.391px;">
<div class="login-box"> <div class="login-box">
<div class="login-logo"> <div class="login-logo">
<img src="dist/img/DynamicQRCode_Original.png" style="width: 95%; height: 95%"> <img src="dist/img/brand/logo.svg" alt="QRForge" style="max-width: 260px;">
</div> </div>
<div class="card"> <div class="card">
+17
View File
@@ -6,4 +6,21 @@
#err-msg { #err-msg {
display: none; display: none;
color: red; color: red;
}
/* List-page qr code thumbnails: fixed box, but object-fit:contain instead of
width/height attrs so taller images (e.g. icon-above-qr) don't get squashed. */
.qr-thumb-link {
display: inline-block;
padding: 0;
border: 0;
background: none;
cursor: pointer;
}
.qr-thumb-img {
width: 100px;
height: 100px;
object-fit: contain;
background: #fff;
border: 1px solid #dee2e6;
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

+11
View File
@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 151.74 151.74" role="img" aria-labelledby="qfi-title qfi-desc">
<title id="qfi-title">QRForge icon</title>
<desc id="qfi-desc">QR-block mark with outbound arrow tile.</desc>
<g transform="translate(-8.95,-2.57)">
<rect id="block-top-left" x="5.24" y="16.81" width="42.29" height="40.70" rx="2.5" fill="#334155" />
<rect id="block-mid" x="59.57" y="68.79" width="24.90" height="23.46" rx="2.5" fill="#334155" />
<rect id="block-bottom-right" x="96.08" y="103.32" width="40.59" height="31.68" rx="2.5" fill="#334155" />
<path id="block-bottom-left-L" d="M 5.24,71.29 Q 5.24,68.79 7.74,68.79 L 45.03,68.79 Q 47.53,68.79 47.53,71.29 L 47.53,103.32 Q 47.53,103.32 47.53,103.32 L 81.97,103.32 Q 84.47,103.32 84.47,105.82 L 84.47,132.50 Q 84.47,135.00 81.97,135.00 L 7.74,135.00 Q 5.24,135.00 5.24,132.50 Z" fill="#334155" />
<path id="arrow-tile" d="M 105.68,6.94 Q 104.67,5.88 106.13,5.88 L 145.89,5.88 Q 148.39,5.88 148.39,8.38 L 148.39,44.14 Q 148.39,46.64 146.42,45.11 L 133.00,34.67 Q 133.00,34.67 133.00,34.67 L 112.50,56.87 Q 112.50,56.87 112.50,56.87 L 134.08,56.87 Q 136.58,56.87 136.58,59.37 L 136.58,89.50 Q 136.58,92.00 134.08,92.00 L 98.63,92.00 Q 96.13,92.00 96.13,89.50 L 96.13,56.87 Q 96.13,56.87 96.13,56.87 L 62.10,56.87 Q 59.60,56.87 59.60,54.37 L 59.60,19.60 Q 59.60,17.10 62.10,17.10 L 93.63,17.10 Q 96.13,17.10 96.13,19.60 L 96.13,41.00 Q 96.13,41.00 96.13,41.00 L 97.00,42.17 Q 97.00,42.17 97.00,42.17 L 117.19,22.73 Q 118.99,21.00 117.27,19.18 L 107.68,9.06 Q 106.68,8.00 105.68,6.94 Z" fill="#2563EB" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+11
View File
@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 151.74 151.74" role="img" aria-labelledby="qfi-title qfi-desc">
<title id="qfi-title">QRForge icon</title>
<desc id="qfi-desc">QR-block mark with outbound arrow tile.</desc>
<g transform="translate(-8.95,-2.57)">
<rect id="block-top-left" x="5.24" y="16.81" width="42.29" height="40.70" rx="2.5" fill="#FFFFFF" />
<rect id="block-mid" x="59.57" y="68.79" width="24.90" height="23.46" rx="2.5" fill="#FFFFFF" />
<rect id="block-bottom-right" x="96.08" y="103.32" width="40.59" height="31.68" rx="2.5" fill="#FFFFFF" />
<path id="block-bottom-left-L" d="M 5.24,71.29 Q 5.24,68.79 7.74,68.79 L 45.03,68.79 Q 47.53,68.79 47.53,71.29 L 47.53,103.32 Q 47.53,103.32 47.53,103.32 L 81.97,103.32 Q 84.47,103.32 84.47,105.82 L 84.47,132.50 Q 84.47,135.00 81.97,135.00 L 7.74,135.00 Q 5.24,135.00 5.24,132.50 Z" fill="#FFFFFF" />
<path id="arrow-tile" d="M 105.68,6.94 Q 104.67,5.88 106.13,5.88 L 145.89,5.88 Q 148.39,5.88 148.39,8.38 L 148.39,44.14 Q 148.39,46.64 146.42,45.11 L 133.00,34.67 Q 133.00,34.67 133.00,34.67 L 112.50,56.87 Q 112.50,56.87 112.50,56.87 L 134.08,56.87 Q 136.58,56.87 136.58,59.37 L 136.58,89.50 Q 136.58,92.00 134.08,92.00 L 98.63,92.00 Q 96.13,92.00 96.13,89.50 L 96.13,56.87 Q 96.13,56.87 96.13,56.87 L 62.10,56.87 Q 59.60,56.87 59.60,54.37 L 59.60,19.60 Q 59.60,17.10 62.10,17.10 L 93.63,17.10 Q 96.13,17.10 96.13,19.60 L 96.13,41.00 Q 96.13,41.00 96.13,41.00 L 97.00,42.17 Q 97.00,42.17 97.00,42.17 L 117.19,22.73 Q 118.99,21.00 117.27,19.18 L 107.68,9.06 Q 106.68,8.00 105.68,6.94 Z" fill="#2563EB" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+11
View File
@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 151.74 151.74" role="img" aria-labelledby="qfi-title qfi-desc">
<title id="qfi-title">QRForge icon</title>
<desc id="qfi-desc">QR-block mark with outbound arrow tile.</desc>
<g transform="translate(-8.95,-2.57)">
<rect id="block-top-left" x="5.24" y="16.81" width="42.29" height="40.70" rx="2.5" fill="#334155" />
<rect id="block-mid" x="59.57" y="68.79" width="24.90" height="23.46" rx="2.5" fill="#334155" />
<rect id="block-bottom-right" x="96.08" y="103.32" width="40.59" height="31.68" rx="2.5" fill="#334155" />
<path id="block-bottom-left-L" d="M 5.24,71.29 Q 5.24,68.79 7.74,68.79 L 45.03,68.79 Q 47.53,68.79 47.53,71.29 L 47.53,103.32 Q 47.53,103.32 47.53,103.32 L 81.97,103.32 Q 84.47,103.32 84.47,105.82 L 84.47,132.50 Q 84.47,135.00 81.97,135.00 L 7.74,135.00 Q 5.24,135.00 5.24,132.50 Z" fill="#334155" />
<path id="arrow-tile" d="M 105.68,6.94 Q 104.67,5.88 106.13,5.88 L 145.89,5.88 Q 148.39,5.88 148.39,8.38 L 148.39,44.14 Q 148.39,46.64 146.42,45.11 L 133.00,34.67 Q 133.00,34.67 133.00,34.67 L 112.50,56.87 Q 112.50,56.87 112.50,56.87 L 134.08,56.87 Q 136.58,56.87 136.58,59.37 L 136.58,89.50 Q 136.58,92.00 134.08,92.00 L 98.63,92.00 Q 96.13,92.00 96.13,89.50 L 96.13,56.87 Q 96.13,56.87 96.13,56.87 L 62.10,56.87 Q 59.60,56.87 59.60,54.37 L 59.60,19.60 Q 59.60,17.10 62.10,17.10 L 93.63,17.10 Q 96.13,17.10 96.13,19.60 L 96.13,41.00 Q 96.13,41.00 96.13,41.00 L 97.00,42.17 Q 97.00,42.17 97.00,42.17 L 117.19,22.73 Q 118.99,21.00 117.27,19.18 L 107.68,9.06 Q 106.68,8.00 105.68,6.94 Z" fill="#2563EB" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+12
View File
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 236.20 246.50" role="img" aria-labelledby="qfs-title qfs-desc">
<title id="qfs-title">QRForge stacked logo</title>
<desc id="qfs-desc">Stacked QRForge logo.</desc>
<g transform="translate(33.28,14.75)">
<rect id="block-top-left" x="5.24" y="16.81" width="42.29" height="40.70" rx="2.5" fill="#334155" />
<rect id="block-mid" x="59.57" y="68.79" width="24.90" height="23.46" rx="2.5" fill="#334155" />
<rect id="block-bottom-right" x="96.08" y="103.32" width="40.59" height="31.68" rx="2.5" fill="#334155" />
<path id="block-bottom-left-L" d="M 5.24,71.29 Q 5.24,68.79 7.74,68.79 L 45.03,68.79 Q 47.53,68.79 47.53,71.29 L 47.53,103.32 Q 47.53,103.32 47.53,103.32 L 81.97,103.32 Q 84.47,103.32 84.47,105.82 L 84.47,132.50 Q 84.47,135.00 81.97,135.00 L 7.74,135.00 Q 5.24,135.00 5.24,132.50 Z" fill="#334155" />
<path id="arrow-tile" d="M 105.68,6.94 Q 104.67,5.88 106.13,5.88 L 145.89,5.88 Q 148.39,5.88 148.39,8.38 L 148.39,44.14 Q 148.39,46.64 146.42,45.11 L 133.00,34.67 Q 133.00,34.67 133.00,34.67 L 112.50,56.87 Q 112.50,56.87 112.50,56.87 L 134.08,56.87 Q 136.58,56.87 136.58,59.37 L 136.58,89.50 Q 136.58,92.00 134.08,92.00 L 98.63,92.00 Q 96.13,92.00 96.13,89.50 L 96.13,56.87 Q 96.13,56.87 96.13,56.87 L 62.10,56.87 Q 59.60,56.87 59.60,54.37 L 59.60,19.60 Q 59.60,17.10 62.10,17.10 L 93.63,17.10 Q 96.13,17.10 96.13,19.60 L 96.13,41.00 Q 96.13,41.00 96.13,41.00 L 97.00,42.17 Q 97.00,42.17 97.00,42.17 L 117.19,22.73 Q 118.99,21.00 117.27,19.18 L 107.68,9.06 Q 106.68,8.00 105.68,6.94 Z" fill="#2563EB" />
</g>
<text x="118.10" y="203.67" text-anchor="middle" font-family="Inter, Manrope, Geist, Arial, sans-serif" font-size="48.39" font-weight="700" letter-spacing="-3.43" fill="#334155">QRForge</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+12
View File
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="5.24 5.88 573.81 145.12" role="img" aria-labelledby="qf-title qf-desc">
<title id="qf-title">QRForge logo</title>
<desc id="qf-desc">QRForge wordmark with a QR-block mark and outbound arrow tile.</desc>
<g id="icon">
<rect id="block-top-left" x="5.24" y="16.81" width="42.29" height="40.70" rx="2.5" fill="#334155" />
<rect id="block-mid" x="59.57" y="68.79" width="24.90" height="23.46" rx="2.5" fill="#334155" />
<rect id="block-bottom-right" x="96.08" y="103.32" width="40.59" height="31.68" rx="2.5" fill="#334155" />
<path id="block-bottom-left-L" d="M 5.24,71.29 Q 5.24,68.79 7.74,68.79 L 45.03,68.79 Q 47.53,68.79 47.53,71.29 L 47.53,103.32 Q 47.53,103.32 47.53,103.32 L 81.97,103.32 Q 84.47,103.32 84.47,105.82 L 84.47,132.50 Q 84.47,135.00 81.97,135.00 L 7.74,135.00 Q 5.24,135.00 5.24,132.50 Z" fill="#334155" />
<path id="arrow-tile" d="M 105.68,6.94 Q 104.67,5.88 106.13,5.88 L 145.89,5.88 Q 148.39,5.88 148.39,8.38 L 148.39,44.14 Q 148.39,46.64 146.42,45.11 L 133.00,34.67 Q 133.00,34.67 133.00,34.67 L 112.50,56.87 Q 112.50,56.87 112.50,56.87 L 134.08,56.87 Q 136.58,56.87 136.58,59.37 L 136.58,89.50 Q 136.58,92.00 134.08,92.00 L 98.63,92.00 Q 96.13,92.00 96.13,89.50 L 96.13,56.87 Q 96.13,56.87 96.13,56.87 L 62.10,56.87 Q 59.60,56.87 59.60,54.37 L 59.60,19.60 Q 59.60,17.10 62.10,17.10 L 93.63,17.10 Q 96.13,17.10 96.13,19.60 L 96.13,41.00 Q 96.13,41.00 96.13,41.00 L 97.00,42.17 Q 97.00,42.17 97.00,42.17 L 117.19,22.73 Q 118.99,21.00 117.27,19.18 L 107.68,9.06 Q 106.68,8.00 105.68,6.94 Z" fill="#2563EB" />
</g>
<text id="wordmark" x="177" y="101" font-family="Inter, Manrope, Geist, Arial, sans-serif" font-size="103" font-weight="700" letter-spacing="-7.3" fill="#334155">QRForge</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

+69
View File
@@ -0,0 +1,69 @@
(function () {
document.addEventListener('DOMContentLoaded', function () {
var searchInput = document.getElementById('location_search');
var searchBtn = document.getElementById('location_search_btn');
var resultsBox = document.getElementById('location_search_results');
var latInput = document.getElementById('latitude');
var lngInput = document.getElementById('longitude');
if (!searchInput || !searchBtn || !resultsBox || !latInput || !lngInput) {
return;
}
function clearResults() {
resultsBox.innerHTML = '';
}
function doSearch() {
var query = searchInput.value.trim();
if (!query) {
return;
}
clearResults();
resultsBox.innerHTML = '<div class="list-group-item">Searching...</div>';
fetch('https://nominatim.openstreetmap.org/search?format=json&limit=5&q=' + encodeURIComponent(query))
.then(function (response) { return response.json(); })
.then(function (results) {
clearResults();
if (!results.length) {
resultsBox.innerHTML = '<div class="list-group-item">No results found.</div>';
return;
}
results.forEach(function (place) {
var item = document.createElement('button');
item.type = 'button';
item.className = 'list-group-item list-group-item-action';
item.textContent = place.display_name;
item.addEventListener('click', function () {
latInput.value = place.lat;
lngInput.value = place.lon;
searchInput.value = place.display_name;
clearResults();
});
resultsBox.appendChild(item);
});
})
.catch(function () {
resultsBox.innerHTML = '<div class="list-group-item text-danger">Search failed (network error).</div>';
});
}
searchBtn.addEventListener('click', doSearch);
searchInput.addEventListener('keydown', function (e) {
if (e.key === 'Enter') {
e.preventDefault();
doSearch();
}
});
document.addEventListener('click', function (e) {
if (e.target !== searchInput && !resultsBox.contains(e.target)) {
clearResults();
}
});
});
})();
+12 -3
View File
@@ -95,9 +95,18 @@
}); });
document.querySelectorAll('#foreground, #background').forEach(function (input) { document.querySelectorAll('#foreground, #background').forEach(function (input) {
input.addEventListener('change', function () { // bootstrap-colorpicker sets the value and fires 'change' via jQuery's
updateStylePreview(scopeOf(input)); // synthetic .trigger(), which a native addEventListener never sees - so the
}); // preview only updates via jQuery's event binding, not the native one below.
if (window.jQuery) {
jQuery(input).on('change', function () {
updateStylePreview(scopeOf(input));
});
} else {
input.addEventListener('change', function () {
updateStylePreview(scopeOf(input));
});
}
}); });
document.querySelectorAll('select[name="level"]').forEach(function (select) { document.querySelectorAll('select[name="level"]').forEach(function (select) {
+1 -1
View File
@@ -60,7 +60,7 @@ if($_SERVER["REQUEST_METHOD"] === "POST" && !isset($_POST["edit"]) && !isset($_P
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qrcode Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>
+1 -1
View File
@@ -29,7 +29,7 @@ $total_pages = $db->totalPages;
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qrcode Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+13 -14
View File
@@ -117,15 +117,7 @@
</div> </div>
<div class="col-sm-12 mb-2"> <div class="col-sm-12 mb-2">
<div class="row"> <div class="row">
<div class="col-sm-4">
<div class="form-group">
<label for="filename">Filename *</label>
<input type="text" name="filename" value="" placeholder="My first Qrcode" class="form-control error" required="required" id="filename">
</div>
</div>
<div class="col-6 col-md-1"> <div class="col-6 col-md-1">
<label for="format">Format *</label> <label for="format">Format *</label>
<select name="format" class="form-control" required="required"> <select name="format" class="form-control" required="required">
@@ -177,13 +169,20 @@
</div> </div>
</div> </div>
<?php if($_SESSION['type'] === 'super') { ?>
<div class="col-sm-12 mb-2"> <div class="col-sm-12 mb-2">
<div class="row"> <div class="row">
<div class="col-sm-4">
<div class="form-group">
<label for="filename">Filename *</label>
<input type="text" name="filename" value="" placeholder="My first Qrcode" class="form-control error" required="required" id="filename">
</div>
</div>
<?php if ($_SESSION['type'] === 'super') { ?>
<div class="col-sm-4"> <div class="col-sm-4">
<div class="form-group"> <div class="form-group">
<label for="id_owner">Owner *</label> <label for="id_owner">Owner *</label>
<select name="id_owner" class="form-control"> <select name="id_owner" id="id_owner" class="form-control">
<option value="">All (shared with every admin)</option> <option value="">All (shared with every admin)</option>
<?php <?php
@@ -199,9 +198,9 @@
</select> </select>
</div> </div>
</div> </div>
<?php } else { ?>
<input type="hidden" name="id_owner" value="<?php echo $_SESSION["user_id"];?>"/>
<?php } ?>
</div> </div>
</div> </div>
<?php } else { ?>
<input type="hidden" name="id_owner" value="<?php echo $_SESSION["user_id"];?>"/>
<?php } ?>
</fieldset> </fieldset>
+33 -34
View File
@@ -58,7 +58,7 @@ if (QRCODE_GENERATOR === "internal-chillerlan.qrcode") {
<div class="col-sm-12 mb-2"> <div class="col-sm-12 mb-2">
<div class="row"> <div class="row">
<div class="col-6 col-md-3"> <div class="col-6 col-md-3">
<label>&nbsp;</label> <label>Randomize</label>
<button type="button" id="random_style_btn" class="btn btn-outline-secondary btn-block"> <button type="button" id="random_style_btn" class="btn btn-outline-secondary btn-block">
<i class="fa fa-dice"></i> Random style <i class="fa fa-dice"></i> Random style
</button> </button>
@@ -113,15 +113,7 @@ if (QRCODE_GENERATOR === "internal-chillerlan.qrcode") {
--> -->
<div class="col-sm-12 mb-2"> <div class="col-sm-12 mb-2">
<div class="row"> <div class="row">
<div class="col-sm-4">
<div class="form-group">
<label for="filename">Filename *</label>
<input type="text" name="filename" value="" placeholder="My first Qrcode" class="form-control error" required="required" id = "filename">
</div>
</div>
<div class="col-6 col-md-1"> <div class="col-6 col-md-1">
<label for="format">Format</label> <label for="format">Format</label>
<select name="format" class="form-control"> <select name="format" class="form-control">
@@ -178,31 +170,38 @@ if (QRCODE_GENERATOR === "internal-chillerlan.qrcode") {
</div> </div>
</div> </div>
<?php if($_SESSION['type'] === 'super') { ?> <div class="col-sm-12 mb-2">
<div class="col-sm-12 mb-2"> <div class="row">
<div class="row"> <div class="col-sm-4">
<div class="col-sm-4"> <div class="form-group">
<div class="form-group"> <label for="filename">Filename *</label>
<label for="id_owner">Owner *</label> <input type="text" name="filename" value="" placeholder="My first Qrcode" class="form-control error" required="required" id="filename">
<select name="id_owner" class="form-control">
<option value="">All (shared with every admin)</option>
<?php
require_once BASE_PATH . '/lib/Users/Users.php';
$users_instance = new Users();
$users = $users_instance->getAllUsers();
foreach ($users as $user) {
$is_self = (int) $user["id"] === (int) $_SESSION["user_id"];
?>
<option value="<?php echo $user["id"];?>" <?php echo $is_self ? 'selected' : ''; ?>><?php echo $user["username"];?></option>
<?php } ?>
</select>
</div>
</div> </div>
</div> </div>
<?php if ($_SESSION['type'] === 'super') { ?>
<div class="col-sm-4">
<div class="form-group">
<label for="id_owner">Owner *</label>
<select name="id_owner" id="id_owner" class="form-control">
<option value="">All (shared with every admin)</option>
<?php
require_once BASE_PATH . '/lib/Users/Users.php';
$users_instance = new Users();
$users = $users_instance->getAllUsers();
foreach ($users as $user) {
$is_self = (int) $user["id"] === (int) $_SESSION["user_id"];
?>
<option value="<?php echo $user["id"];?>" <?php echo $is_self ? 'selected' : ''; ?>><?php echo $user["username"];?></option>
<?php } ?>
</select>
</div>
</div>
<?php } else { ?>
<input type="hidden" name="id_owner" value="<?php echo $_SESSION["user_id"];?>"/>
<?php } ?>
</div> </div>
<?php } else { ?> </div>
<input type="hidden" name="id_owner" value="<?php echo $_SESSION["user_id"];?>"/>
<?php } ?>
<br> <br>
+25 -10
View File
@@ -2,26 +2,41 @@
<?php echo csrf_field(); ?> <?php echo csrf_field(); ?>
<?php include BASE_PATH.'/forms/qrcode_options.php'; ?> <?php include BASE_PATH.'/forms/qrcode_options.php'; ?>
<!-- Input forms --> <!-- Input forms -->
<div class="col-sm-4"> <div class="col-sm-8">
<div class="form-group"> <div class="form-group" style="position: relative;">
<label>Latitude *</label> <label for="location_search">Search address</label>
<input type="text" name="latitude" value="" placeholder="40.7127753" class="form-control"> <div class="input-group">
<input type="text" id="location_search" class="form-control" placeholder="Search for an address or place...">
<div class="input-group-append">
<button type="button" id="location_search_btn" class="btn btn-outline-secondary"><i class="fa fa-search"></i></button>
</div>
</div>
<div id="location_search_results" class="list-group" style="position:absolute;z-index:1000;width:100%;"></div>
<small class="form-text text-muted">Looks up coordinates via OpenStreetMap Nominatim (your search leaves this server and goes to nominatim.openstreetmap.org). Or enter coordinates directly below.</small>
</div> </div>
</div> </div>
<div class="col-sm-4"> <div class="col-sm-4">
<div class="form-group"> <div class="form-group">
<label>Longitude *</label> <label for="latitude">Latitude *</label>
<input type="text" name="longitude" value="" placeholder="-74.0059728" class="form-control"> <input type="text" name="latitude" id="latitude" value="" placeholder="40.7127753" class="form-control">
</div> </div>
</div> </div>
<div class="col-sm-4">
<div class="form-group">
<label for="longitude">Longitude *</label>
<input type="text" name="longitude" id="longitude" value="" placeholder="-74.0059728" class="form-control">
</div>
</div>
<div class="col-sm-12 mb-2"> <div class="col-sm-12 mb-2">
<div class="row"> <div class="row">
<div class="col-6 col-md-3"> <div class="col-6 col-md-3">
<button type="submit" class="btn btn-primary">Submit</button> <button type="submit" class="btn btn-primary">Submit</button>
</div> </div>
</div> </div>
</div> </div>
<script src="dist/js/location-search.js"></script>
</form> </form>
+31 -1
View File
@@ -70,7 +70,11 @@
<td><?php echo htmlspecialchars($row['identifier']); ?></td> <td><?php echo htmlspecialchars($row['identifier']); ?></td>
<td><?php echo htmlspecialchars($row['link']); ?></td> <td><?php echo htmlspecialchars($row['link']); ?></td>
<td> <td>
<?php echo '<img src="qrcode_image.php?type=dynamic&id='.$row['id'].'" width="100" height="100">'; ?> <a href="#" class="qr-thumb-link" data-toggle="modal" data-target="#preview-modal"
data-qr-src="qrcode_image.php?type=dynamic&id=<?php echo $row['id']; ?>"
data-qr-name="<?php echo htmlspecialchars($row['filename']); ?>">
<img src="qrcode_image.php?type=dynamic&id=<?php echo $row['id']; ?>" class="qr-thumb-img" alt="QR code for <?php echo htmlspecialchars($row['filename']); ?>">
</a>
</td> </td>
<td><?php echo htmlspecialchars($row['scan']); ?></td> <td><?php echo htmlspecialchars($row['scan']); ?></td>
<td><?php echo htmlspecialchars($row['state']); ?></td> <td><?php echo htmlspecialchars($row['state']); ?></td>
@@ -135,6 +139,32 @@
<!-- /.Delete Confirmation Modal --> <!-- /.Delete Confirmation Modal -->
<?php endif; ?> <?php endif; ?>
<!-- Qr Code Preview Modal -->
<div class="modal fade" id="preview-modal" role="dialog">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="preview-modal-title">QR code preview</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body text-center">
<img id="preview-modal-img" src="" alt="" style="max-width:100%;max-height:70vh;">
</div>
</div>
</div>
</div>
<!-- /.Qr Code Preview Modal -->
<script>
document.querySelectorAll('.qr-thumb-link').forEach(function (link) {
link.addEventListener('click', function (e) {
e.preventDefault();
document.getElementById('preview-modal-img').src = link.getAttribute('data-qr-src');
document.getElementById('preview-modal-title').textContent = link.getAttribute('data-qr-name');
});
});
</script>
<script> <script>
const deleteButtons = document.querySelectorAll('.delete_btn'); const deleteButtons = document.querySelectorAll('.delete_btn');
+31 -1
View File
@@ -68,7 +68,11 @@
<td><?php echo htmlspecialchars($row['type']); ?></td> <td><?php echo htmlspecialchars($row['type']); ?></td>
<td><?php echo htmlspecialchars_decode($row['content']); ?></td> <td><?php echo htmlspecialchars_decode($row['content']); ?></td>
<td> <td>
<?php echo '<img src="qrcode_image.php?type=static&id='.$row['id'].'" width="100" height="100">'; ?> <a href="#" class="qr-thumb-link" data-toggle="modal" data-target="#preview-modal"
data-qr-src="qrcode_image.php?type=static&id=<?php echo $row['id']; ?>"
data-qr-name="<?php echo htmlspecialchars($row['filename']); ?>">
<img src="qrcode_image.php?type=static&id=<?php echo $row['id']; ?>" class="qr-thumb-img" alt="QR code for <?php echo htmlspecialchars($row['filename']); ?>">
</a>
</td> </td>
<td> <td>
<?php if (!$is_readonly_user): ?> <?php if (!$is_readonly_user): ?>
@@ -131,6 +135,32 @@
<!-- /.Delete Confirmation Modal --> <!-- /.Delete Confirmation Modal -->
<?php endif; ?> <?php endif; ?>
<!-- Qr Code Preview Modal -->
<div class="modal fade" id="preview-modal" role="dialog">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="preview-modal-title">QR code preview</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body text-center">
<img id="preview-modal-img" src="" alt="" style="max-width:100%;max-height:70vh;">
</div>
</div>
</div>
</div>
<!-- /.Qr Code Preview Modal -->
<script>
document.querySelectorAll('.qr-thumb-link').forEach(function (link) {
link.addEventListener('click', function (e) {
e.preventDefault();
document.getElementById('preview-modal-img').src = link.getAttribute('data-qr-src');
document.getElementById('preview-modal-title').textContent = link.getAttribute('data-qr-name');
});
});
</script>
<script> <script>
const deleteButtons = document.querySelectorAll('.delete_btn'); const deleteButtons = document.querySelectorAll('.delete_btn');
+3 -2
View File
@@ -6,9 +6,10 @@
<!-- Main Footer --> <!-- Main Footer -->
<footer class="main-footer text-sm"> <footer class="main-footer text-sm">
<strong><a href="https://github.com/giandonatoinverso/PHP-Dynamic-Qr-code" target="_blank">PHP Qrcode Generator</a> by </strong> Giandonato Inverso <strong><a href="https://www.qrforge.eu" target="_blank">QRForge</a></strong> -
<a href="./about.php">About</a> / credits
<div class="float-right d-none d-sm-inline-block"> <div class="float-right d-none d-sm-inline-block">
<b>Version</b> 2.3.0 <b>Version</b> 3.0
</div> </div>
</footer> </footer>
</div> </div>
+5 -2
View File
@@ -2,9 +2,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge"> <meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="csrf-token" content="<?php echo csrf_token(); ?>"> <meta name="csrf-token" content="<?php echo csrf_token(); ?>">
<meta name="theme-color" content="#007bff"> <meta name="theme-color" content="#2563EB">
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="dist/img/icon-192.png"> <link rel="icon" href="dist/img/brand/favicon.svg" type="image/svg+xml">
<link rel="icon" href="dist/img/brand/favicon-32.png" sizes="32x32" type="image/png">
<link rel="icon" href="dist/img/brand/favicon-16.png" sizes="16x16" type="image/png">
<link rel="apple-touch-icon" href="dist/img/brand/apple-touch-icon.png">
<!-- Font Awesome Icons --> <!-- Font Awesome Icons -->
<link rel="stylesheet" href="plugins/fontawesome-free/css/all.min.css"> <link rel="stylesheet" href="plugins/fontawesome-free/css/all.min.css">
+13 -7
View File
@@ -2,9 +2,9 @@
<aside class="main-sidebar sidebar-dark-primary elevation-4"> <aside class="main-sidebar sidebar-dark-primary elevation-4">
<!-- Brand Logo --> <!-- Brand Logo -->
<a href="./index.php" class="brand-link"> <a href="./index.php" class="brand-link">
<img src="dist/img/Symbol_WhiteBlue.png" alt="Logo" class="brand-image" <img src="dist/img/brand/icon-inverse.svg" alt="QRForge" class="brand-image"
style="opacity: .8"> style="opacity: .8">
<span class="brand-text font-weight-light">Qrcode Generator</span> <span class="brand-text font-weight-light">QRForge</span>
</a> </a>
<!-- Sidebar --> <!-- Sidebar -->
@@ -53,20 +53,20 @@
<ul class="nav nav-treeview"> <ul class="nav nav-treeview">
<li class="nav-item"> <li class="nav-item">
<a href="./dynamic_qrcodes.php" <?php echo ((substr(CURRENT_PAGE, 0, 19) == 'dynamic_qrcodes.php')) ? ' class="nav-link active"' : ' class="nav-link"'; ?>> <a href="./dynamic_qrcodes.php" <?php echo ((substr(CURRENT_PAGE, 0, 19) == 'dynamic_qrcodes.php')) ? ' class="nav-link active"' : ' class="nav-link"'; ?>>
<i class="far fa-circle nav-icon"></i> <i class="fas fa-angle-right nav-icon"></i>
<p>List all</p> <p>List all</p>
</a> </a>
</li> </li>
<?php if ($_SESSION['type'] !== 'user'): ?> <?php if ($_SESSION['type'] !== 'user'): ?>
<li class="nav-item"> <li class="nav-item">
<a href="./dynamic_qrcode.php" <?php echo (CURRENT_PAGE == 'dynamic_qrcode.php') ? ' class="nav-link active"' : ' class="nav-link"'; ?>> <a href="./dynamic_qrcode.php" <?php echo (CURRENT_PAGE == 'dynamic_qrcode.php') ? ' class="nav-link active"' : ' class="nav-link"'; ?>>
<i class="far fa-circle nav-icon"></i> <i class="fas fa-angle-right nav-icon"></i>
<p>Add new</p> <p>Add new</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="./batch_qrcode.php" <?php echo (CURRENT_PAGE == 'batch_qrcode.php') ? ' class="nav-link active"' : ' class="nav-link"'; ?>> <a href="./batch_qrcode.php" <?php echo (CURRENT_PAGE == 'batch_qrcode.php') ? ' class="nav-link active"' : ' class="nav-link"'; ?>>
<i class="far fa-circle nav-icon"></i> <i class="fas fa-angle-right nav-icon"></i>
<p>Batch create (CSV)</p> <p>Batch create (CSV)</p>
</a> </a>
</li> </li>
@@ -86,14 +86,14 @@
<ul class="nav nav-treeview"> <ul class="nav nav-treeview">
<li class="nav-item"> <li class="nav-item">
<a href="./static_qrcodes.php" <?php echo ((substr(CURRENT_PAGE, 0, 18) == 'static_qrcodes.php')) ? ' class="nav-link active"' : ' class="nav-link"'; ?>> <a href="./static_qrcodes.php" <?php echo ((substr(CURRENT_PAGE, 0, 18) == 'static_qrcodes.php')) ? ' class="nav-link active"' : ' class="nav-link"'; ?>>
<i class="far fa-circle nav-icon"></i> <i class="fas fa-angle-right nav-icon"></i>
<p>List all</p> <p>List all</p>
</a> </a>
</li> </li>
<?php if ($_SESSION['type'] !== 'user'): ?> <?php if ($_SESSION['type'] !== 'user'): ?>
<li class="nav-item"> <li class="nav-item">
<a href="./static_qrcode.php" <?php echo (CURRENT_PAGE == 'static_qrcode.php') ? ' class="nav-link active"' : ' class="nav-link"'; ?>> <a href="./static_qrcode.php" <?php echo (CURRENT_PAGE == 'static_qrcode.php') ? ' class="nav-link active"' : ' class="nav-link"'; ?>>
<i class="far fa-circle nav-icon"></i> <i class="fas fa-angle-right nav-icon"></i>
<p>Add new</p> <p>Add new</p>
</a> </a>
</li> </li>
@@ -109,6 +109,12 @@
</a> </a>
</li> </li>
<?php endif; ?> <?php endif; ?>
<li class="nav-item">
<a href="./about.php" <?php echo (CURRENT_PAGE == 'about.php') ? ' class="nav-link active"' : ' class="nav-link"'; ?>>
<i class="fas fa-info-circle nav-icon"></i>
<p>About</p>
</a>
</li>
</ul> </ul>
</nav> </nav>
<!-- /.sidebar-menu --> <!-- /.sidebar-menu -->
+19 -15
View File
@@ -70,7 +70,7 @@ foreach ($createdQrcode_static as $row) {
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qr Code Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>
@@ -120,29 +120,33 @@ foreach ($createdQrcode_static as $row) {
</div><!-- /.col --> </div><!-- /.col -->
<div class="col-12 col-sm-6 col-md-3"> <div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3 bg-success"> <a href="dynamic_qrcodes.php" class="d-block">
<span class="info-box-icon"><i class="fa fa-qrcode"></i></span> <div class="info-box mb-3 bg-success">
<span class="info-box-icon"><i class="fa fa-qrcode"></i></span>
<div class="info-box-content"> <div class="info-box-content">
<span class="info-box-text">Dynamic Qr codes</span> <span class="info-box-text">Dynamic Qr codes</span>
<span class="info-box-number"><?php echo $numQrcode_dynamic; ?></span> <span class="info-box-number"><?php echo $numQrcode_dynamic; ?></span>
</div><!-- /.info-box-content --> </div><!-- /.info-box-content -->
</div> </div>
</a>
</div><!-- /.col --> </div><!-- /.col -->
<!-- fix for small devices only --> <!-- fix for small devices only -->
<div class="clearfix hidden-md-up"></div> <div class="clearfix hidden-md-up"></div>
<div class="col-12 col-sm-6 col-md-3"> <div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3 bg-danger"> <a href="static_qrcodes.php" class="d-block">
<span class="info-box-icon"><i class="fa fa-qrcode"></i></span> <div class="info-box mb-3 bg-danger">
<span class="info-box-icon"><i class="fa fa-qrcode"></i></span>
<div class="info-box-content"> <div class="info-box-content">
<span class="info-box-text">Static QR codes</span> <span class="info-box-text">Static QR codes</span>
<span class="info-box-number"><?php echo $numQrcode_static; ?></span> <span class="info-box-number"><?php echo $numQrcode_static; ?></span>
</div><!-- /.info-box-content --> </div><!-- /.info-box-content -->
</div> </div>
</a>
</div><!-- /.col --> </div><!-- /.col -->
<div class="col-12 col-sm-6 col-md-3"> <div class="col-12 col-sm-6 col-md-3">
+1 -1
View File
@@ -174,7 +174,7 @@ class Qrcode {
$iconWidth = imagesx($icon); $iconWidth = imagesx($icon);
$iconHeight = imagesy($icon); $iconHeight = imagesy($icon);
$maxIconHeight = (int) ($height * 0.25); $maxIconHeight = (int) ($height * 0.625);
$scale = min($maxIconHeight / $iconHeight, ($width * 0.6) / $iconWidth, 1); $scale = min($maxIconHeight / $iconHeight, ($width * 0.6) / $iconWidth, 1);
$targetWidth = max(1, (int) ($iconWidth * $scale)); $targetWidth = max(1, (int) ($iconWidth * $scale));
$targetHeight = max(1, (int) ($iconHeight * $scale)); $targetHeight = max(1, (int) ($iconHeight * $scale));
+1 -1
View File
@@ -159,7 +159,7 @@ class Qrcode {
$iconWidth = imagesx($icon); $iconWidth = imagesx($icon);
$iconHeight = imagesy($icon); $iconHeight = imagesy($icon);
$maxIconHeight = (int) ($height * 0.25); $maxIconHeight = (int) ($height * 0.625);
$scale = min($maxIconHeight / $iconHeight, ($width * 0.6) / $iconWidth, 1); $scale = min($maxIconHeight / $iconHeight, ($width * 0.6) / $iconWidth, 1);
$targetWidth = max(1, (int) ($iconWidth * $scale)); $targetWidth = max(1, (int) ($iconWidth * $scale));
$targetHeight = max(1, (int) ($iconHeight * $scale)); $targetHeight = max(1, (int) ($iconHeight * $scale));
+2 -2
View File
@@ -68,13 +68,13 @@ if (isset($_COOKIE['series_id']) && isset($_COOKIE['remember_token']))
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Login - Qrcode Generator</title> <title>Login - QRForge</title>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
<body class="login-page" style="min-height: 512.391px;"> <body class="login-page" style="min-height: 512.391px;">
<div class="login-box"> <div class="login-box">
<div class="login-logo"> <div class="login-logo">
<img src="dist/img/DynamicQRCode_Original.png" style="width: 95%; height: 95%"> <img src="dist/img/brand/logo.svg" alt="QRForge" style="max-width: 260px;">
</div> </div>
<div class="card"> <div class="card">
+3 -3
View File
@@ -1,12 +1,12 @@
{ {
"name": "Qrcode Generator", "name": "QRForge",
"short_name": "QRcode", "short_name": "QRForge",
"description": "Self-hosted static and dynamic qr code generator", "description": "Self-hosted static and dynamic qr code generator",
"start_url": "index.php", "start_url": "index.php",
"scope": "./", "scope": "./",
"display": "standalone", "display": "standalone",
"background_color": "#ffffff", "background_color": "#ffffff",
"theme_color": "#007bff", "theme_color": "#2563EB",
"icons": [ "icons": [
{ "src": "dist/img/icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "dist/img/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "dist/img/icon-512.png", "sizes": "512x512", "type": "image/png" } { "src": "dist/img/icon-512.png", "sizes": "512x512", "type": "image/png" }
+1 -1
View File
@@ -4,7 +4,7 @@ require_once BASE_PATH . '/includes/auth_validate.php';
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qrcode Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>
+1 -1
View File
@@ -96,7 +96,7 @@ if($_SERVER["REQUEST_METHOD"] === "POST" && !isset($_POST["edit"]) && !isset($_P
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qrcode Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>
+1 -1
View File
@@ -29,7 +29,7 @@ $total_pages = $db->totalPages;
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qrcode Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>
+1 -1
View File
@@ -51,7 +51,7 @@ if($_SERVER["REQUEST_METHOD"] === "POST" && !isset($_POST["edit"])) {
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qrcode Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>
+1 -1
View File
@@ -27,7 +27,7 @@ $total_pages = $db->totalPages;
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<title>Qrcode Generator</title> <title>QRForge</title>
<head> <head>
<?php include './includes/head.php'; ?> <?php include './includes/head.php'; ?>
</head> </head>