Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat widget optimization #759

Merged
merged 4 commits into from
Aug 16, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { UserRepository } from '@impler/dal';
import { LEAD_SIGNUP_USING } from '@shared/constants';
import { OnboardUserCommand } from './onboard-user.command';
import { LeadService } from '@shared/services/lead.service';
import { captureException } from '@shared/helpers/common.helper';
import { CreateProject, CreateProjectCommand } from 'app/project/usecases';

@Injectable()
Expand Down Expand Up @@ -33,15 +34,19 @@ export class OnboardUser {

const updatedUser = await this.userRepository.findOne({ _id: command._userId });
if (updatedUser) {
await this.leadService.createLead({
'First Name': updatedUser.firstName,
'Last Name': updatedUser.lastName,
'Lead Email': updatedUser.email,
'Lead Source': updatedUser.source,
'Mentioned Role': updatedUser.role,
'Signup Method': updatedUser.signupMethod as LEAD_SIGNUP_USING,
'Company Size': updatedUser.companySize,
});
try {
await this.leadService.createLead({
'First Name': updatedUser.firstName,
'Last Name': updatedUser.lastName,
'Lead Email': updatedUser.email,
'Lead Source': updatedUser.source,
'Mentioned Role': updatedUser.role,
'Signup Method': updatedUser.signupMethod as LEAD_SIGNUP_USING,
'Company Size': updatedUser.companySize,
});
} catch (error) {
captureException(error);
}
}

return createdProject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ export class RegisterUser {
screen: SCREENS.VERIFY,
token,
};
} else if (!!this.emailService.isConnected) {
return {
screen: SCREENS.ONBOARD,
token,
};
}

return {
screen: SCREENS.ONBOARD,
token,
};
}
}
7 changes: 6 additions & 1 deletion apps/api/src/app/auth/usecases/verify/verify.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SCREENS } from '@impler/shared';
import { VerifyCommand } from './verify.command';
import { PaymentAPIService } from '@impler/services';
import { AuthService } from 'app/auth/services/auth.service';
import { captureException } from '@shared/helpers/common.helper';
import { UserRepository, EnvironmentRepository } from '@impler/dal';
import { InvalidVerificationCodeException } from '@shared/exceptions/otp-verification.exception';

Expand Down Expand Up @@ -32,7 +33,11 @@ export class Verify {
externalId: user.email,
};

await this.paymentAPIService.createUser(userData);
try {
await this.paymentAPIService.createUser(userData);
} catch (error) {
captureException(error);
}

