Merge branch 'main' of github.com:billylo1/covidpass into main
* 'main' of github.com:billylo1/covidpass: add instructions for removing pass ready for deployment to main alpha test
This commit is contained in:
commit
081674a3db
|
@ -1,6 +1,6 @@
|
|||
API_BASE_URL=http://localhost
|
||||
VERIFIER_HOST=http://localhost:5001/grassroot-verifier/us-central1
|
||||
API_BASE_URL=http://evergreen
|
||||
VERIFIER_HOST=http://evergreen:5001/grassroot-verifier/us-central1
|
||||
HITCOUNT_HOST=http://localhost:8080
|
||||
REGISTRATION_HOST=http://localhost:5001/grassroot-verifier/us-central1
|
||||
REGISTRATION_HOST=http://evergreen:5001/grassroot-verifier/us-central1
|
||||
FUNCTION_SUFFIX=v2
|
||||
GPAY_BASE_URL=http://localhost:5002/grassroots-gpay/us-central1/googlesign
|
||||
|
|
|
@ -32,3 +32,5 @@ yarn-error.log*
|
|||
|
||||
# Idea files
|
||||
.idea
|
||||
*.local
|
||||
*.local
|
||||
|
|
|
@ -126,6 +126,7 @@ function Form(): JSX.Element {
|
|||
_setFileErrorMessages([]);
|
||||
checkBrowserType();
|
||||
const payloadBody = await getPayload(selectedFile);
|
||||
await createDataUrlForDisplay(selectedFile);
|
||||
await renderPhoto(payloadBody);
|
||||
}
|
||||
});
|
||||
|
@ -133,9 +134,68 @@ function Form(): JSX.Element {
|
|||
checkBrowserType();
|
||||
}, [inputFile])
|
||||
|
||||
async function createDataUrlForDisplay(file: File) {
|
||||
|
||||
if (window.localStorage) {
|
||||
|
||||
// https://stackoverflow.com/a/56738510/2789065
|
||||
|
||||
const buffer = Buffer.from(await new Response(file).arrayBuffer());
|
||||
let dataUrl = `data:${file.type};base64,${buffer.toString("base64")}`;
|
||||
localStorage.setItem('pdfDataUrl', dataUrl);
|
||||
// dataUrl = 'https://apple.com';
|
||||
|
||||
|
||||
|
||||
// let script = `function debugBase64(base64URL){
|
||||
// var win = window.open();
|
||||
// win.document.write('<iframe src="' + base64URL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>');
|
||||
// }
|
||||
// debugBase64('${dataUrl}');
|
||||
// `;
|
||||
|
||||
// let hrefValue = `javascript:${script};`
|
||||
|
||||
// let aElement = document.createElement('a')
|
||||
// let textNode = document.createTextNode('Click me');
|
||||
// aElement.appendChild(textNode);
|
||||
// aElement.title = 'Click me';
|
||||
// aElement.setAttribute('id', 'mylink');
|
||||
// aElement.setAttribute('href', hrefValue)
|
||||
// // aElement.setAttribute('download', file.name)
|
||||
// // aElement.setAttribute('target', '_blank')
|
||||
|
||||
// document.getElementById('wrapper').appendChild(aElement);
|
||||
|
||||
// console.log('*** outerHTML ***');
|
||||
// console.log(document.getElementById('wrapper').outerHTML)
|
||||
}
|
||||
}
|
||||
|
||||
async function showPDF() {
|
||||
let dataUrl = localStorage.getItem('pdfDataUrl');
|
||||
// console.log(dataUrl)
|
||||
let script = `function debugBase64(base64URL){
|
||||
var win = window.open();
|
||||
win.document.write('<iframe src="' + base64URL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>');
|
||||
}
|
||||
debugBase64('${dataUrl}');
|
||||
`;
|
||||
|
||||
let hrefValue = `javascript:${script};`
|
||||
document.getElementById('mylink').setAttribute('href', hrefValue);
|
||||
|
||||
}
|
||||
|
||||
async function getPayload(file) : Promise<PayloadBody> {
|
||||
try {
|
||||
const payload = await getPayloadBodyFromFile(file);
|
||||
|
||||
const buffer = Buffer.from(await new Response(file).arrayBuffer());
|
||||
let dataUrl = `data:${file.type};base64,${buffer.toString("base64")}`;
|
||||
|
||||
payload.dataUrl = dataUrl;
|
||||
|
||||
setPayloadBody(payload);
|
||||
setFileLoading(false);
|
||||
setFile(file);
|
||||
|
@ -372,7 +432,6 @@ function Form(): JSX.Element {
|
|||
const newUrl = `https://pay.google.com/gp/v/save/${jwt}`;
|
||||
console.log('> redirect to save Google Pass');
|
||||
|
||||
// saveAs(passBlob, covidPassFilename);
|
||||
setSaveLoading(false);
|
||||
window.location.href = newUrl;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -43,7 +43,7 @@
|
|||
"node-fetch": "^2.6.1",
|
||||
"node-jose": "^2.0.0",
|
||||
"node-pdf-verifier": "^1.0.1",
|
||||
"pdfjs-dist": "^2.6.347",
|
||||
"pdfjs-dist": "^2.10.377",
|
||||
"pngjs": "^6.0.0",
|
||||
"qrcode": "^1.4.4",
|
||||
"react": "^17.0.2",
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<style>
|
||||
.center {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.big-text {
|
||||
font-size: 64;
|
||||
}
|
||||
</style>
|
||||
<script src='displayLocallyStoredPDF.js'></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a class='center big-text' id="mylink">View Receipt</a>
|
||||
<script>updatePage();</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,23 @@
|
|||
function updatePage() {
|
||||
|
||||
let dataUrl = localStorage.getItem('pdfDataUrl');
|
||||
const myLinkElement = document.getElementById('mylink');
|
||||
|
||||
if (dataUrl != undefined) {
|
||||
|
||||
let script = `function showData(base64URL){
|
||||
var win = window.open();
|
||||
win.document.write('<iframe src="' + base64URL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>');
|
||||
} showData('${dataUrl}');`;
|
||||
|
||||
let hrefValue = `javascript:${script};`;
|
||||
myLinkElement.setAttribute('href', hrefValue);
|
||||
|
||||
} else {
|
||||
if (navigator.userAgent.indexOf('Safari') != -1) {
|
||||
myLinkElement.textContent = 'Sorry. This feature requires the use of Safari as default browser. You can change it in Settings - Chrome/Firefox';
|
||||
} else {
|
||||
myLinkElement.textContent = 'Original receipt not available locally. Please re-create your wallet pass. Thanks.';
|
||||
}
|
||||
}
|
||||
}
|
148
src/payload.ts
148
src/payload.ts
|
@ -1,5 +1,6 @@
|
|||
import {Constants} from "./constants";
|
||||
import {COLORS} from "./colors";
|
||||
import link from "next/link";
|
||||
|
||||
export class Receipt {
|
||||
constructor(public name: string, public vaccinationDate: string, public vaccineName: string, public dateOfBirth: string, public numDoses: number, public organization: string) {};
|
||||
|
@ -25,8 +26,9 @@ export class SHCVaccinationRecord {
|
|||
interface Field {
|
||||
key: string;
|
||||
label: string;
|
||||
value: string;
|
||||
value?: string;
|
||||
textAlignment?: string;
|
||||
attributedValue?: string;
|
||||
}
|
||||
|
||||
export interface PassDictionary {
|
||||
|
@ -41,6 +43,7 @@ export interface PayloadBody {
|
|||
rawData: string;
|
||||
receipts: HashTable<Receipt>;
|
||||
shcReceipt: SHCReceipt;
|
||||
dataUrl?: string;
|
||||
}
|
||||
|
||||
export class Payload {
|
||||
|
@ -48,6 +51,7 @@ export class Payload {
|
|||
receipts: HashTable<Receipt>;
|
||||
shcReceipt: SHCReceipt;
|
||||
rawData: string;
|
||||
dataUrl?: string;
|
||||
backgroundColor: string;
|
||||
labelColor: string;
|
||||
foregroundColor: string;
|
||||
|
@ -62,6 +66,7 @@ export class Payload {
|
|||
this.receipts = body.receipts;
|
||||
this.shcReceipt = body.shcReceipt;
|
||||
this.rawData = body.rawData;
|
||||
this.dataUrl = body.dataUrl;
|
||||
this.generic = {
|
||||
headerFields: [],
|
||||
primaryFields: [],
|
||||
|
@ -77,112 +82,20 @@ export class Payload {
|
|||
this.foregroundColor = COLORS.BLACK;
|
||||
this.img1x = Constants.img1xBlack;
|
||||
this.img2x = Constants.img2xBlack;
|
||||
} else {
|
||||
const fullyVaccinated = processReceipt(body.receipts[numDose], this.generic);
|
||||
if (fullyVaccinated) {
|
||||
this.backgroundColor = COLORS.GREEN;
|
||||
} else {
|
||||
this.backgroundColor = COLORS.YELLOW;
|
||||
}
|
||||
this.labelColor = COLORS.WHITE;
|
||||
this.foregroundColor = COLORS.WHITE;
|
||||
this.img1x = Constants.img1xWhite;
|
||||
this.img2x = Constants.img2xWhite;
|
||||
|
||||
// These are the non-SHC ON receipts, which expire Oct 22nd
|
||||
this.expirationDate = '2021-10-22T23:59:59-04:00';
|
||||
this.generic.auxiliaryFields.push({
|
||||
key: "expiry",
|
||||
label: "QR code expiry",
|
||||
value: '2021-10-22'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
let displayLocallyStoredPDFUrl = window.location.href + "displayLocallyStoredPDF.html";
|
||||
console.log(displayLocallyStoredPDFUrl)
|
||||
const attributedValue = `<a href="${displayLocallyStoredPDFUrl}">View</a>`;
|
||||
console.log('*** attributedValue ***');
|
||||
console.log(attributedValue);
|
||||
|
||||
function processReceipt(receipt: Receipt, generic: PassDictionary) : boolean {
|
||||
|
||||
console.log(`processing receipt #${receipt.numDoses}`);
|
||||
|
||||
const name = receipt['name'];
|
||||
const dateOfBirth = receipt.dateOfBirth;
|
||||
const numDoses = receipt.numDoses;
|
||||
const vaccineName = receipt.vaccineName.toLocaleUpperCase();
|
||||
let vaccineNameProper = vaccineName.charAt(0) + vaccineName.substr(1).toLowerCase();
|
||||
|
||||
if (vaccineName.includes('PFIZER'))
|
||||
vaccineNameProper = 'Pfizer (Comirnaty)'
|
||||
|
||||
if (vaccineName.includes('MODERNA'))
|
||||
vaccineNameProper = 'Moderna (SpikeVax)'
|
||||
|
||||
if (vaccineName.includes('ASTRAZENECA') || vaccineName.includes('COVISHIELD'))
|
||||
vaccineNameProper = 'AstraZeneca (Vaxzevria)'
|
||||
|
||||
let doseVaccine = "#" + String(receipt.numDoses) + ": " + vaccineNameProper;
|
||||
let fullyVaccinated = false;
|
||||
|
||||
if (receipt.numDoses > 1 ||
|
||||
vaccineName.toLowerCase().includes('janssen') ||
|
||||
vaccineName.toLowerCase().includes('johnson') ||
|
||||
vaccineName.toLowerCase().includes('j&j')) {
|
||||
fullyVaccinated = true;
|
||||
}
|
||||
|
||||
if (generic.primaryFields.length == 0) {
|
||||
generic.primaryFields.push(
|
||||
{
|
||||
key: "vaccine",
|
||||
label: "Vaccine",
|
||||
value: doseVaccine
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
let fieldToPush = generic.secondaryFields;
|
||||
if (fieldToPush.length > 0) {
|
||||
fieldToPush = generic.backFields;
|
||||
generic.headerFields.push({
|
||||
key: "extra",
|
||||
label: "More",
|
||||
value: "(i)",
|
||||
"textAlignment" : "PKTextAlignmentCenter"
|
||||
});
|
||||
generic.backFields.push({
|
||||
key: "vaccine" + numDoses,
|
||||
label: `Vaccine (Dose ${numDoses})`,
|
||||
value: receipt.vaccineName
|
||||
})
|
||||
}
|
||||
|
||||
fieldToPush.push(
|
||||
{
|
||||
key: "issuer",
|
||||
label: "Authorized Organization",
|
||||
value: receipt.organization
|
||||
},
|
||||
{
|
||||
key: "dov",
|
||||
label: "Vacc. Date",
|
||||
value: receipt.vaccinationDate,
|
||||
}
|
||||
);
|
||||
|
||||
if (generic.auxiliaryFields.length == 0) {
|
||||
generic.auxiliaryFields.push(
|
||||
{
|
||||
key: "name",
|
||||
label: "Name",
|
||||
value: name
|
||||
},
|
||||
{
|
||||
key: "dob",
|
||||
label: "Date of Birth",
|
||||
value: dateOfBirth
|
||||
this.generic.backFields.push({
|
||||
key: "original",
|
||||
label: "Original receipt (saved locally in Safari)",
|
||||
attributedValue: attributedValue
|
||||
});
|
||||
}
|
||||
|
||||
return fullyVaccinated;
|
||||
}
|
||||
}
|
||||
|
||||
function processSHCReceipt(receipt: SHCReceipt, generic: PassDictionary) {
|
||||
|
@ -190,27 +103,34 @@ function processSHCReceipt(receipt: SHCReceipt, generic: PassDictionary) {
|
|||
console.log(`processing receipt for origin ${receipt.cardOrigin}`);
|
||||
|
||||
if (generic.primaryFields.length == 0) {
|
||||
const lastReceiptIndex = receipt.vaccinations.length - 1
|
||||
const mostRecentReceipt = receipt.vaccinations[lastReceiptIndex];
|
||||
const vaccineName = mostRecentReceipt.vaccineName.substring(0,1).toUpperCase() + mostRecentReceipt.vaccineName.substring(1).toLowerCase();
|
||||
const value = `#${lastReceiptIndex + 1} - ${vaccineName}`;
|
||||
generic.primaryFields.push(
|
||||
{
|
||||
key: "name",
|
||||
label: "",
|
||||
value: `${receipt.name} (${receipt.dateOfBirth})`
|
||||
label: `${receipt.name} (Last vaccinated: ${mostRecentReceipt.vaccinationDate})`,
|
||||
value: value
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
let fieldToPush;
|
||||
generic.secondaryFields.push({
|
||||
key: "details",
|
||||
label: "For details or to remove this pass",
|
||||
value: "Touch the circle with ... on the top right"
|
||||
});
|
||||
|
||||
generic.backFields.push({
|
||||
key: "date-of-birth",
|
||||
label: "Date of Birth",
|
||||
value: receipt.dateOfBirth
|
||||
});
|
||||
|
||||
for (let i = 0; i < receipt.vaccinations.length; i++) {
|
||||
|
||||
if (i <= 1)
|
||||
fieldToPush = generic.secondaryFields;
|
||||
else if (i <= 3)
|
||||
fieldToPush = generic.auxiliaryFields;
|
||||
else if (i <= 5)
|
||||
fieldToPush = generic.backFields;
|
||||
|
||||
fieldToPush.push(
|
||||
generic.backFields.push(
|
||||
{
|
||||
key: 'vaccine' + i,
|
||||
label: receipt.vaccinations[i].vaccineName,
|
||||
|
|
Loading…
Reference in New Issue