QR CODE GENERATOR

This commit is contained in:
Myx
2024-10-25 23:40:27 +02:00
parent 9f6e496294
commit af343770c1
18 changed files with 1654 additions and 45 deletions

158
tools/package-lock.json generated
View File

@@ -20,8 +20,9 @@
"@ng-icons/core": "^29.5.1",
"@ng-icons/css.gg": "^29.5.1",
"@ng-icons/heroicons": "^29.5.1",
"angularx-qrcode": "^18.0.2",
"primeicons": "^7.0.0",
"primeng": "^18.0.0-beta.2",
"primeng": "^18.0.0-beta.3",
"rxjs": "~7.8.0",
"tailwindcss-primeui": "^0.3.4",
"tslib": "^2.3.0",
@@ -3271,20 +3272,20 @@
}
},
"node_modules/@primeuix/styled": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.0.6.tgz",
"integrity": "sha512-bOya+/7WzCeF8D4N0BgGNk3Xe4F4PLEGu7V+btRlUOoEbda2uhp4nqqj2fOdzSERmjEUkkYds8dIVgVM56w1NA==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.2.0.tgz",
"integrity": "sha512-3Q6bDrmwTW88tzJsFIFenC0VyXLj0+/wYw+TZnJ/4CCDfehR4WfTs4EZdpuFtYqvmbpJ6zWXAiwSCNdSYTZkyA==",
"dependencies": {
"@primeuix/utils": "^0.0.6"
"@primeuix/utils": "^0.2.0"
},
"engines": {
"node": ">=12.11.0"
}
},
"node_modules/@primeuix/utils": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@primeuix/utils/-/utils-0.0.6.tgz",
"integrity": "sha512-7RQ2/LkZpSbi08NAlfZfajqBtWFM2csimf+xk97EoQDhpouzzbHFwf6WFbAyniZC9aPGJ+m+2qgyLxvYzA0x3g==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@primeuix/utils/-/utils-0.2.0.tgz",
"integrity": "sha512-AaDIeRFlsbkVTk2s0mlEjnGSLi31X669NVwo+n+AVAnBdDiQznjipNTpHbOobVBtjOKZize74PChK6uoaSBRUw==",
"engines": {
"node": ">=12.11.0"
}
@@ -4176,6 +4177,18 @@
"ajv": "^8.8.2"
}
},
"node_modules/angularx-qrcode": {
"version": "18.0.2",
"resolved": "https://registry.npmjs.org/angularx-qrcode/-/angularx-qrcode-18.0.2.tgz",
"integrity": "sha512-G/VZ25t31c63T3g8zQ4JjZcHcXXoFXC7Y1GicSBHTloOHATZO5o1VoUGW+TsFLg0K41n/6X8hdgDhmyi5AeqLQ==",
"dependencies": {
"qrcode": "1.5.3",
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/core": "^18.1.0"
}
},
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@@ -4755,7 +4768,6 @@
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true,
"engines": {
"node": ">=6"
}
@@ -5501,6 +5513,14 @@
}
}
},
"node_modules/decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/default-gateway": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
@@ -5588,6 +5608,11 @@
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"peer": true
},
"node_modules/dijkstrajs": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -5716,6 +5741,11 @@
"node": ">= 4"
}
},
"node_modules/encode-utf8": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
"integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@@ -6332,7 +6362,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"dependencies": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
@@ -6505,7 +6534,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -7994,7 +8022,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"dependencies": {
"p-locate": "^4.1.0"
},
@@ -9183,7 +9210,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"dependencies": {
"p-try": "^2.0.0"
},
@@ -9198,7 +9224,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"dependencies": {
"p-limit": "^2.2.0"
},
@@ -9247,7 +9272,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"engines": {
"node": ">=6"
}
@@ -9385,7 +9409,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"engines": {
"node": ">=8"
}
@@ -9577,6 +9600,14 @@
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/pngjs": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/postcss": {
"version": "8.4.35",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
@@ -9831,11 +9862,11 @@
"integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw=="
},
"node_modules/primeng": {
"version": "18.0.0-beta.2",
"resolved": "https://registry.npmjs.org/primeng/-/primeng-18.0.0-beta.2.tgz",
"integrity": "sha512-zCC36qtQsruPObuB/awdxHX0KvuRXa0Ebew0jTGNwal8YpJenF6ytxB4UIn6BetnuCYDuRAXW5zklxveIgxXiw==",
"version": "18.0.0-beta.3",
"resolved": "https://registry.npmjs.org/primeng/-/primeng-18.0.0-beta.3.tgz",
"integrity": "sha512-nX2sxTHRiggoaDrgFsnAfIihVFvZR4RfpH9JwOy4BL7wQ8cG0SYvSf1E5TTorJOED9/nPwrtVGUoHrDUsiNX+A==",
"dependencies": {
"@primeuix/styled": "0.0.6",
"@primeuix/styled": "0.2.0",
"tslib": "^2.3.0"
},
"peerDependencies": {
@@ -9924,6 +9955,71 @@
"node": ">=0.9"
}
},
"node_modules/qrcode": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
"integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
"dependencies": {
"dijkstrajs": "^1.0.1",
"encode-utf8": "^1.0.3",
"pngjs": "^5.0.0",
"yargs": "^15.3.1"
},
"bin": {
"qrcode": "bin/qrcode"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/qrcode/node_modules/cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
}
},
"node_modules/qrcode/node_modules/y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
},
"node_modules/qrcode/node_modules/yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"dependencies": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/qrcode/node_modules/yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
@@ -10214,7 +10310,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -10228,6 +10323,11 @@
"node": ">=0.10.0"
}
},
"node_modules/require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
@@ -10748,6 +10848,11 @@
"node": ">= 0.8"
}
},
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -12721,6 +12826,11 @@
"which": "bin/which"
}
},
"node_modules/which-module": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
},
"node_modules/wildcard": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
@@ -12731,7 +12841,6 @@
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -12792,7 +12901,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -12807,7 +12915,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
@@ -12818,8 +12925,7 @@
"node_modules/wrap-ansi/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/wrappy": {
"version": "1.0.2",

View File

@@ -22,8 +22,9 @@
"@ng-icons/core": "^29.5.1",
"@ng-icons/css.gg": "^29.5.1",
"@ng-icons/heroicons": "^29.5.1",
"angularx-qrcode": "^18.0.2",
"primeicons": "^7.0.0",
"primeng": "^18.0.0-beta.2",
"primeng": "^18.0.0-beta.3",
"rxjs": "~7.8.0",
"tailwindcss-primeui": "^0.3.4",
"tslib": "^2.3.0",

View File

@@ -3,6 +3,10 @@
justify-content: center;
}
.darkmode {
background-color: #121212;
}
::ng-deep {
.p-panel {
border-radius: unset !important;

View File

@@ -1,9 +1,9 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { HeaderComponent } from './header/header.component';
import { PrimeNGConfig } from 'primeng/api';
import { Lara } from 'primeng/themes/lara';
import { FooterComponent } from './footer/footer.component';
import { Lara } from 'primeng/themes/lara';
@Component({
selector: 'app-root',
@@ -12,7 +12,7 @@ import { FooterComponent } from './footer/footer.component';
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
export class AppComponent implements OnInit{
title = 'tools';
constructor(private config: PrimeNGConfig) {
@@ -21,4 +21,8 @@ export class AppComponent {
darkModeSelector: '.darkmode'
});
}
ngOnInit(): void {
const element = document.querySelector('html');
element?.classList.toggle('darkmode');
}
}

View File

@@ -8,6 +8,7 @@ import { DdsToPngComponent } from '../tools/client-side/dds-to-png/dds-to-png.co
import { ImageConverterComponent } from '../tools/server-side/image-converter/image-converter.component';
import { WordCounterComponent } from '../tools/client-side/word-counter/word-counter.component';
import { ColorPickerComponent } from '../tools/client-side/color-picker/color-picker.component';
import { QrCodeGeneratorComponent } from '../tools/client-side/qr-code-generator/qr-code-generator.component';
export const routes: Routes = [
{
@@ -50,6 +51,11 @@ export const routes: Routes = [
pathMatch: 'full',
component: WordCounterComponent
},
{
path: 'qr-code-generator',
pathMatch: 'full',
component: QrCodeGeneratorComponent
},
{
path: 'color-picker',
pathMatch: 'full',

View File

@@ -1,5 +1,5 @@
<p-megamenu [model]="items">
<ng-template pTemplate="start">
<img [ngClass]="{'logotype': true, 'darkMode': !isDarkMode}" src="../../assets/logo-full-orange-beta.png" alt="logo" />
<img class="logotype" src="../../assets/logo-full-orange-beta-vectorized.svg" alt="Bytefy Logotype" />
</ng-template>
</p-megamenu>

View File

@@ -2,10 +2,6 @@
width: 140px;
}
.darkMode {
filter: invert(1);
}
::ng-deep .p-megamenu-col-12 {
flex-direction: row !important;
display: flex !important;

View File

@@ -95,6 +95,29 @@ export class HeaderComponent implements OnInit {
}
]
]
},
{
label: 'Generators',
icon: 'pi pi-box',
items: [
[
{
label: 'Generators',
items: [
{
label: 'QR Code Generator',
routerLink: 'qr-code-generator',
routerLinkActiveOptions: { exact: true }
},
{
label: 'Guid Generator',
routerLink: 'guid',
routerLinkActiveOptions: { exact: true }
}
]
}
]
]
}
]
}

View File

@@ -3,6 +3,7 @@
<p-tag *ngIf="isBeta" severity="warn" value="Beta"></p-tag>
</ng-template>
<textarea
pInputTextarea
(keyup)="onTopChange($event)"
[disabled]="topDisabled"
pTextarea

View File

@@ -1,10 +1,12 @@
* {
color: #fff;
}
.icon {
display: flex;
flex-direction: row;
justify-content: center;
padding: 5px;
background-color: var(--primary-contrast);
// background-color: var(--primary-contrast);
i {
transform: rotate(90deg);
@@ -36,7 +38,6 @@ textarea {
font-size: 16px;
resize: none;
background-color: var(--primary-contrast);
color: var(--text-color)
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 640 KiB

View File

@@ -3,11 +3,15 @@
body,
body .p-component
{
font-family: "Roboto Mono", monospace;
font-optical-sizing: auto;
font-weight: 304;
font-style: normal;
margin: 0px;
}
html {
background-color: #121212;
}
* {

View File

@@ -1,3 +1,7 @@
* {
color: #FFF;
}
.color-picker {
display: flex;
align-items: center;

View File

@@ -4,6 +4,7 @@
align-items: center;
margin-top: 20px;
width: 98vw;
color: #fff;
p-panel {
display: flex;

View File

@@ -0,0 +1,89 @@
<div class="card flex justify-center">
<p-panel header="QR Code Generator">
<ng-template pTemplate="header">
<p-tag *ngIf="isBeta" severity="warn" value="Beta"></p-tag>
</ng-template>
<div class="wrapper">
<p-message *ngIf="error.error" severity="error">{{error.message}}</p-message>
<qrcode
(qrCodeURL)="onCodeUrlChanged($event)"
[qrdata]="qrCodeData"
[allowEmptyString]="true"
[ariaLabel]="'QR Code image with the following content...'"
[cssClass]="'center'"
[colorDark]="colorCode"
[colorLight]="backgroundColorCode"
[elementType]="'canvas'"
[errorCorrectionLevel]="level"
[imageSrc]="innerQrCodeimage"
[imageHeight]="75"
[imageWidth]="75"
[margin]="4"
[scale]="1"
[title]="qrCodeData"
[width]="qrCodeSize"
></qrcode>
<p-toolbar>
<div class="p-toolbar-group-start">
<input type="file" style="display:none" #fileSelector (change)="onFileSelected($event)" />
<p-button icon="pi pi-print" class="mr-2 miniButtons" (click)="onPrintButtonClick()"/>
<p-button icon="pi pi-upload" class="miniButtons" type="file" (click)="fileSelector.click()"/>
</div>
<div class="p-toolbar-group-center" *ngIf="!isMobile">
<input type="text" pInputText formControlName="text" [value]="qrCodeData" (keyup)="onDataTextInputChanged($event)" />
<p-button [icon]="expandIcon" severity="info" (click)="onExpandButtonClick()" />
</div>
<div class="p-toolbar-group-end">
<a [href]="qrCodeImageUrl" download="qrcode" >
<p-button label="Save" icon="pi pi-download" class="button-size" />
</a>
</div>
<div class="p-toolbar-group-center" *ngIf="isMobile">
<input type="text" pInputText formControlName="text" [value]="qrCodeData" (keyup)="onDataTextInputChanged($event)" />
<p-button [icon]="expandIcon" severity="info" (click)="onExpandButtonClick()" />
</div>
</p-toolbar>
</div>
<textarea
*ngIf="extendedInput"
(keyup)="onDataTextInputChanged($event)"
[value]="qrCodeData"
pInputTextarea
[autoResize]="true"
[fluid]="true"
rows="5"
cols="30"
placeholder="Contents of QR Code"
></textarea>
<p-accordion [multiple]="true" [activeIndex]="activeTabs">
<p-accordionTab
header="More settings"
value="1"
>
<div class="vertical">
<p>Size of QR Code</p>
<input type="number" max="1000" pInputText autocomplete="off" placeholder="Size" value="300" (keyup)="onSizeInputChanged($event)" />
<p>Image in QR code</p>
<input pInputText autocomplete="off" placeholder="Image url" (keyup)="onImageLinkInputChanged($event)"/>
<p>Error correction level</p>
<p-selectbutton [options]="correctionLevel" optionLabel="level" (onChange)="onLevelSelected($event)">
<ng-template pTemplate="item" let-item>
<i>{{item.level}}</i>
</ng-template>
</p-selectbutton>
<p>Color</p>
<p-colorpicker [inline]="true" (onChange)="onColorChanged($event)"/>
<p>Background color</p>
<p-colorpicker [inline]="true" (onChange)="onBackgroundColorChanged($event)"/>
</div>
</p-accordionTab>
</p-accordion>
</p-panel>
</div>

View File

@@ -0,0 +1,103 @@
:host {
display: flex;
justify-content: center;
margin-top: 20px;
width: 96vw;
.miniButtons {
margin: 0px 4px;
}
.wrapper {
display: flex;
flex-direction: column;
background-color: #000000;
}
a.disabled {
pointer-events: none;
cursor: default;
}
.card {
display: flex;
flex-direction: column;
width: 1140px;
}
.center {
display: flex;
justify-content: center;
}
.p-toolbar-group-end, .p-toolbar-group-center, .p-toolbar-group-start {
width: 300px;
::ng-deep {
.p-button {
height: 39px !important;
}
}
}
.p-toolbar-group-end {
display: flex;
justify-content: flex-end;
}
.p-toolbar-group-center .p-inputtext {
width: calc(100% - 44px);
}
qrcode {
display: flex;
justify-content: center;
}
.vertical {
display: flex;
flex-direction: column;
}
::ng-deep .p-panel-header {
justify-content: unset !important;
* {
margin-right: 5px;
}
}
@media only screen and (max-width: 1021px) {
.p-toolbar-group-end, .p-toolbar-group-start {
width: unset;
::ng-deep {
.p-button {
height: 40px !important;
}
p-button {
height: 40px !important;
margin: 0px 4px 0px 0px !important;
}
}
}
.p-toolbar-group-end {
display: flex;
justify-content: flex-start;
::ng-deep {
p-button {
margin: 0px 0px 0px 0px !important;
}
}
}
.p-toolbar-group-center {
width: 100%;
.p-inputtext {
width: calc(100% - 44px);
}
}
}
}

View File

@@ -0,0 +1,28 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { QrCodeGeneratorComponent } from './qr-code-generator.component';
describe('QrCodeGeneratorComponent', () => {
let component: QrCodeGeneratorComponent;
let fixture: ComponentFixture<QrCodeGeneratorComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ QrCodeGeneratorComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(QrCodeGeneratorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,177 @@
import { Component, OnInit, Renderer2 } from '@angular/core';
import { QRCodeModule } from 'angularx-qrcode';
import { AccordionModule } from 'primeng/accordion';
import { PanelModule } from 'primeng/panel';
import { TagModule } from 'primeng/tag';
import { InputTextModule } from 'primeng/inputtext';
import { ButtonModule } from 'primeng/button';
import { ToolbarModule } from 'primeng/toolbar';
import { CommonModule } from '@angular/common';
import { InputTextareaModule } from 'primeng/inputtextarea';
import { FloatLabelModule } from 'primeng/floatlabel';
import { FileUploadModule } from 'primeng/fileupload';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { MessageModule } from 'primeng/message';
import { SelectButtonChangeEvent, SelectButtonModule } from 'primeng/selectbutton';
import { ColorPickerChangeEvent, ColorPickerModule } from 'primeng/colorpicker';
export interface QrCodeError {
error: boolean;
message: string;
}
@Component({
selector: 'app-qr-code-generator',
templateUrl: './qr-code-generator.component.html',
styleUrls: ['./qr-code-generator.component.scss'],
standalone: true,
imports: [
QRCodeModule,
AccordionModule,
PanelModule,
TagModule,
InputTextModule,
ButtonModule,
ToolbarModule,
CommonModule,
FloatLabelModule,
InputTextareaModule,
FileUploadModule,
MessageModule,
SelectButtonModule,
ColorPickerModule
]
})
export class QrCodeGeneratorComponent implements OnInit {
qrCodeData: string = 'bytefy.net';
isBeta = true;
extendedInput = false;
activeTabs: number[] = [1];
expandIcon = 'pi pi-angle-up';
inputedValue: string = '';
qrCodeImageUrl: SafeUrl = '';
unsafeUrl: string = '';
downloadEnabled = false;
error: QrCodeError = {
error: false,
message: ''
};
colorCode: string = '#000000';
backgroundColorCode: string = '#ffffff';
level: "L" | "M" | "Q" | "H" | "low" | "medium" | "quartile" | "high" = 'H';
innerQrCodeimage: string = '';
qrCodeSize: number = 300;
correctionLevel: any[] = [
{ level: 'L' },
{ level: 'M' },
{ level: 'Q' },
{ level: 'H' }
];
isMobile: boolean = false;
constructor(private renderer: Renderer2, private sanitizer: DomSanitizer) {}
ngOnInit(): void {
this.isMobile = window.innerWidth < 1021;
window.addEventListener('resize', () => {
this.isMobile = window.innerWidth < 1021;
});
}
onImageLinkInputChanged(event: Event): void {
this.innerQrCodeimage = (event.target as HTMLInputElement).value;
}
onLevelSelected(level: SelectButtonChangeEvent): void {
this.level = level.value;
}
onFileSelected(event: Event): void {
const file = (event.target as HTMLInputElement).files?.item(0);
if (!file) {
return;
}
const reader = new FileReader();
reader.onload = () => {
this.qrCodeData = reader.result as string;
this.validateInput();
};
reader.readAsText(file);
}
onDataTextInputChanged(event: Event): void {
const input = (event.target as HTMLInputElement).value;
this.qrCodeData = input
this.inputedValue = input;
this.validateInput();
}
onSizeInputChanged(event: Event): void {
let size = parseInt((event.target as HTMLInputElement).value, 10);
if(size <= 1000){
this.qrCodeSize = size;
this.error.error = false;
}
else
this.error = {
error: true,
message: 'Too large image size, change the field "Size of QR Code". Maximum value is 1000.'
};
}
onColorChanged(event: ColorPickerChangeEvent): void {
this.colorCode = event.value.toString();
}
onBackgroundColorChanged(event: ColorPickerChangeEvent): void {
this.backgroundColorCode = event.value.toString();
}
onExpandButtonClick(): void {
this.extendedInput = !this.extendedInput;
this.expandIcon = this.extendedInput ? 'pi pi-angle-down' : 'pi pi-angle-up';
}
onCodeUrlChanged(url: SafeUrl): void {
this.qrCodeImageUrl = url;
}
onPrintButtonClick(): void {
const iframe = this.renderer.createElement('iframe');
this.renderer.setStyle(iframe, 'position', 'absolute');
this.renderer.setStyle(iframe, 'width', '0');
this.renderer.setStyle(iframe, 'height', '0');
this.renderer.setStyle(iframe, 'border', '0');
document.body.appendChild(iframe);
iframe.onload = () => {
const doc = iframe.contentDocument || iframe.contentWindow?.document;
if (doc) {
const img = doc.createElement('img');
img.src = this.sanitizer.sanitize(4, this.qrCodeImageUrl);
doc.body.appendChild(img);
iframe.contentWindow?.print();
setTimeout(() => {
document.body.removeChild(iframe);
}, 1000);
}
};
iframe.srcdoc = '<html><head><title>Bytefy.net Print QR Code</title></head><body></body></html>';
}
validateInput(): void {
this.error = {
error: this.qrCodeData.length > 1269,
message: 'File size is too large.'
};
}
}