maintenance
This commit is contained in:
6
src/utility/contexts.ts
Normal file
6
src/utility/contexts.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
import {createContext} from 'react';
|
||||
|
||||
export const ViewContext = createContext('');
|
||||
20
src/utility/conversions.ts
Normal file
20
src/utility/conversions.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
import countryMapping from 'services/files/countries_mapping.json';
|
||||
|
||||
export const getCountryFullName = (shortName: string): string => {
|
||||
return countryMapping[shortName] || 'Unknown';
|
||||
};
|
||||
|
||||
// Matches Java's implementation of the standard object.hashCode() for CharSequence
|
||||
export const createHashFromString = (string: string): number => {
|
||||
let hash = 0;
|
||||
let i = 0;
|
||||
|
||||
while (i < string.length) {
|
||||
hash = ((hash << 5) - hash + string.charCodeAt(i++)) << 0;
|
||||
}
|
||||
|
||||
return hash;
|
||||
};
|
||||
105
src/utility/custom-hooks.ts
Normal file
105
src/utility/custom-hooks.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
import {useState, useEffect, useRef, Dispatch, SetStateAction, RefObject} from 'react';
|
||||
import {DirectionType, ITableSort} from 'interfaces/tableProps';
|
||||
import AuthService from 'services/Authentication.service';
|
||||
|
||||
const getWidth = () => window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
||||
|
||||
export const useCurrentWidth = (): number => {
|
||||
const [width, setWidth] = useState(getWidth());
|
||||
|
||||
useEffect(() => {
|
||||
const resizeListener = () => setWidth(getWidth());
|
||||
|
||||
window.addEventListener('resize', resizeListener);
|
||||
|
||||
return () => window.removeEventListener('resize', resizeListener);
|
||||
}, []);
|
||||
|
||||
return width;
|
||||
};
|
||||
|
||||
export const useComponentVisible = (
|
||||
initialIsVisible: boolean
|
||||
): {
|
||||
ref: RefObject<HTMLDivElement>;
|
||||
isComponentVisible: boolean;
|
||||
setIsComponentVisible: Dispatch<SetStateAction<boolean>>;
|
||||
} => {
|
||||
const [isComponentVisible, setIsComponentVisible] = useState(initialIsVisible);
|
||||
const ref = useRef(null);
|
||||
const handleClickOutside = () => {
|
||||
setIsComponentVisible(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('click', handleClickOutside, true);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('click', handleClickOutside, true);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return {
|
||||
ref,
|
||||
isComponentVisible,
|
||||
setIsComponentVisible
|
||||
};
|
||||
};
|
||||
|
||||
export const useHeightResize = (heightOffset: number): [number] => {
|
||||
const [height, setHeight] = useState(window.innerHeight - heightOffset);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
setHeight(window.innerHeight - heightOffset);
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
|
||||
return [height];
|
||||
};
|
||||
|
||||
export const useSearch = (propsSearchValue?: string): [string, Dispatch<SetStateAction<string>>] => {
|
||||
const [searchValue, setSearchValue] = useState<string | undefined>(propsSearchValue);
|
||||
|
||||
useEffect(() => {
|
||||
setSearchValue(propsSearchValue);
|
||||
}, [propsSearchValue, setSearchValue]);
|
||||
|
||||
return [searchValue, setSearchValue];
|
||||
};
|
||||
|
||||
export const useSort = ({sortColumn, sortDirection}: Partial<ITableSort>): [ITableSort, Dispatch<SetStateAction<ITableSort>>] => {
|
||||
const [sortData, setSortData] = useState<ITableSort | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if ((sortColumn && !sortData) || sortColumn !== sortData?.sortColumn || sortDirection !== sortData?.sortDirection) {
|
||||
const newSortDirection = sortDirection || sortData?.sortDirection || DirectionType.Asc;
|
||||
const newSortColumn = sortColumn || sortData?.sortColumn;
|
||||
|
||||
setSortData({
|
||||
sortDirection: newSortDirection,
|
||||
sortColumn: newSortColumn ?? ''
|
||||
});
|
||||
}
|
||||
}, [sortColumn, sortDirection, sortData, setSortData]);
|
||||
|
||||
return [sortData, setSortData];
|
||||
};
|
||||
|
||||
export const useLoginStatus = (applicationId: string): [boolean] => {
|
||||
const [isLoggedIn, setLoginStatus] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
AuthService.hasLoginToken().then((response: boolean) => setLoginStatus(response));
|
||||
}, [applicationId]);
|
||||
|
||||
return [isLoggedIn];
|
||||
};
|
||||
129
src/utility/date.ts
Normal file
129
src/utility/date.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
import moment, {DurationInputArg2, Moment, unitOfTime} from 'moment';
|
||||
import AuthService from 'services/Authentication.service';
|
||||
import userStore from 'services/user-store';
|
||||
import {DataValueType} from 'components/table';
|
||||
|
||||
let delta = 0;
|
||||
|
||||
export enum TimeFormats {
|
||||
Utc = 'utc',
|
||||
LocalTime = 'localTime'
|
||||
}
|
||||
|
||||
export const defaultTimeFormat = `MM-DD-YYYY HH:mm:ss`;
|
||||
export const isoTimeFormat = `YYYY-MM-DD HH:mm:ss`;
|
||||
export const shortTimeFormat = `YYYY-MM-DD`;
|
||||
|
||||
export const getDuration = (start: Date, end: Date, unitOfTime: unitOfTime.Diff): number => {
|
||||
return moment.utc(end).diff(moment.utc(start), unitOfTime);
|
||||
};
|
||||
|
||||
export const fetchPlatformTimeFromServer = async (): Promise<void> => {
|
||||
let platformTime;
|
||||
const localTimeBeforeCall = moment.utc().utc().valueOf();
|
||||
const headers = new Headers();
|
||||
|
||||
headers.set('Authorization', `Basic ${await userStore.get(AuthService.token, '')}`);
|
||||
|
||||
const response = await fetch('https://phenixrts.com/video/dash/time.txt', {headers});
|
||||
const localTimeAfterCall = moment.utc().utc().valueOf();
|
||||
const localTime = localTimeBeforeCall + (localTimeAfterCall - localTimeBeforeCall) / 2;
|
||||
const dateHeader = response.headers.get('date');
|
||||
|
||||
if (dateHeader) {
|
||||
platformTime = moment.utc(dateHeader).utc();
|
||||
delta = moment.duration(platformTime.diff(localTime)).asMilliseconds();
|
||||
}
|
||||
};
|
||||
|
||||
export const getAdjustedTime = (): Moment => {
|
||||
return moment.utc().add(delta, 'milliseconds').milliseconds(0);
|
||||
};
|
||||
|
||||
export const getTimezoneAbbreviation = (date: Date): string => {
|
||||
const timezone = date
|
||||
.toString()
|
||||
.match(/\(.+\)/g)[0]
|
||||
.replace('(', '')
|
||||
.replace(')', '');
|
||||
let abbreviation = '';
|
||||
|
||||
timezone.split(' ').forEach(word => {
|
||||
abbreviation += word.split('')[0];
|
||||
});
|
||||
|
||||
return abbreviation;
|
||||
};
|
||||
|
||||
export const formatDate = (date: Moment | string | Date, format: TimeFormats): string => {
|
||||
const isUTC = format === TimeFormats.Utc;
|
||||
const utcDate = moment.utc(date).format(`${isoTimeFormat} UTC`);
|
||||
const localDate = `${moment.utc(date).format(isoTimeFormat)} ${getTimezoneAbbreviation(moment.utc(date).toDate())}`;
|
||||
|
||||
return isUTC ? utcDate : localDate;
|
||||
};
|
||||
|
||||
export const getFormattedDate = (val: boolean | string | number, format: string = defaultTimeFormat): string => {
|
||||
// TODO: Change table component, as value type in this function should not be a boolean type
|
||||
if (!!val && (typeof val === 'number' || typeof val === 'string')) {
|
||||
return moment.utc(val).format(format);
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
export const getDateFromNow = (value: DataValueType): string => {
|
||||
return value ? moment.utc(value).fromNow() : '';
|
||||
};
|
||||
|
||||
export const getDurationFromNow = (val: number, type: DurationInputArg2 = 'seconds'): number => {
|
||||
const now = moment.utc(new Date());
|
||||
const end = moment.utc(val);
|
||||
const duration = end.diff(now, type);
|
||||
|
||||
return duration;
|
||||
};
|
||||
|
||||
export const getMinAndMaxFromArrayOfObject = (
|
||||
// TODO: move out this function, as it is not related to dates
|
||||
arr: Record<string, any>[], // eslint-disable-line
|
||||
prop: string,
|
||||
mutate?: (val) => string | number
|
||||
): {min: string | number; max: string | number} | null => {
|
||||
const arrLength = arr.length;
|
||||
|
||||
if (arrLength) {
|
||||
let min = mutate ? mutate(arr[0][prop]) : arr[0][prop];
|
||||
let max = mutate ? mutate(arr[0][prop]) : arr[0][prop];
|
||||
let minIdx = 0;
|
||||
let maxIdx = 0;
|
||||
let tmp;
|
||||
|
||||
for (let i = 0; i < arrLength; i += 1) {
|
||||
tmp = mutate ? mutate(arr[i][prop]) : arr[i][prop];
|
||||
|
||||
if (tmp < min) {
|
||||
min = tmp;
|
||||
minIdx = i;
|
||||
}
|
||||
|
||||
if (tmp > max) {
|
||||
max = tmp;
|
||||
maxIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
min: arr[minIdx][prop],
|
||||
max: arr[maxIdx][prop]
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
min: null,
|
||||
max: null
|
||||
};
|
||||
};
|
||||
76
src/utility/error-handler.ts
Normal file
76
src/utility/error-handler.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
|
||||
export interface IError extends Error {
|
||||
response?: {
|
||||
status?: number;
|
||||
data?: {
|
||||
status?: string;
|
||||
message?: string;
|
||||
};
|
||||
config?: {
|
||||
data?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface IPortalError {
|
||||
status: string;
|
||||
message?: string;
|
||||
statusCode?: number;
|
||||
requestPayload?: string;
|
||||
}
|
||||
|
||||
export class PortalError extends Error implements IPortalError {
|
||||
private _name: string;
|
||||
private _status: string;
|
||||
private _message?: string;
|
||||
private _statusCode?: number;
|
||||
private _requestPayload?: string;
|
||||
|
||||
constructor(status?: string, options: {message?: string; statusCode?: number; requestPayload?: string} = {}) {
|
||||
super(options.message || status);
|
||||
this._name = 'PortalError'; // Set the error name
|
||||
this._status = status || 'default'; // Custom status property
|
||||
this._message = options.message;
|
||||
this._statusCode = options.statusCode;
|
||||
this._requestPayload = options.requestPayload;
|
||||
}
|
||||
|
||||
get status(): string {
|
||||
return this._status;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get message(): string | undefined {
|
||||
return this._message;
|
||||
}
|
||||
|
||||
get statusCode(): number | undefined {
|
||||
return this._statusCode;
|
||||
}
|
||||
|
||||
get requestPayload(): string | undefined {
|
||||
return this._requestPayload;
|
||||
}
|
||||
}
|
||||
|
||||
export const transformToPortalError = (e: Error | IPortalError | string | unknown): PortalError => {
|
||||
if (e instanceof PortalError) {
|
||||
return e;
|
||||
}
|
||||
|
||||
if (e instanceof Error) {
|
||||
return new PortalError('no-status-error', {message: e.message});
|
||||
}
|
||||
|
||||
if (typeof e === 'string') {
|
||||
return new PortalError('no-status-error', {message: e});
|
||||
}
|
||||
|
||||
return new PortalError();
|
||||
};
|
||||
40
src/utility/filters.ts
Normal file
40
src/utility/filters.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
import {IAdvancedSelectItem} from 'components/ui/advanced-select';
|
||||
import {capabilities} from 'constants/capabilities';
|
||||
import {isEqual} from './validators';
|
||||
|
||||
export const mergeArrays = <T>(firstArray: T[], secondArray: T[]): T[] => {
|
||||
// This method is generic and we accept any types of arrays for it
|
||||
|
||||
const longer = firstArray.length >= secondArray.length ? firstArray : secondArray;
|
||||
const shorter = secondArray.length <= firstArray.length ? secondArray : firstArray;
|
||||
const difference = [];
|
||||
|
||||
shorter.forEach(recordInLongerArray => {
|
||||
const isPresent = longer.some(recordInShorterArray => isEqual(recordInShorterArray, recordInLongerArray));
|
||||
|
||||
if (!isPresent) {
|
||||
difference.push(recordInLongerArray);
|
||||
}
|
||||
});
|
||||
|
||||
return [...difference, ...longer];
|
||||
};
|
||||
|
||||
export const findDefaultCapabilities = (...requestedCapabilities: string[]): IAdvancedSelectItem[] => {
|
||||
const foundCapabilities = new Map();
|
||||
|
||||
for (const capability of capabilities) {
|
||||
if (requestedCapabilities.includes(capability.value) && !foundCapabilities.has(capability.value)) {
|
||||
foundCapabilities.set(capability.value, capability);
|
||||
|
||||
if (foundCapabilities.size === requestedCapabilities.length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(foundCapabilities.values());
|
||||
};
|
||||
9
src/utility/index.ts
Normal file
9
src/utility/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
export * from './contexts';
|
||||
export * from './date';
|
||||
export * from './sort';
|
||||
export * from './validators';
|
||||
export * from './conversions';
|
||||
export * from './stream';
|
||||
93
src/utility/numbers.ts
Normal file
93
src/utility/numbers.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
export const toSeconds = (milliseconds: number): number => {
|
||||
if (!milliseconds) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return milliseconds / 1000;
|
||||
};
|
||||
|
||||
export const toSignificantFigure = (value: number, precision = 3): string => {
|
||||
return value.toPrecision(precision);
|
||||
};
|
||||
|
||||
export const formatNumberWithPrecision = (value: number, precision = 1): string => {
|
||||
if (!value && value !== 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (value % 1 !== 0) {
|
||||
value = Number(value.toFixed(precision));
|
||||
}
|
||||
|
||||
return value.toLocaleString();
|
||||
};
|
||||
|
||||
export const addTrailingZeroToPercentage = (stringNumber: string): string => {
|
||||
if (!stringNumber || stringNumber === '%') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (stringNumber.indexOf('.') > -1) {
|
||||
return stringNumber;
|
||||
}
|
||||
|
||||
return stringNumber.replace('%', '.0%');
|
||||
};
|
||||
|
||||
export const formatToLocalString = (value: string | number): string => {
|
||||
return Number(value).toLocaleString();
|
||||
};
|
||||
|
||||
export const formatWithUnits = (value: number, valueUnits: string): string => {
|
||||
const sizeUnits = [
|
||||
{
|
||||
value: 1,
|
||||
symbol: ''
|
||||
},
|
||||
{
|
||||
value: 1e3,
|
||||
symbol: 'k'
|
||||
},
|
||||
{
|
||||
value: 1e6,
|
||||
symbol: 'M'
|
||||
},
|
||||
{
|
||||
value: 1e9,
|
||||
symbol: 'G'
|
||||
},
|
||||
{
|
||||
value: 1e12,
|
||||
symbol: 'T'
|
||||
},
|
||||
{
|
||||
value: 1e15,
|
||||
symbol: 'P'
|
||||
},
|
||||
{
|
||||
value: 1e18,
|
||||
symbol: 'E'
|
||||
}
|
||||
];
|
||||
const valueSize =
|
||||
sizeUnits
|
||||
.slice()
|
||||
.reverse()
|
||||
.find(unit => {
|
||||
return value >= unit.value;
|
||||
}) || sizeUnits[0];
|
||||
let formatedValue = (value / valueSize.value).toFixed(2) || 0;
|
||||
|
||||
if (valueSize !== sizeUnits[0]) {
|
||||
formatedValue = String(formatedValue).substring(0, 3);
|
||||
|
||||
while (formatedValue.replace('.', '').length !== 3) {
|
||||
formatedValue += '0';
|
||||
}
|
||||
}
|
||||
|
||||
return `${formatedValue}${valueSize.symbol}${valueUnits}`;
|
||||
};
|
||||
39
src/utility/polyfills.ts
Normal file
39
src/utility/polyfills.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
if (!ReadableStream.prototype[Symbol.asyncIterator]) {
|
||||
Object.defineProperty(ReadableStream.prototype, Symbol.asyncIterator, {
|
||||
value: function () {
|
||||
const reader = this.getReader();
|
||||
|
||||
return {
|
||||
next: async () => {
|
||||
const {done, value} = await reader.read();
|
||||
|
||||
return {
|
||||
value,
|
||||
done
|
||||
};
|
||||
},
|
||||
return: async () => {
|
||||
reader.releaseLock();
|
||||
|
||||
return {
|
||||
value: undefined,
|
||||
done: true
|
||||
};
|
||||
},
|
||||
throw: async e => {
|
||||
reader.releaseLock();
|
||||
|
||||
throw e;
|
||||
},
|
||||
[Symbol.asyncIterator]: function () {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
},
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
20
src/utility/sort.ts
Normal file
20
src/utility/sort.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
import {DirectionType} from 'interfaces/tableProps';
|
||||
|
||||
import {DataValueType} from 'components/table';
|
||||
|
||||
export const compare = (a: Record<string, DataValueType>, b: Record<string, DataValueType>, direction: DirectionType, propName: string): number => {
|
||||
if (a && b) {
|
||||
const isDesc = direction === DirectionType.Desc;
|
||||
|
||||
if (a[propName] < b[propName]) {
|
||||
return isDesc ? -1 : 1;
|
||||
} else if (a[propName] > b[propName]) {
|
||||
return isDesc ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
40
src/utility/stream.ts
Normal file
40
src/utility/stream.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
export const parseStreamIdFromStreamUri = (uri: string): string => {
|
||||
const indexOfQuestionMark = uri.indexOf('?');
|
||||
const parsedUri = uri?.split('/') || [];
|
||||
const [protocol, , domain] = parsedUri;
|
||||
const streamUriPrefix = protocol && domain ? `${protocol}//${domain}/` : '';
|
||||
|
||||
return uri.substring(streamUriPrefix.length, indexOfQuestionMark > -1 ? indexOfQuestionMark : uri.length);
|
||||
};
|
||||
|
||||
interface IStreamInfo {
|
||||
streamId?: string;
|
||||
capabilities?: string[];
|
||||
}
|
||||
|
||||
export const parseStreamInfoFromStreamUri = (uri: string): IStreamInfo => {
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
|
||||
const streamId = parseStreamIdFromStreamUri(uri);
|
||||
const queryParams = [...new URLSearchParams(uri.split('?')[1])].reduce((accumulator, [key, value]) => {
|
||||
if (key === 'capabilities') {
|
||||
accumulator[key] = value?.split(',') || [];
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
accumulator[key] = value;
|
||||
|
||||
return accumulator;
|
||||
}, {});
|
||||
|
||||
return {
|
||||
...queryParams,
|
||||
streamId
|
||||
};
|
||||
};
|
||||
81
src/utility/validators.ts
Normal file
81
src/utility/validators.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
|
||||
*/
|
||||
export const validateURL = (str: string): boolean => {
|
||||
let url;
|
||||
|
||||
try {
|
||||
url = new URL(str);
|
||||
} catch (ignoredErr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!url.protocol;
|
||||
};
|
||||
|
||||
export const isEqual = (obj1: unknown, obj2: unknown): boolean => {
|
||||
// In this case we really accepting any types of arguments
|
||||
// TODO: Replace isEqual usage from components/shared/utils with this one
|
||||
|
||||
const getType = (obj: unknown): string => {
|
||||
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
|
||||
};
|
||||
|
||||
const areArraysEqual = () => {
|
||||
if (obj1.length !== obj2.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < obj1.length; i++) {
|
||||
if (!isEqual(obj1[i], obj2[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const areObjectsEqual = () => {
|
||||
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const key in obj1) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj1, key)) {
|
||||
if (!isEqual(obj1[key], obj2[key])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const areFunctionsEqual = () => {
|
||||
return obj1.toString() === obj2.toString();
|
||||
};
|
||||
|
||||
const arePrimativesEqual = () => {
|
||||
return obj1 === obj2;
|
||||
};
|
||||
|
||||
const type = getType(obj1);
|
||||
|
||||
if (type !== getType(obj2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type === 'array') {
|
||||
return areArraysEqual();
|
||||
}
|
||||
|
||||
if (type === 'object') {
|
||||
return areObjectsEqual();
|
||||
}
|
||||
|
||||
if (type === 'function') {
|
||||
return areFunctionsEqual();
|
||||
}
|
||||
|
||||
return arePrimativesEqual();
|
||||
};
|
||||
Reference in New Issue
Block a user