Skip to content

Commit

Permalink
Add upload error
Browse files Browse the repository at this point in the history
Fix file selector
Copy fileupload class to components
  • Loading branch information
ayinloya committed Dec 19, 2023
1 parent 992a366 commit a4b3e95
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 57 deletions.
74 changes: 64 additions & 10 deletions packages/components/document-capture/DocumentCapture.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,23 @@ class DocumentCapture extends HTMLElement {
this.innerHTML = `
${styles}
<div>
<document-instruction ${this.hideInstructions ? 'hidden' : ''}></document-instruction>
<id-capture side-of-id='Front' id-type='National ID' ${this.hideInstructions ? '' : 'hidden'} ></id-capture>
<id-capture id='back-of-id' side-of-id='Back' id-type='National ID' hidden ></id-capture>
<document-instruction ${this.documentCaptureModes} ${this.showNavigation} ${this.hideInstructions ? 'hidden' : ''}></document-instruction>
<id-capture side-of-id='Front'
${this.title} ${this.showNavigation} ${this.hideInstructions ? '' : 'hidden'}
${this.documentCaptureModes}
></id-capture>
<document-instruction id='document-instruction-back' ${this.documentCaptureModes} ${this.showNavigation} hidden></document-instruction>
<id-capture id='back-of-id' side-of-id='Back' ${this.title} ${this.showNavigation}
${this.documentCaptureModes}
hidden
></id-capture>
<id-review hidden></id-review>
<id-review id='back-of-id-review' hidden></id-review>
<thank-you hidden></thank-you>
</div>
`;

console.log("documentCaptureModes", this.documentCaptureModes);

this._data = {
images: [],
meta: {
Expand All @@ -54,6 +62,7 @@ class DocumentCapture extends HTMLElement {
};

this.documentInstruction = this.querySelector('document-instruction');
this.documentInstructionBack = this.querySelector('#document-instruction-back');
this.idCapture = this.querySelector('id-capture');
this.idReview = this.querySelector('id-review');
this.idCaptureBack = this.querySelector('#back-of-id');
Expand Down Expand Up @@ -83,6 +92,14 @@ class DocumentCapture extends HTMLElement {
this.setActiveScreen(this.idCapture);
await getPermissions(this.idCapture);
});
this.documentInstruction.addEventListener('DocumentInstruction::DocumentChange', async (event) => {
this.idReview.setAttribute('data-image', event.detail.image);
this._data.images.push({
image: event.detail.image.split(',')[1],
image_type_id: IMAGE_TYPE.ID_CARD_IMAGE_BASE64,
});
this.setActiveScreen(this.idReview);
});

this.idCapture.addEventListener('IDCapture::ImageCaptured', (event) => {
this.idReview.setAttribute('data-image', event.detail.image);
Expand All @@ -94,22 +111,42 @@ class DocumentCapture extends HTMLElement {
this.setActiveScreen(this.idReview);
});

this.idReview.addEventListener('IdReview::ReCaptureID', async (event) => {
this.idReview.addEventListener('IdReview::ReCaptureID', async () => {
this.idReview.removeAttribute('data-image');
this._data.images.pop();
this.setActiveScreen(this.idCapture);
await getPermissions(this.idCapture);
if (this.hideInstructions) {
this.setActiveScreen(this.idCapture);
await getPermissions(this.idCapture);
}else {
this.setActiveScreen(this.documentInstruction);
}
});

this.idReview.addEventListener('IdReview::SelectImage', async () => {
if (this.hideBackOfId) {
this._publishSelectedImages();
} else {
} else if (this.hideInstructions) {
this.setActiveScreen(this.idCaptureBack);
await getPermissions(this.idCaptureBack);
} else {
this.setActiveScreen(this.documentInstructionBack);
}
});

this.documentInstructionBack.addEventListener('DocumentInstruction::StartCamera', async () => {
this.setActiveScreen(this.idCaptureBack);
await getPermissions(this.idCaptureBack);
});

this.documentInstructionBack.addEventListener('DocumentInstruction::DocumentChange', async (event) => {
console.log("image", event.detail.image);
this.idReview.setAttribute('data-image', event.detail.image);
this._data.images.push({
image: event.detail.image.split(',')[1],
image_type_id: IMAGE_TYPE.ID_CARD_BACK_IMAGE_BASE64,
});
this.setActiveScreen(this.backOfIdReview);
});
this.idCaptureBack.addEventListener('IDCapture::ImageCaptured', (event) => {
this.backOfIdReview.setAttribute('data-image', event.detail.image);
this._data.images.push({
Expand All @@ -123,8 +160,12 @@ class DocumentCapture extends HTMLElement {
this.backOfIdReview.addEventListener('IdReview::ReCaptureID', async (event) => {
this.backOfIdReview.removeAttribute('data-image');
this._data.images.pop();
this.setActiveScreen(this.idCaptureBack);
await getPermissions(this.idCaptureBack);
if (this.hideInstructions) {
this.setActiveScreen(this.idCaptureBack);
await getPermissions(this.idCaptureBack);
}else {
this.setActiveScreen(this.documentInstructionBack);
}
});

this.backOfIdReview.addEventListener('IdReview::SelectImage', () => {
Expand All @@ -146,6 +187,19 @@ class DocumentCapture extends HTMLElement {
return this.hasAttribute('hide-back-of-id');
}

get showNavigation() {
return this.hasAttribute('show-navigation') ? 'show-navigation' : '';
}

get title() {
return this.hasAttribute('title') ? `title=${this.getAttribute('title')}` : '';
}


get documentCaptureModes() {
return this.hasAttribute('document-capture-modes') ? `document-capture-modes='${this.getAttribute('document-capture-modes')}'` : '';
}

setActiveScreen(screen) {
this.activeScreen?.setAttribute('hidden', '');
screen.removeAttribute('hidden');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ export const DocumentCaptureHideBackOfId = {
`,
}

export const DocumentCaptureAllowAttributes = {
render: () => `
<document-capture
document-capture-modes='camera,upload'
>
</document-capture>
`,
}

export const DocumentCaptureHideInstructionNBackOfId = {
render: () => `
<document-capture
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"use strict";
import SmartFileUpload from "../../../domain/SmartFileUpload";
import Utils from "../../../domain/Util";
import styles from "../../../styles";

function templateString() {
Expand Down Expand Up @@ -258,6 +260,8 @@ function templateString() {
</p>
</div>
</div>
<div id="error" class='color-red'>
</div>
</div>
</section>
<section className="footer">
Expand Down Expand Up @@ -313,8 +317,7 @@ class DocumentInstruction extends HTMLElement {
this.takeDocumentPhotoButton = this.shadowRoot.querySelector('#take-photo');
this.uploadDocumentPhotoButton = this.shadowRoot.querySelector('#upload-photo');

const CloseIframeButtons =
this.shadowRoot.querySelectorAll(".close-iframe");
const CloseIframeButtons = this.shadowRoot.querySelectorAll(".close-iframe");

this.backButton && this.backButton.addEventListener("click", (e) => {
this.handleBackEvents(e);
Expand All @@ -333,17 +336,27 @@ class DocumentInstruction extends HTMLElement {
if (this.takeDocumentPhotoButton) this.takeDocumentPhotoButton.addEventListener('click', () => {
this.dispatchEvent(
new CustomEvent("DocumentInstruction::StartCamera", {
detail: {},
detail: {},
}),
);
);
});

if (this.uploadDocumentPhotoButton) this.uploadDocumentPhotoButton.addEventListener('change', (e) => {
this.dispatchEvent(
new CustomEvent("DocumentInstruction::DocumentChange", {
detail: {files: e.target.files},
}),
);
if (this.uploadDocumentPhotoButton) this.uploadDocumentPhotoButton.addEventListener('change', async (event) => {
this.shadowRoot.querySelector('#error').innerHTML = '';
try {
const { files } = event.target;

// validate file, and convert file to data url
const fileData = await SmartFileUpload.retrieve(files);

this.dispatchEvent(
new CustomEvent("DocumentInstruction::DocumentChange", {
detail: { image: fileData },
}),
);
} catch (error) {
this.shadowRoot.querySelector('#error').innerHTML = Utils.handleError(error);
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ class IdCaptureScreen extends HTMLElement {
}

get idType() {
return this.getAttribute('id-type');
return this.getAttribute('id-type') || "Document";
}

get cameraError() {
Expand Down
66 changes: 66 additions & 0 deletions packages/components/domain/SmartFileUpload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class SmartFileUpload {
static memoryLimit = 10240000;

static supportedTypes = ['image/jpeg', 'image/png'];

static getHumanSize(numberOfBytes) {
// Approximate to the closest prefixed unit
const units = [
'B',
'kB',
'MB',
'GB',
'TB',
'PB',
'EB',
'ZB',
'YB',
];
const exponent = Math.min(
Math.floor(Math.log(numberOfBytes) / Math.log(1024)),
units.length - 1,
);
const approx = numberOfBytes / 1024 ** exponent;
const output = exponent === 0
? `${numberOfBytes} bytes`
: `${approx.toFixed(0)} ${units[exponent]}`;

return output;
}

static getData(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();

reader.onload = (e) => {
resolve(e.target.result);
};
reader.onerror = () => {
reject(new Error('An error occurred reading the file. Please check the file, and try again'));
};
reader.readAsDataURL(file);
});
}

static async retrieve(files) {
if (files.length > 1) {
throw new Error('Only one file upload is permitted at a time');
}

const file = files[0];

if (!SmartFileUpload.supportedTypes.includes(file.type)) {
throw new Error('Unsupported file format. Please ensure that you are providing a JPG or PNG image');
}

if (file.size > SmartFileUpload.memoryLimit) {
throw new Error(`${file.name} is too large. Please ensure that the file is less than ${SmartFileUpload.getHumanSize(SmartFileUpload.memoryLimit)}.`);
}

const imageAsDataUrl = await SmartFileUpload.getData(file);

return imageAsDataUrl;
}
}

export default SmartFileUpload;
38 changes: 38 additions & 0 deletions packages/components/domain/Util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class Utils {
static handleError(e) {
switch (e.name) {
case 'NotAllowedError':
case 'SecurityError':
return `
Looks like camera access was not granted, or was blocked by a browser
level setting / extension. Please follow the prompt from the URL bar,
or extensions, and enable access.
You may need to refresh to start all over again
`;
case 'AbortError':
return `
Oops! Something happened, and we lost access to your stream.
Please refresh to start all over again
`;
case 'NotReadableError':
return `
There seems to be a problem with your device's camera, or its connection.
Please check this, and when resolved, try again. Or try another device.
`;
case 'NotFoundError':
return `
We are unable to find a video stream.
You may need to refresh to start all over again
`;
case 'TypeError':
return `
This site is insecure, and as such cannot have access to your camera.
Try to navigate to a secure version of this page, or contact the owner.
`;
default:
return e.message;
}
}
}

export default Utils;
35 changes: 0 additions & 35 deletions packages/components/domain/camera/SmartCamera.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,41 +36,6 @@ class SmartCamera {
const smallerModelNumber = 970; // S10e
return !isNaN(modelNumber) && modelNumber >= smallerModelNumber;
}

static handleError(e) {
switch (e.name) {
case 'NotAllowedError':
case 'SecurityError':
return `
Looks like camera access was not granted, or was blocked by a browser
level setting / extension. Please follow the prompt from the URL bar,
or extensions, and enable access.
You may need to refresh to start all over again
`;
case 'AbortError':
return `
Oops! Something happened, and we lost access to your stream.
Please refresh to start all over again
`;
case 'NotReadableError':
return `
There seems to be a problem with your device's camera, or its connection.
Please check this, and when resolved, try again. Or try another device.
`;
case 'NotFoundError':
return `
We are unable to find a video stream.
You may need to refresh to start all over again
`;
case 'TypeError':
return `
This site is insecure, and as such cannot have access to your camera.
Try to navigate to a secure version of this page, or contact the owner.
`;
default:
return e.message;
}
}
}

export { SmartCamera };
1 change: 0 additions & 1 deletion packages/components/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ ${typography}
img {
height: auto;
max-width: 100%;
transform: scaleX(-1);
}
video {
Expand Down

0 comments on commit a4b3e95

Please sign in to comment.