import { connect as reduxConnect, MapDispatchToPropsParam, MapStateToPropsParam, useDispatch, useSelector, } from 'react-redux'; import { State, Dispatch } from 'app/types'; export const connect = ( mapStateToProps?: MapStateToPropsParam | null | undefined, dispatchProps?: MapDispatchToPropsParam | null | undefined, // mergeProps, // options, ) => reduxConnect(mapStateToProps, dispatchProps /*, mergeProps, options*/); export const useReduxDispatch = () => useDispatch(); export const useReduxSelector = ( selector: (state: State) => TSelected, equalityFn?: (left: TSelected, right: TSelected) => boolean, ): TSelected => useSelector(selector, equalityFn); let lastId = 0; export function uniqueId(prefix: string = 'id'): string { return `${prefix}${++lastId}`; } /** * @param {object} obj * @param {Array} keys * * @returns {object} */ export function omit(obj: { [key: string]: any }, keys: Array): { [key: string]: any } { const newObj = { ...obj }; keys.forEach((key) => { Reflect.deleteProperty(newObj, key); }); return newObj; } /** * Asynchronously loads script * * @param {string} src * * @returns {Promise} */ export function loadScript(src: string): Promise { const script = document.createElement('script'); script.async = true; script.defer = true; script.src = src; return new Promise((resolve, reject) => { script.onload = () => resolve(); script.onerror = reject; if (document && document.body) { document.body.appendChild(script); } }); } /** * Returns a function, that, as long as it continues to be invoked, will not * be triggered. The function will be called after it stops being called for * N milliseconds. If `immediate` is passed, trigger the function on the * leading edge, instead of the trailing. The function also has a property 'clear' * that is a function which will clear the timer to prevent previously scheduled executions. * * @source https://github.com/component/debounce * * @param {Function} function - function to wrap * @param {number} [timeout=100] - timeout in ms * @param {bool} [immediate=false] - whether to execute at the beginning */ export { default as debounce } from 'debounce'; /** * @param {string} jwt * * @throws {Error} If can not decode token * * @returns {object} - decoded jwt payload */ export function getJwtPayloads(jwt: string): { sub: string; jti: number; exp: number; } { const parts = (jwt || '').split('.'); if (parts.length !== 3) { throw new Error('Invalid jwt token'); } try { return JSON.parse(atob(parts[1])); } catch (err) { throw new Error('Can not decode jwt token'); } }