From aaffc5880634b6ed0bf4835d26f2be592ce3c820 Mon Sep 17 00:00:00 2001 From: Niloofar Sadeghi Date: Sun, 9 Oct 2022 13:26:42 +0330 Subject: [PATCH 1/4] refactor: convert date, digital-options, dom and files to ts --- .../{date-time.spec.js => date-time.spec.ts} | 3 +- .../utils/date/{date-time.js => date-time.ts} | 94 +++++++++++-------- .../src/utils/date/{index.js => index.ts} | 0 .../utils/digital-options/digital-options.js | 21 ----- .../utils/digital-options/digital-options.ts | 42 +++++++++ .../digital-options/{index.js => index.ts} | 0 .../src/utils/dom/{index.js => index.ts} | 0 .../utils/dom/{position.js => position.ts} | 28 +++++- ...eo_optimization.js => seo_optimization.ts} | 8 +- ...loader-utils.js => file-uploader-utils.ts} | 62 +++++++++--- .../{image_utility.js => image_utility.ts} | 40 +++++--- .../src/utils/files/{index.js => index.ts} | 0 12 files changed, 202 insertions(+), 96 deletions(-) rename packages/shared/src/utils/date/__tests__/{date-time.spec.js => date-time.spec.ts} (97%) rename packages/shared/src/utils/date/{date-time.js => date-time.ts} (62%) rename packages/shared/src/utils/date/{index.js => index.ts} (100%) delete mode 100644 packages/shared/src/utils/digital-options/digital-options.js create mode 100644 packages/shared/src/utils/digital-options/digital-options.ts rename packages/shared/src/utils/digital-options/{index.js => index.ts} (100%) rename packages/shared/src/utils/dom/{index.js => index.ts} (100%) rename packages/shared/src/utils/dom/{position.js => position.ts} (77%) rename packages/shared/src/utils/dom/{seo_optimization.js => seo_optimization.ts} (57%) rename packages/shared/src/utils/files/{file-uploader-utils.js => file-uploader-utils.ts} (58%) rename packages/shared/src/utils/files/image/{image_utility.js => image_utility.ts} (61%) rename packages/shared/src/utils/files/{index.js => index.ts} (100%) diff --git a/packages/shared/src/utils/date/__tests__/date-time.spec.js b/packages/shared/src/utils/date/__tests__/date-time.spec.ts similarity index 97% rename from packages/shared/src/utils/date/__tests__/date-time.spec.js rename to packages/shared/src/utils/date/__tests__/date-time.spec.ts index 2110a96d4e21..41235d9e75ac 100644 --- a/packages/shared/src/utils/date/__tests__/date-time.spec.js +++ b/packages/shared/src/utils/date/__tests__/date-time.spec.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import moment from 'moment'; import 'moment/min/locales'; -import * as DateTime from '../date-time.js'; +import * as DateTime from '../date-time'; describe('toMoment', () => { it('return utc epoch value date based on client epoch value passed', () => { @@ -64,6 +64,7 @@ describe('formatDate', () => { }); }); +/* eslint-disable no-unused-expressions */ describe('daysFromTodayTo', () => { it('return empty string when there is no argument passed', () => { expect(DateTime.daysFromTodayTo()).to.be.empty; diff --git a/packages/shared/src/utils/date/date-time.js b/packages/shared/src/utils/date/date-time.ts similarity index 62% rename from packages/shared/src/utils/date/date-time.js rename to packages/shared/src/utils/date/date-time.ts index bd30ab91cea2..844bc3426aa7 100644 --- a/packages/shared/src/utils/date/date-time.js +++ b/packages/shared/src/utils/date/date-time.ts @@ -1,21 +1,25 @@ import moment from 'moment'; import 'moment/min/locales'; +type TExtendedMoment = typeof moment & { + createFromInputFallback: (config: { _d: Date }) => void; +}; + // Disables moment's fallback to native Date object // moment will return `Invalid Date` if date cannot be parsed -moment.createFromInputFallback = function (config) { +(moment as TExtendedMoment).createFromInputFallback = function (config) { config._d = new Date(NaN); // eslint-disable-line no-underscore-dangle }; // Localize moment instance with specific object -export const initMoment = lang => moment.locale(lang); +export const initMoment = (lang: string) => moment.locale(lang); /** * Convert epoch to moment object * @param {Number} epoch * @return {moment} the moment object of provided epoch */ -export const epochToMoment = epoch => moment.unix(epoch).utc(); +export const epochToMoment = (epoch: number) => moment.unix(epoch).utc(); /** * Convert date string or epoch to moment object @@ -23,33 +27,34 @@ export const epochToMoment = epoch => moment.unix(epoch).utc(); * @param {String} value the date in string format * @return {moment} the moment object of 'now' or the provided date epoch or string */ -export const toMoment = value => { +export const toMoment = (value?: moment.MomentInput): moment.Moment => { if (!value) return moment().utc(); // returns 'now' moment object - if (value instanceof moment && value.isValid() && value.isUTC()) return value; // returns if already a moment object + if (value instanceof moment && (value as moment.Moment).isValid() && (value as moment.Moment).isUTC()) + return value as moment.Moment; // returns if already a moment object if (typeof value === 'number') return epochToMoment(value); // returns epochToMoment() if not a date - if (/invalid/i.test(moment(value))) { + if (/invalid/i.test(moment(value).toString())) { const today_moment = moment(); return value > today_moment.utc().daysInMonth() - ? moment.utc(today_moment.add(value, 'd'), 'DD MMM YYYY') + ? moment.utc(today_moment.add(value as string | number, 'd'), 'DD MMM YYYY') : moment.utc(value, 'DD MMM YYYY'); // returns target date } return moment.utc(value); }; -export const toLocalFormat = time => moment.utc(time).local().format('YYYY-MM-DD HH:mm:ss Z'); +export const toLocalFormat = (time: moment.MomentInput) => moment.utc(time).local().format('YYYY-MM-DD HH:mm:ss Z'); /** * Set specified time on moment object * @param {moment} moment_obj the moment to set the time on * @param {String} time 24 hours format, may or may not include seconds * @return {moment} a new moment object of result */ -export const setTime = (moment_obj, time) => { +export const setTime = (moment_obj: moment.Moment, time: string) => { const [hour, minute, second] = time ? time.split(':') : [0, 0, 0]; moment_obj - .hour(hour) - .minute(minute || 0) - .second(second || 0); + .hour(+hour) + .minute(+minute || 0) + .second(+second || 0); return moment_obj; }; @@ -59,23 +64,24 @@ export const setTime = (moment_obj, time) => { * @param {String} time the time to set on the date * @return {Number} unix value of the result */ -export const convertToUnix = (epoch, time) => setTime(toMoment(epoch), time).unix(); +export const convertToUnix = (epoch: number | string, time: string) => setTime(toMoment(epoch), time).unix(); -export const toGMTFormat = time => +export const toGMTFormat = (time?: moment.MomentInput) => moment(time || undefined) .utc() .format('YYYY-MM-DD HH:mm:ss [GMT]'); -export const formatDate = (date, date_format = 'YYYY-MM-DD') => toMoment(date).format(date_format); +export const formatDate = (date?: moment.MomentInput, date_format = 'YYYY-MM-DD') => toMoment(date).format(date_format); -export const formatTime = (epoch, time_format = 'HH:mm:ss [GMT]') => toMoment(epoch).format(time_format); +export const formatTime = (epoch: number | string, time_format = 'HH:mm:ss [GMT]') => + toMoment(epoch).format(time_format); /** * return the number of days from today to date specified * @param {String} date the date to calculate number of days from today * @return {Number} an integer of the number of days */ -export const daysFromTodayTo = date => { +export const daysFromTodayTo = (date?: string) => { const diff = toMoment(date).startOf('day').diff(toMoment().startOf('day'), 'days'); return !date || diff < 0 ? '' : diff; }; @@ -85,7 +91,7 @@ export const daysFromTodayTo = date => { * @param {String} date the date to calculate number of days since * @return {Number} an integer of the number of days */ -export const daysSince = date => { +export const daysSince = (date: string) => { const diff = toMoment().startOf('day').diff(toMoment(date).startOf('day'), 'days'); return !date ? '' : diff; }; @@ -93,18 +99,22 @@ export const daysSince = date => { /** * return the number of months between two specified dates */ -export const diffInMonths = (now, then) => then.diff(now, 'month'); +export const diffInMonths = (now: moment.MomentInput, then: moment.Moment) => then.diff(now, 'month'); /** * return moment duration between two dates * @param {Number} epoch start time * @param {Number} epoch end time * @return {moment.duration} moment duration between start time and end time */ -export const getDiffDuration = (start_time, end_time) => +export const getDiffDuration = (start_time: number, end_time: number) => moment.duration(moment.unix(end_time).diff(moment.unix(start_time))); /** returns the DD MM YYYY format */ -export const getDateFromNow = (days, unit, format) => { +export const getDateFromNow = ( + days: string | number, + unit?: moment.unitOfTime.DurationConstructor, + format?: string +) => { const date = moment(new Date()); return date.add(days, unit).format(format); }; @@ -114,7 +124,7 @@ export const getDateFromNow = (days, unit, format) => { * @param {moment.duration} moment duration object * @return {String} formatted display string */ -export const formatDuration = (duration, format) => { +export const formatDuration = (duration: moment.Duration, format?: string) => { const d = Math.floor(duration.asDays()); // duration.days() does not include months/years const h = duration.hours(); const m = duration.minutes(); @@ -135,95 +145,99 @@ export const formatDuration = (duration, format) => { * return true if the time_str is in "HH:MM" format, else return false * @param {String} time_str time */ -export const isTimeValid = time_str => +export const isTimeValid = (time_str: string) => /^([0-9]|[0-1][0-9]|2[0-3]):([0-9]|[0-5][0-9])(:([0-9]|[0-5][0-9]))?$/.test(time_str); /** * return true if the time_str's hour is between 0 and 23, else return false * @param {String} time_str time */ -export const isHourValid = time_str => isTimeValid(time_str) && /^([01][0-9]|2[0-3])$/.test(time_str.split(':')[0]); +export const isHourValid = (time_str: string) => + isTimeValid(time_str) && /^([01][0-9]|2[0-3])$/.test(time_str.split(':')[0]); /** * return true if the time_str's minute is between 0 and 59, else return false * @param {String} time_str time */ -export const isMinuteValid = time_str => isTimeValid(time_str) && /^[0-5][0-9]$/.test(time_str.split(':')[1]); +export const isMinuteValid = (time_str: string) => isTimeValid(time_str) && /^[0-5][0-9]$/.test(time_str.split(':')[1]); /** * return true if the date is typeof string and a valid moment date, else return false * @param {String|moment} date date */ -export const isDateValid = date => moment(date, 'DD MMM YYYY').isValid(); +export const isDateValid = (date: moment.MomentInput) => moment(date, 'DD MMM YYYY').isValid(); /** * add the specified number of days to the given date * @param {String} date date * @param {Number} num_of_days number of days to add */ -export const addDays = (date, num_of_days) => toMoment(date).clone().add(num_of_days, 'day'); +export const addDays = (date: string, num_of_days: number) => toMoment(date).clone().add(num_of_days, 'day'); /** * add the specified number of weeks to the given date * @param {String} date date * @param {Number} num_of_weeks number of days to add */ -export const addWeeks = (date, num_of_weeks) => toMoment(date).clone().add(num_of_weeks, 'week'); +export const addWeeks = (date: string, num_of_weeks: number) => toMoment(date).clone().add(num_of_weeks, 'week'); /** * add the specified number of months to the given date * @param {String} date date * @param {Number} num_of_months number of months to add */ -export const addMonths = (date, num_of_months) => toMoment(date).clone().add(num_of_months, 'month'); +export const addMonths = (date: string, num_of_months: number) => toMoment(date).clone().add(num_of_months, 'month'); /** * add the specified number of years to the given date * @param {String} date date * @param {Number} num_of_years number of years to add */ -export const addYears = (date, num_of_years) => toMoment(date).clone().add(num_of_years, 'year'); +export const addYears = (date: string, num_of_years: number) => toMoment(date).clone().add(num_of_years, 'year'); /** * subtract the specified number of days from the given date * @param {String} date date * @param {Number} num_of_days number of days to subtract */ -export const subDays = (date, num_of_days) => toMoment(date).clone().subtract(num_of_days, 'day'); +export const subDays = (date: string, num_of_days: number) => toMoment(date).clone().subtract(num_of_days, 'day'); /** * subtract the specified number of months from the given date * @param {String} date date * @param {Number} num_of_months number of months to subtract */ -export const subMonths = (date, num_of_months) => toMoment(date).clone().subtract(num_of_months, 'month'); +export const subMonths = (date: string, num_of_months: number) => + toMoment(date).clone().subtract(num_of_months, 'month'); /** * subtract the specified number of years from the given date * @param {String} date date * @param {Number} num_of_years number of years to subtract */ -export const subYears = (date, num_of_years) => toMoment(date).clone().subtract(num_of_years, 'year'); +export const subYears = (date: string, num_of_years: number) => toMoment(date).clone().subtract(num_of_years, 'year'); /** * returns the minimum moment between the two passing parameters * @param {moment|string|epoch} first datetime parameter * @param {moment|string|epoch} second datetime parameter */ -export const minDate = (date_1, date_2) => moment.min(toMoment(date_1), toMoment(date_2)); +export const minDate = (date_1: moment.MomentInput, date_2: moment.MomentInput) => + moment.min(toMoment(date_1), toMoment(date_2)); /** * returns a new date * @param {moment|string|epoch} date date */ -export const getStartOfMonth = date => toMoment(date).clone().startOf('month').format('YYYY-MM-DD'); +export const getStartOfMonth = (date: moment.MomentInput) => + toMoment(date).clone().startOf('month').format('YYYY-MM-DD'); /** * returns miliseconds into UTC formatted string * @param {Number} miliseconds miliseconds * @param {String} str_format formatting using moment e.g - YYYY-MM-DD HH:mm */ -export const formatMilliseconds = (miliseconds, str_format, is_local_time = false) => { +export const formatMilliseconds = (miliseconds: moment.MomentInput, str_format: string, is_local_time = false) => { if (is_local_time) { return moment(miliseconds).format(str_format); } @@ -236,7 +250,7 @@ export const formatMilliseconds = (miliseconds, str_format, is_local_time = fals * @param {String} from_date_format initial date format * @param {String} to_date_format to date format */ -export const convertDateFormat = (date, from_date_format, to_date_format) => +export const convertDateFormat = (date: moment.MomentInput, from_date_format: string, to_date_format: string) => moment(date, from_date_format).format(to_date_format); /** @@ -244,11 +258,11 @@ export const convertDateFormat = (date, from_date_format, to_date_format) => * @param {String} time 24 hours format, may or may not include seconds * @return {String} equivalent 12-hour time */ -export const convertTimeFormat = time => { +export const convertTimeFormat = (time: string) => { const time_moment_obj = moment(time, 'HH:mm'); const time_hour = time_moment_obj.format('HH'); const time_min = time_moment_obj.format('mm'); - const formatted_time = `${Number(time_hour % 12) || 12}:${time_min}`; - const time_suffix = `${Number(time_hour >= 12) ? 'pm' : 'am'}`; + const formatted_time = `${Number(time_hour) % 12 || 12}:${time_min}`; + const time_suffix = `${Number(time_hour) >= 12 ? 'pm' : 'am'}`; return `${formatted_time} ${time_suffix}`; }; diff --git a/packages/shared/src/utils/date/index.js b/packages/shared/src/utils/date/index.ts similarity index 100% rename from packages/shared/src/utils/date/index.js rename to packages/shared/src/utils/date/index.ts diff --git a/packages/shared/src/utils/digital-options/digital-options.js b/packages/shared/src/utils/digital-options/digital-options.js deleted file mode 100644 index 671fb13c5ba0..000000000000 --- a/packages/shared/src/utils/digital-options/digital-options.js +++ /dev/null @@ -1,21 +0,0 @@ -import { isEuCountry } from '../location'; - -export const showDigitalOptionsUnavailableError = (showError, message) => { - const { title, text, link } = message; - showError({ - message: text, - header: title, - redirect_label: link, - redirectOnClick: null, - should_show_refresh: false, - redirect_to: '/mt5', - should_clear_error_on_click: true, - }); -}; - -export const isEuResidenceWithOnlyVRTC = accounts => { - return ( - accounts?.length === 1 && - accounts.every(acc => isEuCountry(acc.residence) && acc.landing_company_shortcode === 'virtual') - ); -}; diff --git a/packages/shared/src/utils/digital-options/digital-options.ts b/packages/shared/src/utils/digital-options/digital-options.ts new file mode 100644 index 000000000000..520906a01f13 --- /dev/null +++ b/packages/shared/src/utils/digital-options/digital-options.ts @@ -0,0 +1,42 @@ +import { isEuCountry } from '../location'; + +type TMessage = { + title: string; + text: string; + link: string; +}; + +type TShowError = { + message: string; + header: string; + redirect_label: string; + redirectOnClick: null; + should_show_refresh: boolean; + redirect_to: string; + should_clear_error_on_click: boolean; +}; + +export const showDigitalOptionsUnavailableError = (showError: (t: TShowError) => void, message: TMessage) => { + const { title, text, link } = message; + showError({ + message: text, + header: title, + redirect_label: link, + redirectOnClick: null, + should_show_refresh: false, + redirect_to: '/mt5', + should_clear_error_on_click: true, + }); +}; + +type TAccounts = { + residence?: string; + landing_company_shortcode?: string; +}; + +export const isEuResidenceWithOnlyVRTC = (accounts: TAccounts[]) => { + return ( + accounts?.length === 1 && + accounts.every(acc => isEuCountry(acc.residence) && acc.landing_company_shortcode === 'virtual') + ); +}; diff --git a/packages/shared/src/utils/digital-options/index.js b/packages/shared/src/utils/digital-options/index.ts similarity index 100% rename from packages/shared/src/utils/digital-options/index.js rename to packages/shared/src/utils/digital-options/index.ts diff --git a/packages/shared/src/utils/dom/index.js b/packages/shared/src/utils/dom/index.ts similarity index 100% rename from packages/shared/src/utils/dom/index.js rename to packages/shared/src/utils/dom/index.ts diff --git a/packages/shared/src/utils/dom/position.js b/packages/shared/src/utils/dom/position.ts similarity index 77% rename from packages/shared/src/utils/dom/position.js rename to packages/shared/src/utils/dom/position.ts index 4d4f3fb28a33..d0778ed37638 100644 --- a/packages/shared/src/utils/dom/position.js +++ b/packages/shared/src/utils/dom/position.ts @@ -1,14 +1,36 @@ -const getMaxHeightByAligningBottom = ({ parent_rect, child_height }) => +type RectResult = { + bottom: number; + height: number; + left: number; + right: number; + top: number; + width: number; +}; + +type TGetMaxHeightByAligning = { + parent_rect: RectResult; + child_height: number; +}; + +type TGetPosition = { + preferred_alignment: string; + child_el: HTMLElement; + parent_el: HTMLElement; + should_consider_parent_height: boolean; +}; + +const getMaxHeightByAligningBottom = ({ parent_rect, child_height }: TGetMaxHeightByAligning) => parent_rect.top + parent_rect.height + child_height; -const getMinHeightByAligningTop = ({ parent_rect, child_height }) => parent_rect.top - child_height; +const getMinHeightByAligningTop = ({ parent_rect, child_height }: TGetMaxHeightByAligning) => + parent_rect.top - child_height; export const getPosition = ({ preferred_alignment = 'bottom', child_el, parent_el, should_consider_parent_height = true, -}) => { +}: TGetPosition) => { const parent_rect = parent_el.getBoundingClientRect(); const child_height = child_el.clientHeight; const body_rect = document.body.getBoundingClientRect(); diff --git a/packages/shared/src/utils/dom/seo_optimization.js b/packages/shared/src/utils/dom/seo_optimization.ts similarity index 57% rename from packages/shared/src/utils/dom/seo_optimization.js rename to packages/shared/src/utils/dom/seo_optimization.ts index 5187e1af0d7f..3910d97a2feb 100644 --- a/packages/shared/src/utils/dom/seo_optimization.js +++ b/packages/shared/src/utils/dom/seo_optimization.ts @@ -3,15 +3,15 @@ import { deriv_urls } from '../url/constants'; export const alternateLinkTagChange = () => { const current_search_params = new URLSearchParams(location.search); const current_lang = current_search_params.get('lang') - ? `${current_search_params.get('lang').toLowerCase()}` + ? `${current_search_params.get('lang')?.toLowerCase()}` : 'en'; const alternate_rel_link = document.querySelector("link[rel='alternate']"); - alternate_rel_link.setAttribute('hreflang', current_lang); - alternate_rel_link.setAttribute('href', `${deriv_urls.DERIV_APP_PRODUCTION}${location.pathname}`); + alternate_rel_link?.setAttribute('hreflang', current_lang); + alternate_rel_link?.setAttribute('href', `${deriv_urls.DERIV_APP_PRODUCTION}${location.pathname}`); }; export const canonicalLinkTagChange = () => { const canonical_rel_link = document.querySelector("link[rel='canonical']"); - canonical_rel_link.setAttribute('href', `${deriv_urls.DERIV_APP_PRODUCTION}${location.pathname}`); + canonical_rel_link?.setAttribute('href', `${deriv_urls.DERIV_APP_PRODUCTION}${location.pathname}`); }; diff --git a/packages/shared/src/utils/files/file-uploader-utils.js b/packages/shared/src/utils/files/file-uploader-utils.ts similarity index 58% rename from packages/shared/src/utils/files/file-uploader-utils.js rename to packages/shared/src/utils/files/file-uploader-utils.ts index 6a3447b6cb0b..7b3342467f19 100644 --- a/packages/shared/src/utils/files/file-uploader-utils.js +++ b/packages/shared/src/utils/files/file-uploader-utils.ts @@ -1,21 +1,56 @@ -import { compressImg, convertToBase64, isImageType, getFormatFromMIME } from './image/image_utility'; +import { compressImg, convertToBase64, isImageType, getFormatFromMIME, TImage } from './image/image_utility'; -export const truncateFileName = (file, limit) => { +export type TFile = File & { file: Blob }; + +type TSettings = { + documentType: { + passport: string; + national_identity_card: string; + driving_licence: string; + utility_bill: string; + bankstatement: string; + power_of_attorney: string; + amlglobalcheck: string; + docverification: string; + proofid: string; + driverslicense: string; + proofaddress: string; + other: string; + }; + pageType: { + front: string; + back: string; + photo: string; + }; + expirationDate?: string; + documentId?: string; + lifetimeValid?: boolean; +}; + +type TFileObject = TSettings & { + filename: File['name']; + buffer: FileReader['result']; + documentFormat: string; + file_size: File['size']; +}; + +export const truncateFileName = (file: TFile, limit: number) => { const string_limit_regex = new RegExp(`(.{${limit || 30}})..+`); return file?.name?.replace(string_limit_regex, `$1….${getFileExtension(file)}`); }; -export const getFileExtension = file => { - return file?.type?.match(/[^/]+$/)[0]; +export const getFileExtension = (file: TFile) => { + const f = file?.type?.match(/[^/]+$/); + return f && f[0]; }; -export const compressImageFiles = files => { - const promises = []; +export const compressImageFiles = (files: TFile[]) => { + const promises: Promise[] = []; files.forEach(f => { - const promise = new Promise(resolve => { + const promise = new Promise(resolve => { if (isImageType(f.type)) { convertToBase64(f).then(img => { - compressImg(img).then(compressed_img => { + compressImg(img as TImage).then(compressed_img => { const file_arr = f; file_arr.file = compressed_img; resolve(file_arr.file); @@ -31,20 +66,20 @@ export const compressImageFiles = files => { return Promise.all(promises); }; -export const readFiles = (files, getFileReadErrorMessage, settings) => { - const promises = []; +export const readFiles = (files: TFile[], getFileReadErrorMessage: (t: string) => string, settings: TSettings) => { + const promises: Promise[] = []; files.forEach(f => { const fr = new FileReader(); - const promise = new Promise(resolve => { + const promise = new Promise(resolve => { fr.onload = () => { const file_obj = { filename: f.name, buffer: fr.result, - documentType: settings?.documentType || 'utility_bill', documentFormat: getFormatFromMIME(f), file_size: f.size, ...settings, + documentType: settings?.documentType || 'utility_bill', }; resolve(file_obj); }; @@ -92,4 +127,5 @@ export const PAGE_TYPE = { photo: 'photo', }; -export const getSupportedFiles = filename => /^.*\.(png|PNG|jpg|JPG|jpeg|JPEG|gif|GIF|pdf|PDF)$/.test(filename); +export const getSupportedFiles = (filename: string) => + /^.*\.(png|PNG|jpg|JPG|jpeg|JPEG|gif|GIF|pdf|PDF)$/.test(filename); diff --git a/packages/shared/src/utils/files/image/image_utility.js b/packages/shared/src/utils/files/image/image_utility.ts similarity index 61% rename from packages/shared/src/utils/files/image/image_utility.js rename to packages/shared/src/utils/files/image/image_utility.ts index 37abbc428bb3..f0f140b8be57 100644 --- a/packages/shared/src/utils/files/image/image_utility.js +++ b/packages/shared/src/utils/files/image/image_utility.ts @@ -1,12 +1,29 @@ -require('canvas-toBlob'); +import 'canvas-toBlob'; +import { TFile } from '../file-uploader-utils'; -const compressImg = image => +declare global { + interface Blob { + lastModifiedDate: number; + name: string; + } +} + +export type TImage = { + src: string; + filename: string; +}; + +const compressImg = (image: TImage): Promise => new Promise(resolve => { const img = new Image(); img.src = image.src; img.onload = () => { - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); + const canvas: HTMLCanvasElement = document.createElement('canvas'); + const canvas_res = canvas.getContext('2d'); + if (!canvas_res || !(canvas_res instanceof CanvasRenderingContext2D)) { + throw new Error('Failed to get 2D context'); + } + const context: CanvasRenderingContext2D = canvas_res; if (img.naturalWidth > 2560) { const width = 2560; const scaleFactor = width / img.naturalWidth; @@ -26,7 +43,7 @@ const compressImg = image => canvas.toBlob( blob => { const filename = image.filename.replace(/\.[^/.]+$/, '.jpg'); - const file = new Blob([blob], { + const file = new Blob([blob as BlobPart], { type: 'image/jpeg', }); file.lastModifiedDate = Date.now(); @@ -39,7 +56,7 @@ const compressImg = image => }; }); -const convertToBase64 = file => +const convertToBase64 = (file: TFile) => new Promise(resolve => { const reader = new FileReader(); reader.readAsDataURL(file); @@ -49,14 +66,9 @@ const convertToBase64 = file => }; }); -const isImageType = filename => /(gif|jpg|jpeg|tiff|png)$/i.test(filename); +const isImageType = (filename: string) => /(gif|jpg|jpeg|tiff|png)$/i.test(filename); -const getFormatFromMIME = file => +const getFormatFromMIME = (file: TFile) => (file.type.split('/')[1] || (file.name.match(/\.([\w\d]+)$/) || [])[1] || '').toUpperCase(); -module.exports = { - compressImg, - convertToBase64, - isImageType, - getFormatFromMIME, -}; +export { compressImg, convertToBase64, isImageType, getFormatFromMIME }; diff --git a/packages/shared/src/utils/files/index.js b/packages/shared/src/utils/files/index.ts similarity index 100% rename from packages/shared/src/utils/files/index.js rename to packages/shared/src/utils/files/index.ts From 85f468e6d28a92f1f7046d4eb20b0c6bb2c791f8 Mon Sep 17 00:00:00 2001 From: Niloofar Sadeghi Date: Sun, 9 Oct 2022 14:05:17 +0330 Subject: [PATCH 2/4] build: remove @types/moment --- package-lock.json | 18 ------------------ packages/shared/package.json | 1 - 2 files changed, 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index b91af5d392af..7050ed3f15a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,6 @@ "@testing-library/user-event": "^13.2.1", "@types/classnames": "^2.2.11", "@types/js-cookie": "^3.0.1", - "@types/moment": "^2.13.0", "@types/object.fromentries": "^2.0.0", "@types/qrcode.react": "^1.0.2", "@types/react-loadable": "^5.5.6", @@ -14819,15 +14818,6 @@ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" }, - "node_modules/@types/moment": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/@types/moment/-/moment-2.13.0.tgz", - "integrity": "sha512-DyuyYGpV6r+4Z1bUznLi/Y7HpGn4iQ4IVcGn8zrr1P4KotKLdH0sbK1TFR6RGyX6B+G8u83wCzL+bpawKU/hdQ==", - "deprecated": "This is a stub types definition for Moment (https://github.com/moment/moment). Moment provides its own type definitions, so you don't need @types/moment installed!", - "dependencies": { - "moment": "*" - } - }, "node_modules/@types/node": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz", @@ -60584,14 +60574,6 @@ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" }, - "@types/moment": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/@types/moment/-/moment-2.13.0.tgz", - "integrity": "sha512-DyuyYGpV6r+4Z1bUznLi/Y7HpGn4iQ4IVcGn8zrr1P4KotKLdH0sbK1TFR6RGyX6B+G8u83wCzL+bpawKU/hdQ==", - "requires": { - "moment": "*" - } - }, "@types/node": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz", diff --git a/packages/shared/package.json b/packages/shared/package.json index 91cbca59574a..26ab484210f0 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -42,7 +42,6 @@ "dependencies": { "@deriv/translations": "^1.0.0", "@types/js-cookie": "^3.0.1", - "@types/moment": "^2.13.0", "@types/react-loadable": "^5.5.6", "canvas-toBlob": "^1.0.0", "extend": "^3.0.2", From 0d99c58fa467ca2f3bb10858d190a389992a50fa Mon Sep 17 00:00:00 2001 From: Niloofar Sadeghi Date: Tue, 11 Oct 2022 09:17:13 +0330 Subject: [PATCH 3/4] fix: review comments --- packages/shared/src/utils/dom/position.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/shared/src/utils/dom/position.ts b/packages/shared/src/utils/dom/position.ts index d0778ed37638..4ee1a1af5b4a 100644 --- a/packages/shared/src/utils/dom/position.ts +++ b/packages/shared/src/utils/dom/position.ts @@ -1,21 +1,12 @@ -type RectResult = { - bottom: number; - height: number; - left: number; - right: number; - top: number; - width: number; -}; +type RectResult = Record<'bottom' | 'height' | 'left' | 'right' | 'top' | 'width', number>; type TGetMaxHeightByAligning = { parent_rect: RectResult; child_height: number; }; -type TGetPosition = { +type TGetPosition = Record<'child_el' | 'parent_el', HTMLElement> & { preferred_alignment: string; - child_el: HTMLElement; - parent_el: HTMLElement; should_consider_parent_height: boolean; }; From a378b1412aca4c1580d71c7caf6760e951852a6a Mon Sep 17 00:00:00 2001 From: Niloofar Sadeghi Date: Tue, 11 Oct 2022 14:32:28 +0330 Subject: [PATCH 4/4] fix: review comments --- .../src/utils/digital-options/digital-options.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/shared/src/utils/digital-options/digital-options.ts b/packages/shared/src/utils/digital-options/digital-options.ts index 520906a01f13..8b6d347472de 100644 --- a/packages/shared/src/utils/digital-options/digital-options.ts +++ b/packages/shared/src/utils/digital-options/digital-options.ts @@ -16,6 +16,11 @@ type TShowError = { should_clear_error_on_click: boolean; }; +type TAccounts = { + residence?: string; + landing_company_shortcode?: string; +}; + export const showDigitalOptionsUnavailableError = (showError: (t: TShowError) => void, message: TMessage) => { const { title, text, link } = message; showError({ @@ -29,11 +34,6 @@ export const showDigitalOptionsUnavailableError = (showError: (t: TShowError) => }); }; -type TAccounts = { - residence?: string; - landing_company_shortcode?: string; -}; - export const isEuResidenceWithOnlyVRTC = (accounts: TAccounts[]) => { return ( accounts?.length === 1 &&