await this.userRepository.findOneAndUpdate(
{
Expand Down
7 changes: 7 additions & 0 deletions apps/api/src/app/shared/helpers/common.helper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as Sentry from '@sentry/node';
import { BadRequestException } from '@nestjs/common';
import { APIMessages } from '../constants';
import { PaginationResult, Defaults, FileMimeTypesEnum } from '@impler/shared';
Expand Down Expand Up @@ -76,3 +77,9 @@ export function generateVerificationCode(): string {

return otp;
}

export function captureException(error: any) {
if (Sentry.isInitialized()) {
Sentry.captureException(error);
} else console.error(error);
}
71 changes: 40 additions & 31 deletions apps/api/src/app/shared/services/lead.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios from 'axios';
import { Injectable } from '@nestjs/common';
import { LEAD_SIGNUP_USING } from '@shared/constants';
import { captureException } from '@shared/helpers/common.helper';

interface ILeadInformation {
'First Name': string;
Expand Down Expand Up @@ -82,45 +83,53 @@ export class LeadService {
const maUrl = `https://marketingautomation.zoho.com/api/v1/json/listsubscribe?listkey=${process.env.LEAD_LIST_KEY}&leadinfo=${leadData}&topic_id=${process.env.LEAD_TOPIC_ID}`;
if (this.log) console.log(maUrl);

const maResponse = await axios.post(
maUrl,
{},
{
headers: {
Authorization: `Zoho-oauthtoken ${maAccessToken}`,
},
}
);
if (this.log) console.log('Lead created', maResponse.data);
try {
const maResponse = await axios.post(
maUrl,
{},
{
headers: {
Authorization: `Zoho-oauthtoken ${maAccessToken}`,
},
}
);
if (this.log) console.log('Lead created', maResponse.data);
} catch (error) {
captureException(error);
}
}
const crmAccessToken = await this.getCRMAccessToken();
if (crmAccessToken) {
// Add Lead to Zoho CRM
const crmUrl = `https://www.zohoapis.com/crm/v6/Leads`;
if (this.log) console.log(crmUrl);

const crmResponse = await axios.post(
crmUrl,
{
data: [
{
Last_Name: data['Last Name'],
First_Name: data['First Name'],
Email: data['Lead Email'],
Lead_Source: data['Lead Source'],
Signup_Method: data['Signup Method'],
Mentioned_Role: data['Mentioned Role'],
Company_Size: data['Company Size'],
},
],
},
{
headers: {
Authorization: `Zoho-oauthtoken ${crmAccessToken}`,
try {
const crmResponse = await axios.post(
crmUrl,
{
data: [
{
Last_Name: data['Last Name'],
First_Name: data['First Name'],
Email: data['Lead Email'],
Lead_Source: data['Lead Source'],
Signup_Method: data['Signup Method'],
Mentioned_Role: data['Mentioned Role'],
Company_Size: [data['Company Size']],
},
],
},
}
);
if (this.log) console.log('CRM LEad created', crmResponse.data);
{
headers: {
Authorization: `Zoho-oauthtoken ${crmAccessToken}`,
},
}
);
if (this.log) console.log('CRM LEad created', crmResponse.data);
} catch (error) {
captureException(error);
}
}
}
}
30 changes: 28 additions & 2 deletions apps/widget/src/components/Common/Container/Container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ApiService } from '@impler/client';
import { MessageHandlerDataType } from '@types';
import { generateShades, ParentWindow, deepMerge } from '@util';
import { API_URL, colors, mantineConfig, variables } from '@config';
import { IWidgetShowPayload, WidgetEventTypesEnum, WIDGET_TEXTS } from '@impler/shared';
import { IWidgetShowPayload, WidgetEventTypesEnum, WIDGET_TEXTS, isObject } from '@impler/shared';

let api: ApiService;

Expand Down Expand Up @@ -48,9 +48,35 @@ export function Container({ children }: PropsWithChildren<{}>) {
}
setShowWidget(true);
setSecondaryPayload({
...data.value,
accessToken: data.value.accessToken,
host: data.value.host,
projectId: data.value.projectId,
uuid: data.value.uuid,
extra: isObject(data.value.extra) ? JSON.stringify(data.value.extra) : data.value.extra,
templateId: data.value.templateId,
authHeaderValue: data.value.authHeaderValue,
primaryColor: data.value.primaryColor || colors.primary,
colorScheme: data.value.colorScheme,
title: data.value.title,
texts: deepMerge(WIDGET_TEXTS, data.value.texts),
schema:
typeof data.value.schema === 'string'
? data.value.schema
: Array.isArray(data.value.schema)
? JSON.stringify(data.value.schema)
: undefined,
data:
typeof data.value.data === 'string'
? data.value.data
: Array.isArray(data.value.data)
? JSON.stringify(data.value.data)
: undefined,
output:
typeof data.value.output === 'string'
? data.value.output
: isObject(data.value.output)
? JSON.stringify(data.value.output)
: undefined,
});
} else if (data && data.type === WidgetEventTypesEnum.CLOSE_WIDGET) {
setShowWidget(false);
Expand Down
2 changes: 1 addition & 1 deletion apps/widget/src/components/Common/Provider/Provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface IProviderProps {
primaryColor: string;
output?: string;
schema?: string;
data?: Record<string, string | number>[];
data?: string;
host: string;
showWidget: boolean;
setShowWidget: (status: boolean) => void;
Expand Down
2 changes: 1 addition & 1 deletion apps/widget/src/hooks/useSample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export function useSample({ onDownloadComplete }: UseSampleProps) {
);
sampleData.append('schema', JSON.stringify(parsedSchema));
}
if (Array.isArray(data)) sampleData.append('data', JSON.stringify(data));
if (data) sampleData.append('data', data);
if (images && importId && imageSchema) {
const imagesBlob = await images.generateAsync({ type: 'blob', compression: 'DEFLATE' });
sampleData.append('file', imagesBlob);
Expand Down
4 changes: 2 additions & 2 deletions apps/widget/src/types/component.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IWidgetShowPayload } from '@impler/shared';
import { IUserShowPayload } from '@impler/shared';
import { EventTypesEnum, WidgetEventTypesEnum } from '@impler/shared';

export type MessageHandlerDataType =
Expand All @@ -7,7 +7,7 @@ export type MessageHandlerDataType =
}
| {
type: WidgetEventTypesEnum.SHOW_WIDGET;
value: IWidgetShowPayload;
value: IUserShowPayload;
}
| {
type: WidgetEventTypesEnum.CLOSE_WIDGET;
Expand Down
2 changes: 1 addition & 1 deletion apps/widget/src/types/store.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface IAppStore {
texts: typeof WIDGET_TEXTS;
importId?: string;
imageSchema?: string;
data?: Record<string, string | number>[];
data?: string;
templateInfo: ITemplate;
uploadInfo: IUpload;
reset: () => void;
Expand Down
27 changes: 15 additions & 12 deletions apps/widget/src/util/helpers/common.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import tippy from 'tippy.js';
import 'tippy.js/dist/tippy.css';
import 'tippy.js/animations/shift-away.css';
import { variables } from '@config';
import { downloadFile, WIDGET_TEXTS } from '@impler/shared';
import { convertStringToJson, downloadFile, isObject, WIDGET_TEXTS } from '@impler/shared';

// eslint-disable-next-line no-magic-numbers
export function formatBytes(bytes, decimals = 2) {
Expand Down Expand Up @@ -97,20 +97,23 @@ export const addTippyToElement = (element: SVGSVGElement | HTMLElement, content:
});
};

function isObject(value: any): boolean {
return value instanceof Object && value.constructor === Object;
}

// Utility function to deeply merge defaultTexts with user provided texts
export function deepMerge(defaultTexts: typeof WIDGET_TEXTS, texts?: typeof WIDGET_TEXTS): typeof WIDGET_TEXTS {
if (!texts || !isObject(texts)) return defaultTexts;
export function deepMerge(
defaultTexts: typeof WIDGET_TEXTS,
texts?: string | typeof WIDGET_TEXTS
): typeof WIDGET_TEXTS {
if (!texts) return defaultTexts;
let newTexts: typeof WIDGET_TEXTS | undefined;
if (typeof texts === 'string') newTexts = convertStringToJson(texts);
else newTexts = texts;
if (newTexts && !isObject(newTexts)) return defaultTexts;
else {
const mergedResult = { ...defaultTexts };
for (const sectionKey in texts) {
if (isObject(texts[sectionKey])) {
for (const textKey in texts[sectionKey]) {
if (mergedResult[sectionKey][textKey] && typeof texts[sectionKey][textKey] === 'string') {
mergedResult[sectionKey][textKey] = texts[sectionKey][textKey];
for (const sectionKey in newTexts) {
if (isObject(newTexts[sectionKey])) {
for (const textKey in newTexts[sectionKey]) {
if (mergedResult[sectionKey][textKey] && typeof newTexts[sectionKey][textKey] === 'string') {
mergedResult[sectionKey][textKey] = newTexts[sectionKey][textKey];
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions libs/shared/src/config/texts.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const WIDGET_TEXTS = {
CONFIRM_JOB: 'Confirm',
},
FILE_DROP_AREA: {
DROP_FILE: 'Drop and drop file here or ',
DROP_FILE: 'Drop and drop a file here or ',
BROWSE_FILE: 'Browse from computer',
IMAGE_FILE_SIZE: 'Image size should be less than 5 MB. Supported formats are PNG, JPG and JPEG.',
BRING_FILE: 'Bring any .csv or .xlsx file here to start Import',
Expand All @@ -31,7 +31,7 @@ export const WIDGET_TEXTS = {
PHASE1: {
SELECT_TEMPLATE_NAME: 'Template',
SELECT_TEMPLATE_NAME_PLACEHOLDER: 'Select Template',
SELECT_TEMPLATE_REQUIRED_MSG: 'Please select template from the list',
SELECT_TEMPLATE_REQUIRED_MSG: 'Please select a template from the list',

SELECT_SHEET_NAME: 'Select sheet to Import',
SELECT_SHEET_NAME_PLACEHOLDER: 'Select Excel sheet',
Expand All @@ -47,7 +47,7 @@ export const WIDGET_TEXTS = {
SELECT_FILE_FORMAT_MSG: 'File type not supported! Please select a .csv or .xlsx file.',

TEMPLATE_NOT_FOUND_MSG: "We couldn't find the template you're importing! Please check the passed parameters.",
INCOMPLETE_TEMPLATE_MSG: 'This import do not have any columns. Please try again after some time!',
INCOMPLETE_TEMPLATE_MSG: 'This import does not have any columns. Please try again after some time!',
},
PHASE2: {
REVIEW_DATA: 'Review Data',
Expand All @@ -63,8 +63,8 @@ export const WIDGET_TEXTS = {
},
PHASE4: {
TITLE: 'Bravo! {count} rows have been uploaded',
SUB_TITLE: '{count} rows have been uploaded successfully, and currently is in process, it will be ready shortly.',
UPLOAD_AGAIN: 'Upload new File',
SUB_TITLE: '{count} rows have been uploaded successfully and currently is in process, it will be ready shortly.',
UPLOAD_AGAIN: 'Upload New File',
},
AUTOIMPORT_PHASE1: {
MAPCOLUMN: 'Map Column',
Expand Down
16 changes: 12 additions & 4 deletions libs/shared/src/types/widget/widget.types.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
import { WIDGET_TEXTS } from '../../config/texts.config';
import { ISchemaItem } from '../column';

export interface ICommonShowPayload {
host: string;
extra?: string;
extra?: string | any;
templateId?: string;
authHeaderValue?: string;
primaryColor?: string;
colorScheme?: string;
title?: string;
schema?: string;
data?: Record<string, string | any>[];
output?: string;
projectId: string;
accessToken: string;
uuid: string;
}
export interface IWidgetShowPayload extends ICommonShowPayload {
texts?: typeof WIDGET_TEXTS;
data?: string;
schema?: string;
output?: string;
}

export interface IUserShowPayload extends ICommonShowPayload {
texts?: string | typeof WIDGET_TEXTS;
data?: string | Record<string, string | number>[];
schema?: string | ISchemaItem[];
output?: string | Record<string, string | number>;
}

export interface IOption {
Expand Down
Loading
Loading