Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions apps/widget/src/hooks/Phase1/usePhase1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,18 @@ export function usePhase1({ goNext, texts, onManuallyEnterData }: IUsePhase1Prop
{
onSuccess(uploadData, uploadValues) {
ParentWindow.UploadStarted({ templateId: uploadData._templateId, uploadId: uploadData._id });
ParentWindow.UploadSuccess({ uploadId: uploadData._id, rowCount: uploadData.totalRecords });
ParentWindow.UploadStatusSuccess({ uploadId: uploadData._id, rowCount: uploadData.totalRecords });
setUploadInfo(uploadData);
if (uploadValues.file) goNext();
else onManuallyEnterData();
},
onError(error: IErrorObject) {
ParentWindow.UploadStatusError({ error, status: error.statusCode });
ParentWindow.UploadError({
errorCode: error.statusCode || 500,
errorMessage: error.message || 'Unknown Error',
});
ParentWindow.UploadStatusError(error);
resetField('file');
setError('file', {
type: 'file',
Expand All @@ -131,7 +136,6 @@ export function usePhase1({ goNext, texts, onManuallyEnterData }: IUsePhase1Prop
string[],
IErrorObject,
{ file: File }
// eslint-disable-next-line prettier/prettier
>(['getExcelSheetNames'], (excelSheetFile) => api.getExcelSheetNames(excelSheetFile), {
onSuccess(sheetNames) {
if (sheetNames.length <= 1) {
Expand Down
12 changes: 9 additions & 3 deletions apps/widget/src/util/parent-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ export function DataImported(value: Record<string, any>[]) {
export function ImportJobCreated(value: IUserJob) {
window.parent.postMessage({ type: EventTypesEnum.IMPORT_JOB_CREATED, value }, '*');
}
export function UploadSuccess(value: { uploadId: string; rowCount: number }) {
window.parent.postMessage({ type: EventTypesEnum.UPLOAD_SUCCESS, value }, '*');
}
export function UploadError(value: { errorCode: number; errorMessage: string }) {
window.parent.postMessage({ type: EventTypesEnum.UPLOAD_ERROR, value }, '*');
}

export function UploadStatusSuccess(value: { uploadId: string; rowCount: number }) {
window.parent.postMessage(
Expand All @@ -47,16 +53,16 @@ export function UploadStatusSuccess(value: { uploadId: string; rowCount: number
);
}

export function UploadStatusError(value: { error?: { message?: string }; status: number }) {
export function UploadStatusError(value: { message?: string; error?: string; statusCode?: number }) {
window.parent.postMessage(
{
source: 'impler-embed',
type: 'UPLOAD_STATUS',
payload: {
status: 'ERROR',
meta: {
errorCode: value.status || 500,
errorMessage: value.error?.message || 'Unknown Network Error',
errorCode: value.statusCode || 500,
errorMessage: value.message || value.error || 'Unknown Network Error',
timestamp: new Date().toISOString(),
},
},
Expand Down
4 changes: 4 additions & 0 deletions libs/embed/src/shared/eventTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export enum EventTypesEnum {
UPLOAD_STARTED = 'UPLOAD_STARTED',
UPLOAD_TERMINATED = 'UPLOAD_TERMINATED',
UPLOAD_COMPLETED = 'UPLOAD_COMPLETED',
UPLOAD_SUCCESS = 'UPLOAD_SUCCESS',
UPLOAD_ERROR = 'UPLOAD_ERROR',
DATA_IMPORTED = 'DATA_IMPORTED',
IMPORT_JOB_CREATED = 'IMPORT_JOB_CREATED',
}

export enum WidgetEventTypesEnum {
Expand Down
2 changes: 2 additions & 0 deletions libs/shared/src/types/widget/widget.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export enum EventTypesEnum {
UPLOAD_STARTED = 'UPLOAD_STARTED',
UPLOAD_TERMINATED = 'UPLOAD_TERMINATED',
UPLOAD_COMPLETED = 'UPLOAD_COMPLETED',
UPLOAD_SUCCESS = 'UPLOAD_SUCCESS',
UPLOAD_ERROR = 'UPLOAD_ERROR',
DATA_IMPORTED = 'DATA_IMPORTED',
IMPORT_JOB_CREATED = 'IMPORT_JOB_CREATED',
}
Expand Down
15 changes: 15 additions & 0 deletions packages/client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const EventTypes = {
UPLOAD_STARTED: 'UPLOAD_STARTED',
UPLOAD_TERMINATED: 'UPLOAD_TERMINATED',
UPLOAD_COMPLETED: 'UPLOAD_COMPLETED',
UPLOAD_SUCCESS: 'UPLOAD_SUCCESS',
UPLOAD_ERROR: 'UPLOAD_ERROR',
DATA_IMPORTED: 'DATA_IMPORTED',
IMPORT_JOB_CREATED: 'IMPORT_JOB_CREATED',
} as const;
Expand Down Expand Up @@ -135,6 +137,8 @@ export type UploadTemplateData = {
templateId: string;
};
export type UploadData = { uploadId: string };
export type UploadSuccessData = { uploadId: string; rowCount: number };
export type UploadErrorData = { errorCode: number; errorMessage: string };

export type EventCalls =
| {
Expand All @@ -157,6 +161,14 @@ export type EventCalls =
type: typeof EventTypes.IMPORT_JOB_CREATED;
value: IUserJob;
}
| {
type: typeof EventTypes.UPLOAD_SUCCESS;
value: UploadSuccessData;
}
| {
type: typeof EventTypes.UPLOAD_ERROR;
value: UploadErrorData;
}
| {
type: typeof EventTypes.CLOSE_WIDGET;
}
Expand Down Expand Up @@ -236,7 +248,10 @@ export interface IUseImplerProps {
onUploadStart?: (value: UploadTemplateData) => void;
onUploadTerminate?: (value: UploadData) => void;
onUploadComplete?: (value: IUpload) => void;
onUploadSuccess?: (value: UploadSuccessData) => void;
onDataImported?: (importedData: Record<string, any>[]) => void;
onWidgetClose?: () => void;
onImportJobCreated?: (jobInfo: IUserJob) => void;
onWidgetReady?: () => void;
onUploadError?: (error: UploadErrorData) => void;
}
51 changes: 48 additions & 3 deletions packages/react/src/hooks/useImpler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { isObject, EventTypes, logError, EventCalls, IShowWidgetProps, IUseImplerProps } from '@impler/client';

export function useImpler({
Expand All @@ -19,13 +19,29 @@ export function useImpler({
onDataImported,
onUploadTerminate,
onImportJobCreated,
onWidgetReady,
onUploadSuccess,
onUploadError,
}: IUseImplerProps) {
const [uuid] = useState(generateUuid());
const [isImplerInitiated, setIsImplerInitiated] = useState(false);
const onWidgetReadyCalledRef = useRef(false);

/*
* Use a ref so the listener always calls the latest version of callbacks
* without needing to re-register with the embed library
*/
const onEventHappenRef = useRef<(eventData: EventCalls) => void>(() => {});

const onEventHappen = useCallback(
(eventData: EventCalls) => {
switch (eventData.type) {
case EventTypes.WIDGET_READY:
if (onWidgetReady && !onWidgetReadyCalledRef.current) {
onWidgetReadyCalledRef.current = true;
onWidgetReady();
}
break;
case EventTypes.UPLOAD_STARTED:
if (onUploadStart) onUploadStart(eventData.value);
break;
Expand All @@ -35,6 +51,12 @@ export function useImpler({
case EventTypes.UPLOAD_COMPLETED:
if (onUploadComplete) onUploadComplete(eventData.value);
break;
case EventTypes.UPLOAD_SUCCESS:
if (onUploadSuccess) onUploadSuccess(eventData.value);
break;
case EventTypes.UPLOAD_ERROR:
if (onUploadError) onUploadError(eventData.value);
break;
case EventTypes.DATA_IMPORTED:
if (onDataImported) onDataImported(eventData.value);
break;
Expand All @@ -46,13 +68,32 @@ export function useImpler({
break;
}
},
[onUploadComplete, onUploadStart, onUploadTerminate, onWidgetClose]
[
onUploadComplete,
onUploadStart,
onUploadTerminate,
onWidgetClose,
onDataImported,
onImportJobCreated,
onWidgetReady,
onUploadSuccess,
onUploadError,
]
);

// Keep ref in sync with latest callback
useEffect(() => {
onEventHappenRef.current = onEventHappen;
}, [onEventHappen]);

useEffect(() => {
const readyCheckInterval = setInterval(() => {
if (window.impler && window.impler.isReady()) {
setIsImplerInitiated(true);
if (onWidgetReady && !onWidgetReadyCalledRef.current) {
onWidgetReadyCalledRef.current = true;
onWidgetReady();
}
clearInterval(readyCheckInterval);
}
}, 1000);
Expand All @@ -66,7 +107,11 @@ export function useImpler({
if (!window.impler) logError('IMPLER_UNDEFINED_ERROR');
else {
window.impler.init(uuid);
window.impler.on('message', onEventHappen, uuid);
/*
* Use a stable wrapper that delegates to the ref,
* so the embed always calls the latest version of onEventHappen
*/
window.impler.on('message', (data: EventCalls) => onEventHappenRef.current(data), uuid);
}
}, []);

Expand Down
Loading