Compare commits
16 Commits
Author | SHA1 | Date |
---|---|---|
Marvin Sextro | 68387b1eae | |
Marvin Sextro | 685bbcb19b | |
Marvin Sextro | 7d930105d2 | |
Marvin Sextro | d205444659 | |
Marvin Sextro | 822e8fcd4c | |
Marvin Sextro | 53c81eb9e5 | |
Marvin Sextro | 2a9bdd86d7 | |
po | 87a990e146 | |
Marvin Sextro | 9534a5d5e3 | |
Marvin Sextro | b8eae1fb54 | |
Marvin Sextro | e765408e5a | |
Marvin Sextro | 931b0806f9 | |
Marvin Sextro | 4f30b9b326 | |
Marvin Sextro | 3b04e24a6b | |
Marvin Sextro | 40397d2fea | |
Marvin Sextro | 64f473d214 |
|
@ -1,36 +1,28 @@
|
|||
interface ButtonProps {
|
||||
text?: string,
|
||||
icon?: string,
|
||||
onClick?: () => void,
|
||||
loading?: boolean,
|
||||
type?: ButtonType,
|
||||
}
|
||||
|
||||
export enum ButtonType {
|
||||
submit = 'submit',
|
||||
button = 'button',
|
||||
onClick: () => void,
|
||||
}
|
||||
|
||||
function Button(props: ButtonProps): JSX.Element {
|
||||
|
||||
function handleTouchEnd(event: React.TouchEvent<HTMLButtonElement>) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
props.onClick();
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type={props.type}
|
||||
type="button"
|
||||
onClick={props.onClick}
|
||||
className={`${props.type == ButtonType.submit ? "bg-green-600 hover:bg-green-700" : "bg-gray-400 dark:bg-gray-600 hover:bg-gray-500"} relative focus:outline-none h-20 text-white font-semibold rounded-md items-center flex justify-center`}>
|
||||
onTouchEnd={handleTouchEnd}
|
||||
className="bg-gray-400 dark:bg-gray-600 hover:bg-gray-500 relative focus:outline-none h-20 text-white font-semibold rounded-md items-center flex justify-center">
|
||||
{
|
||||
props.icon && <img src={props.icon} className="w-12 h-12 mr-2 -ml-4" />
|
||||
}
|
||||
{
|
||||
props.type == ButtonType.submit &&
|
||||
<div id="spin" className={`${props.loading ? undefined : "hidden"} absolute left-2`}>
|
||||
<svg className="animate-spin h-5 w-5 ml-4" viewBox="0 0 24 24">
|
||||
<circle className="opacity-0" cx="12" cy="12" r="10" stroke="currentColor"
|
||||
strokeWidth="4"/>
|
||||
<path className="opacity-80" fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/>
|
||||
</svg>
|
||||
</div>
|
||||
}
|
||||
{props.text}
|
||||
</button>
|
||||
)
|
||||
|
|
|
@ -13,7 +13,7 @@ import {getPayloadBodyFromFile, getPayloadBodyFromQR} from "../src/process";
|
|||
import {PassData} from "../src/pass";
|
||||
import {COLORS} from "../src/colors";
|
||||
import Colors from './Colors';
|
||||
import Button, { ButtonType } from './Button';
|
||||
import Button from './Button';
|
||||
|
||||
function Form(): JSX.Element {
|
||||
const {t} = useTranslation(['index', 'errors', 'common']);
|
||||
|
@ -74,7 +74,7 @@ function Form(): JSX.Element {
|
|||
navigator.userAgent.indexOf('CriOS') == -1 &&
|
||||
navigator.userAgent.indexOf('FxiOS') == -1
|
||||
)
|
||||
}, []);
|
||||
}, [isSafari]);
|
||||
|
||||
// Whether Safari is used or not
|
||||
let [isShareDialogAvailable, setIsShareDialogAvailable] = useState<boolean>(false);
|
||||
|
@ -82,7 +82,7 @@ function Form(): JSX.Element {
|
|||
// Check if share dialog is available
|
||||
useEffect(() => {
|
||||
setIsShareDialogAvailable(window.navigator && window.navigator.share !== undefined);
|
||||
}, []);
|
||||
}, [isShareDialogAvailable]);
|
||||
|
||||
// Open share dialog
|
||||
async function showShareDialog() {
|
||||
|
@ -191,6 +191,9 @@ function Form(): JSX.Element {
|
|||
const passBlob = new Blob([pass], {type: "application/vnd.apple.pkpass"});
|
||||
saveAs(passBlob, 'covid.pkpass');
|
||||
setLoading(false);
|
||||
|
||||
var scrollingElement = (document.scrollingElement || document.body);
|
||||
scrollingElement.scrollTop = scrollingElement.scrollHeight;
|
||||
} catch (e) {
|
||||
setErrorMessage(e.message);
|
||||
setLoading(false);
|
||||
|
@ -275,7 +278,19 @@ function Form(): JSX.Element {
|
|||
</p>
|
||||
</label>
|
||||
<div className="grid grid-cols-1">
|
||||
<Button type={ButtonType.submit} text={t('index:addToWallet')} loading={loading} />
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-green-600 hover:bg-green-700 relative focus:outline-none h-20 text-white font-semibold rounded-md items-center flex justify-center">
|
||||
<div id="spin" className={`${loading ? undefined : "hidden"} absolute left-2`}>
|
||||
<svg className="animate-spin h-5 w-5 ml-4" viewBox="0 0 24 24">
|
||||
<circle className="opacity-0" cx="12" cy="12" r="10" stroke="currentColor"
|
||||
strokeWidth="4"/>
|
||||
<path className="opacity-80" fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/>
|
||||
</svg>
|
||||
</div>
|
||||
{t('index:addToWallet')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}/>
|
||||
|
|
|
@ -12,7 +12,8 @@ module.exports = {
|
|||
'es', 'es-ES',
|
||||
'no', 'no-NO',
|
||||
'nb', 'nb-NO',
|
||||
'sv', 'sv-SE', 'sv-FI'
|
||||
'sv', 'sv-SE', 'sv-FI',
|
||||
'ro', 'ro-RO', 'ro-MD'
|
||||
],
|
||||
localeExtension: 'yml',
|
||||
},
|
||||
|
|
|
@ -2,4 +2,12 @@ const {i18n} = require('./next-i18next.config');
|
|||
|
||||
module.exports = {
|
||||
i18n,
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: '/pass/note',
|
||||
destination: '/pass'
|
||||
}
|
||||
];
|
||||
}
|
||||
};
|
|
@ -24,6 +24,7 @@
|
|||
"pdfjs-dist": "^2.5.207",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-qr-code": "^2.0.3",
|
||||
"uuid": "^8.3.2",
|
||||
"webpack": "^5.0.0",
|
||||
"worker-loader": "^3.0.7"
|
||||
|
|
|
@ -12,7 +12,11 @@ function Imprint(): JSX.Element {
|
|||
<Card step="§" heading={t('common:imprint')} content={
|
||||
<div className="space-y-3">
|
||||
<p className="font-bold">{t('imprint:heading')}</p>
|
||||
<p>Marvin Sextro</p>
|
||||
<p>
|
||||
Marvin Sextro<br />
|
||||
Kopenhagener Straße 45<br />
|
||||
10437 Berlin
|
||||
</p>
|
||||
<p className="font-bold">{t('imprint:contact')}</p>
|
||||
<p>
|
||||
<a href="mailto:covidpass@marvinsextro.de" className="underline">covidpass@marvinsextro.de</a>
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
import {useTranslation} from 'next-i18next';
|
||||
import {serverSideTranslations} from 'next-i18next/serverSideTranslations';
|
||||
|
||||
import React, {useEffect, useState} from "react";
|
||||
import QRCode from "react-qr-code";
|
||||
|
||||
import Alert from '../components/Alert';
|
||||
import Card from '../components/Card';
|
||||
import Logo from "../components/Logo";
|
||||
|
||||
function Pass(): JSX.Element {
|
||||
const { t } = useTranslation(['common', 'index']);
|
||||
|
||||
const [fragment, setFragment] = useState<string>(undefined);
|
||||
const [view, setView] = useState<boolean>(true);
|
||||
|
||||
useEffect(() => {
|
||||
const rawFragment = window.location.hash.substring(1);
|
||||
|
||||
if (!rawFragment) {
|
||||
setView(false);
|
||||
}
|
||||
|
||||
const resizeTimeout = window.setTimeout(() => {
|
||||
if (rawFragment) {
|
||||
window.location.replace('/pass/note');
|
||||
}
|
||||
}, 200);
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
clearTimeout(resizeTimeout);
|
||||
const decodedFragment = Buffer.from(rawFragment, 'base64').toString();
|
||||
setFragment(decodedFragment);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="py-5 flex flex-col space-y-5 md:w-2/3 xl:w-2/5 md:mx-auto items-center justify-center px-5">
|
||||
<Logo/>
|
||||
<div className="flex flex-row items-center">
|
||||
{
|
||||
fragment &&
|
||||
<Card content={
|
||||
<div className="p-2 bg-white rounded-md">
|
||||
<QRCode value={fragment} size={280} level="L" />
|
||||
</div>
|
||||
} />
|
||||
}
|
||||
{
|
||||
!view &&
|
||||
<Alert isWarning={true} message={t('index:viewerNote')} onClose={undefined} />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['index', 'common'])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default Pass;
|
|
@ -152,7 +152,7 @@ function Privacy(): JSX.Element {
|
|||
<li>
|
||||
{t('privacy:appleSync')}:
|
||||
|
||||
<a href="https://www.apple.com/legal/privacy/en-ww/privacy.tsx" className="underline">
|
||||
<a href="https://www.apple.com/legal/privacy/en-ww/" className="underline">
|
||||
{t('common:privacyPolicy')}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -25,4 +25,5 @@ privacyPolicy: Datenschutzerklärung
|
|||
createdOnDevice: Auf Deinem Gerät erstellt
|
||||
openSourceTransparent: Open Source und transparent
|
||||
hostedInEU: In der EU gehostet
|
||||
share: Weiterempfehlen
|
||||
share: Weiterempfehlen
|
||||
viewerNote: Bitte drücke und halte den Link auf der Rückseite des Passes, um den QR Code unter iOS vergrößert anzuzeigen.
|
|
@ -25,4 +25,4 @@ privacyPolicy: Πολιτική Απορρήτου
|
|||
createdOnDevice: Δημιουργείται στη συσκευή σας
|
||||
openSourceTransparent: Ανοιχτού κώδικα και διαφανής
|
||||
hostedInEU: Φιλοξενείται στην ΕΕ
|
||||
share: Συστήσει
|
||||
share: Κοινοποιήστε το
|
|
@ -25,4 +25,5 @@ privacyPolicy: Privacy Policy
|
|||
createdOnDevice: Created on your device
|
||||
openSourceTransparent: Open source and transparent
|
||||
hostedInEU: Hosted in the EU
|
||||
share: Share
|
||||
share: Share
|
||||
viewerNote: Please press and hold the link on the back of the pass in order to enlarge the QR code on iOS.
|
|
@ -0,0 +1 @@
|
|||
ro
|
|
@ -0,0 +1 @@
|
|||
ro
|
|
@ -0,0 +1,6 @@
|
|||
title: CovidPass
|
||||
subtitle: Adaugă-ți Certificatul UE Covid in aplicația ta preferată de wallet.
|
||||
privacyPolicy: Politica de Confidențialitate
|
||||
donate: Donează
|
||||
gitHub: GitHub
|
||||
imprint: Mențiuni Legale
|
|
@ -0,0 +1,20 @@
|
|||
noFileOrQrCode: Te rog scaneaza un cod QR, sau alege un fisier
|
||||
signatureFailed: Eroare in timpul semnarii certificatului pe server
|
||||
decodingFailed: Imposibil de decodat continutul codului QR
|
||||
invalidColor: Culoare Invalida
|
||||
certificateData: Eroare in citirea datelor certificatului
|
||||
nameMissing: Eroare in citirea numelui
|
||||
dobMissing: Eroare in citirea datei de nastere
|
||||
invalidMedicalProduct: Produs medical (Vaccin) invalid
|
||||
invalidCountryCode: Codul tarii este invalid
|
||||
invalidManufacturer: Fabricant invalid
|
||||
invalidFileType: Tipul fisierului invalid
|
||||
couldNotDecode: Eroare in decodarea codului QR din fisier
|
||||
couldNotFindQrCode: Nu s-a gasit niciun cod QR valid in fisierul selectat
|
||||
invalidQrCode: Cod QR invalid
|
||||
certificateType: Tipul certificatului este invalid
|
||||
invalidTestResult: Rezultatul testului este invalid
|
||||
invalidTestType: Tipul testului este invalid
|
||||
noCameraAccess: Nu s-a putut accesa camera. Schimbati permisiunile in Setari > Safari > Camera.
|
||||
noCameraFound: Nu s-a putut accesa camera.
|
||||
safariSupportOnly: in iOS, va rog sa folositi doar browser-ul safari.
|
|
@ -0,0 +1,27 @@
|
|||
heading: Informații conform articolului 5 TMG
|
||||
contact: Contact
|
||||
euDisputeResolution: Soluționarea Disputelor UE
|
||||
euDisputeResolutionParagraph: |
|
||||
Comisia Europeana dispune de o platforma pentru soluționarea disputelor online (OS) https://ec.europa.eu/consumers/odr.
|
||||
Ne puteți găsi adresa de email in datele de mai sus.
|
||||
consumerDisputeResolution: Rezolvarea litigiilor consumatorilor / comisia universală de arbitraj
|
||||
consumerDisputeResolutionParagraph: Nu suntem dispuși sau obligați să participăm la procedurile de soluționare a litigiilor în fața unei comisii de arbitraj pentru consumatori.
|
||||
liabilityForContents: Raspunderea pentru continut
|
||||
liabilityForContentsParagraph: |
|
||||
În calitate de furnizori de servicii, suntem responsabili pentru conținutul propriu în conformitate cu articolul 7 paragraful 1 TMG în conformitate cu legile generale.
|
||||
Conform secțiunilor 8 până la 10, nu suntem obligați să monitorizăm informațiile transmise sau stocate sau să investigăm circumstanțe care indică o activitate ilegală.
|
||||
Obligațiile de a elimina sau de a bloca utilizarea informațiilor conform legilor generale rămân neafectate.
|
||||
Cu toate acestea, răspunderea în această privința este posibilă numai din momentul în care devine cunoscută o încălcare concretă a legii.
|
||||
Dacă aflăm de existența unor asemenea încălcări, vom elimina imediat conținutul relevant.
|
||||
liabilityForLinks: Raspunderea pentru linkuri
|
||||
liabilityForLinksParagraph: |
|
||||
Oferta noastră conține link-uri către site-uri externe ale terților, asupra cărora nu avem nicio influență.
|
||||
Prin urmare, nu ne putem asuma nicio răspundere pentru aceste conținuturi externe.
|
||||
Furnizorul sau operatorul respectiv al site-urilor este întotdeauna responsabil pentru conținutul site-urilor mentionate.
|
||||
Paginile conectate au fost verificate pentru posibile încălcări legale la momentul punerii link-ului.
|
||||
Conținuturile ilegale nu erau recunoscute în momentul punerii link-urilor.
|
||||
Cu toate acestea, un control permanent al conținutului paginilor linkate nu este rezonabil fără dovezi concrete ale unei încălcări a legii.
|
||||
Dacă aflăm că există încălcări, vom elimina imediat astfel de legături.
|
||||
credits: Credite
|
||||
creditsSource: Cu extrase din https://www.e-recht24.de/impressum-generator.html
|
||||
creditsTranslation: Tradus cu https://www.DeepL.com/Translator (free version)
|
|
@ -0,0 +1,28 @@
|
|||
iosHint: In iOS, te rog foloseste browser-ul Safari.
|
||||
errorClose: Inchide
|
||||
selectCertificate: Alege certificatul
|
||||
selectCertificateDescription: Te rog scaneaza codul QR de pe certificatul tau sau alege un screenshot/PDF cu codul QR
|
||||
stopCamera: Opreste Camera
|
||||
startCamera: Porneste Camera
|
||||
openFile: Selecteaza fisierul
|
||||
foundQrCode: Cod QR detectat!
|
||||
pickColor: Alege o culoare
|
||||
pickColorDescription: Alege o culoare de fundal pentru certificatul tau.
|
||||
colorWhite: alb
|
||||
colorBlack: negru
|
||||
colorGrey: gri
|
||||
colorGreen: verde
|
||||
colorIndigo: indigo
|
||||
colorBlue: albastru
|
||||
colorPurple: mov
|
||||
colorTeal: teal
|
||||
addToWallet: Adauga in Wallet
|
||||
dataPrivacyDescription: |
|
||||
Confidentialitatea datelor este de o importanta speciala cand vine vorba de date medicale.
|
||||
Pentru a face o alegere informata, va rugam cititi
|
||||
iAcceptThe: Sunt de acord cu
|
||||
privacyPolicy: Politica de Confidentialitate
|
||||
createdOnDevice: Creat pe dispozitivul tau
|
||||
openSourceTransparent: Open source si transparent
|
||||
hostedInEU: Gazduit in UE
|
||||
share: Distribuie
|
|
@ -0,0 +1,57 @@
|
|||
gdprNotice: |
|
||||
Politica noastră de confidențialitate se bazează pe termenii folosiți de legiuitorul european
|
||||
pentru adoptarea Regulamentului general privind protecția datelor (GDPR).
|
||||
generalInfo: Informații Generale
|
||||
generalInfoProcess: |
|
||||
Întregul proces de generare a fișierului de Wallet are loc local în browserul dvs.
|
||||
Pentru pasul de semnare (certificare), doar o reprezentare hashed (codata ireversibil) a datelor dvs. este trimisă către server.
|
||||
generalInfoStoring: Datele dumneavoastră nu sunt stocate dincolo de sesiunea activă a browserului, iar site-ul nu utilizează cookie-uri.
|
||||
generalInfoThirdParties: Nu sunt trimise date catre părți terțe.
|
||||
generalInfoHttps: Datele sunt transmise în mod securizat prin https.
|
||||
generalInfoLocation: Serverele noastre sunt găzduite in Nuremberg, Germania.
|
||||
generalInfoGitHub: Codul sursă al acestui site este accesibil pe
|
||||
generalInfoLockScreen: În mod normal, cardurile din Apple Wallet sunt accesibile de pe lock screen. Puteți schimba acest lucru in
|
||||
settings: setări
|
||||
generalInfoProvider: |
|
||||
Furnizorul de server prelucrează date pentru a furniza acest site.
|
||||
Pentru a înțelege mai bine ce măsuri iau aceștia pentru a vă proteja datele, vă rugăm să citiți și pe partea lor
|
||||
privacyPolicy: Politica de Confidențialitate
|
||||
andThe: și
|
||||
dataPrivacyFaq: Întrebari puse des despre confidențialitate
|
||||
contact: Contact
|
||||
email: Email
|
||||
website: Website
|
||||
process: Explicație simplificata a procesului
|
||||
processFirst: În primul rând, următorii pași au loc local în browserul dvs
|
||||
processSecond: În al doilea rând, următorii pași au loc pe serverul nostru
|
||||
processThird: În cele din urmă, următorii pași au loc local în browserul dvs
|
||||
processRecognizing: Recunoașterea și extragerea datelor codului QR din certificatul selectat
|
||||
processDecoding: Decodificarea datelor dvs. personale și medicale din încărcarea codului QR
|
||||
processAssembling: Asamblarea unui fișier de Wallet incomplet din datele dvs
|
||||
processGenerating: Generarea unui fișier care conține hash-uri ale datelor stocate în fișierul wallet
|
||||
processSending: Trimiterea doar fișierul care conține hash-urile către serverul nostru
|
||||
processReceiving: Primirea și verificarea hashurilor care au fost generate local
|
||||
processSigning: Semnarea fișierului care conține hashurile
|
||||
processSendingBack: Trimiterea semnăturii înapoi
|
||||
processCompleting: Asamblarea fișierului wallet semnat din fișierul incomplet generat local și semnătura
|
||||
processSaving: Salvarea fisierului pe dispozitiv
|
||||
locallyProcessedData: Date procesate local
|
||||
the:
|
||||
schema: Schema Certificatului Digital Covid
|
||||
specification: contine o schema complete cu datele care sunt continute de codul QR al certificatului covid si care vor fi procesate in browser.
|
||||
serverProvider: Furnizorul de Servere
|
||||
serverProviderIs: Furnizorul nostru de servere este
|
||||
logFiles: Următoarele date pot fi colectate și stocate în fișierele jurnal ale serverului
|
||||
logFilesBrowser: Tipurile și versiunile de browser utilizate
|
||||
logFilesOs: Sistemul de operare utilizat de sistemul de accesare
|
||||
logFilesReferrer: Site-ul web de pe care un sistem de accesare ajunge pe site-ul nostru web (așa-numiții recomandanți)
|
||||
logFilesTime: Data și ora accesului
|
||||
logFilesIpAddress: Adresele IP pseudonimizate
|
||||
rights: Drepturile tale
|
||||
rightsGranted: În conformitate cu GDPR, aveți următoarele drepturi
|
||||
rightsAccess: Dreptul de acces la datele dumneavoastră; Ai dreptul să știi ce date au fost colectate despre tine și cum au fost prelucrate.
|
||||
rightsErasure: Dreptul de a fi uitat; Ștergerea datelor dumneavoastră personale.
|
||||
rightsRectification: Dreptul de rectificare; Aveți dreptul de a corecta datele eronate.
|
||||
rightsPortability: Dreptul la portabilitatea datelor; Aveți dreptul să vă transferați datele dintr-un sistem de procesare în altul.
|
||||
thirdParties: Părți terțe
|
||||
appleSync: Este posibil ca Apple să vă sincronizeze cardurile wallet prin iCloud
|
|
@ -0,0 +1,3 @@
|
|||
User-agent: *
|
||||
Disallow: /pass
|
||||
Disallow: /pass/note
|
|
@ -3,9 +3,9 @@ import {Constants} from "./constants";
|
|||
import {COLORS} from "./colors";
|
||||
|
||||
enum CertificateType {
|
||||
Vaccination = 'Vaccination Card',
|
||||
Test = 'Test Certificate',
|
||||
Recovery = 'Recovery Certificate',
|
||||
Vaccination = 'Vaccination Pass',
|
||||
Test = 'Test Pass',
|
||||
Recovery = 'Recovery Pass',
|
||||
}
|
||||
|
||||
enum TextAlignment {
|
||||
|
@ -116,6 +116,11 @@ export class Payload {
|
|||
|
||||
const country = valueSets.countryCodes[countryCode].display;
|
||||
|
||||
// Encode raw data and get url
|
||||
const encodedData = Buffer.from(body.rawData).toString('base64');
|
||||
const url = window.location.protocol + "//" + window.location.host;
|
||||
|
||||
|
||||
const generic: PassDictionary = {
|
||||
headerFields: [
|
||||
{
|
||||
|
@ -134,6 +139,11 @@ export class Payload {
|
|||
secondaryFields: [],
|
||||
auxiliaryFields: [],
|
||||
backFields: [
|
||||
{
|
||||
key: "enlarge",
|
||||
label: "Enlarging the QR Code",
|
||||
value: `Inside the Wallet app on iOS, press and hold the link below. This does not work when accessing the Wallet by double-clicking the side button.\n<a href='${url}/pass#${encodedData}'>Enlarge QR Code</a>`
|
||||
},
|
||||
{
|
||||
key: "uvci",
|
||||
label: "Unique Certificate Identifier (UVCI)",
|
||||
|
@ -157,10 +167,27 @@ export class Payload {
|
|||
this.img2x = dark ? Constants.img2xWhite : Constants.img2xBlack
|
||||
this.dark = dark;
|
||||
|
||||
this.generic = Payload.fillPassData(this.certificateType, generic, properties, valueSets, country, dateOfBirth);
|
||||
this.generic = Payload.fillPassData(
|
||||
this.certificateType,
|
||||
generic,
|
||||
properties,
|
||||
valueSets,
|
||||
country,
|
||||
dateOfBirth,
|
||||
url
|
||||
);
|
||||
}
|
||||
|
||||
static fillPassData(type: CertificateType, data: PassDictionary, properties: Object, valueSets: ValueSets, country: string, dateOfBirth: string): PassDictionary {
|
||||
static fillPassData(
|
||||
type: CertificateType,
|
||||
data: PassDictionary,
|
||||
properties: Object,
|
||||
valueSets: ValueSets,
|
||||
country: string,
|
||||
dateOfBirth: string,
|
||||
url: string
|
||||
): PassDictionary {
|
||||
|
||||
switch (type) {
|
||||
case CertificateType.Vaccination:
|
||||
const dose = `${properties['dn']}/${properties['sd']}`;
|
||||
|
@ -353,7 +380,7 @@ export class Payload {
|
|||
{
|
||||
key: "credits",
|
||||
label: "",
|
||||
value: "Created with <a href='https://covidpass.marvinsextro.de'>CovidPass</a>"
|
||||
value: `Created with <a href='${url}'>CovidPass</a>`
|
||||
}
|
||||
]);
|
||||
|
||||
|
|
26
yarn.lock
26
yarn.lock
|
@ -1873,7 +1873,7 @@ lodash@^4.17.21:
|
|||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
|
@ -2396,6 +2396,15 @@ process@0.11.10, process@^0.11.10:
|
|||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
|
||||
prop-types@^15.7.2:
|
||||
version "15.8.0"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.0.tgz#d237e624c45a9846e469f5f31117f970017ff588"
|
||||
integrity sha512-fDGekdaHh65eI3lMi5OnErU6a8Ighg2KjcjQxO7m8VHyWjcPyj5kiOgV1LQDOOOgVy3+5FgjXvdSSX7B8/5/4g==
|
||||
dependencies:
|
||||
loose-envify "^1.4.0"
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
public-encrypt@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
|
||||
|
@ -2433,6 +2442,11 @@ purgecss@^4.0.3:
|
|||
postcss "^8.3.5"
|
||||
postcss-selector-parser "^6.0.6"
|
||||
|
||||
qr.js@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
|
||||
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=
|
||||
|
||||
querystring-es3@0.2.1, querystring-es3@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
||||
|
@ -2513,11 +2527,19 @@ react-is@17.0.2:
|
|||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||
|
||||
react-is@^16.7.0:
|
||||
react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-qr-code@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/react-qr-code/-/react-qr-code-2.0.3.tgz#cc80785e08f817d1ab066ca4035262f77d049648"
|
||||
integrity sha512-6GDH0l53lksf2JgZwwcoS0D60a1OAal/GQRyNFkMBW19HjSqvtD5S20scmSQsKl+BgWM85Wd5DCcUYoHd+PZnQ==
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
qr.js "0.0.0"
|
||||
|
||||
react-refresh@0.8.3:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
|
||||
|
|
Loading…
Reference in New Issue