Skip to content
Open
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
File renamed without changes.
31 changes: 31 additions & 0 deletions src/async/cachedPromise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export function getPromiseCacheFunc(seconds = 10) {
const storage = new Map<string, { expiredTime: number; promiseResult: Promise<any> }>();

function getNowSeconds() {
return new Date().getTime() / 1000;
}

function add(key: any, result: any) {
storage.set(key, {
promiseResult: result,
expiredTime: getNowSeconds() + seconds,
});
}

function isExpired(key: any) {
const expiredTime = storage.get(key)?.expiredTime;
return expiredTime && getNowSeconds() > expiredTime;
}

return function <T>(promise: () => Promise<T>, key: string): () => Promise<T> {
if (!storage.has(key) || isExpired(key)) {
return () =>
promise().then((promiseResult) => {
add(key, promiseResult);
return promiseResult;
});
}
const promiseResult = storage.get(key)?.promiseResult;
return () => Promise.resolve(promiseResult);
};
}
File renamed without changes.
3 changes: 3 additions & 0 deletions src/calculateScrollBottom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const calculateScrollBottom = (element: HTMLElement) => {
return element.scrollHeight - element.scrollTop - element.clientHeight;
};
35 changes: 0 additions & 35 deletions src/date.ts

This file was deleted.

57 changes: 57 additions & 0 deletions src/date/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import "moment/locale/ru";
import moment, { LocaleSpecification, Moment, unitOfTime } from "moment";
import { sort, uniqWith } from "ramda";

export enum DateMode {
DAY_MONTH_YEAR = "DD MMMM YYYY",
DAY_MONTH_YEAR_TIME = "DD MMMM YYYY HH:mm",
DAY_MONTH = "DD MMMM",
DAY_MONTH_SHORT = "DD.MM",
DATE = "DD.MM.YYYY",
DATE_WITH_SLASHES = "DD/MM/YYYY",
UTC = "YYYY.MM.DD HH:mm:ss UTC-0000",
UTC_PROXY_SERVER = "YYYY-MM-DDTHH:mm:ss",
TIME = "HH:mm",
TIME_WITH_SECONDS = "HH:mm:ss",
DATE_TIME = "DD.MM.YYYY HH:mm",
DATE_TIME_WITH_SECONDS = "DD.MM.YYYY HH:mm:ss",
DATE_TIME_WITH_MILLI_SECONDS = "DD.MM.YYYY HH:mm:ss:SSS",
YEAR_AND_QUARTER = "YYYY.Q",
SERVER_YEAR_AND_QUARTER = "YYYY~Q",
HUMANABLE_DATE_TIME_WITHOUT_YEAR = "D MMMM в HH:mm",
}

// @ts-ignore
const config = moment.localeData("ru")["_config"] as LocaleSpecification;

const weekdaysShort: string[] = config.weekdaysShort as any;

moment.updateLocale("ru", {
calendar: {
...config.calendar,
},
week: {
dow: 1,
},
weekdaysShort: [weekdaysShort[1], ...weekdaysShort.slice(2), weekdaysShort[0]],
});

export function momentFromLocalString(value: string, mode: DateMode = DateMode.DATE) {
return moment(value, mode);
}

export const sortDates = (dates: Moment[]): Moment[] => sort((a: Moment, b: Moment) => a.diff(b), dates);

export const uniqDatesBy = (by?: unitOfTime.StartOf) => (dates: Moment[]): Moment[] =>
uniqWith((prevDate, currDate) => prevDate.isSame(currDate, by), dates);

export const currentDateIsBetweenDates = (start: Moment, end: Moment) => moment().isBetween(start, end);

export function convertMomentToStartDateModeInterval(date: Moment, mode: DateMode) {
return moment(date.format(mode), mode);
}

export const changeFormatMoment = (initialFormat: DateMode, convertFormat: DateMode) => (date: Moment) =>
moment(date.format(initialFormat), convertFormat);

export const now = moment();
10 changes: 10 additions & 0 deletions src/decorators/eventValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default (func: Function) => {
return function (ev?: any) {
if (ev && ev.target) {
func(ev.target.value);
return;
}

func(null);
};
};
8 changes: 8 additions & 0 deletions src/decorators/preventDefault.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default (func?: Function) => {
return function (ev?: any) {
if (ev) {
ev.preventDefault();
}
func && func(ev);
};
};
8 changes: 8 additions & 0 deletions src/decorators/stopPropagation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default (func?: Function) => {
return function (ev?: any) {
if (ev) {
ev.stopPropagation();
}
if (func) func(ev);
};
};
6 changes: 6 additions & 0 deletions src/files/blobToFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function blobToFile(theBlob: Blob, fileName: string): File {
const blob: any = new Blob([theBlob]);
blob.lastModifiedDate = new Date();
blob.name = fileName;
return blob as File;
}
7 changes: 7 additions & 0 deletions src/files/toBase64.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const toBase64 = (file: File) =>
new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result as string);
reader.onerror = (error) => reject(error);
});
18 changes: 9 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ export * from "./files/bytesToHumanReadableFormat";
export * from "./files/createFileInput";
export * from "./types/DecoderType";
export * from "./types/FileInterface";
export * from "./request/defaultDecoders";
export * from "./request/decoders/numberFieldDecoder";
export * from "./request/index";
export * from "./asyncTimeout";
export * from "./async/asyncTimeout";
export * from "./BaseError";
export * from "./capitalizeFirstStringCharacter";
export * from "./string/capitalizeFirstStringCharacter";
export * from "./date";
export * from "./events";
export * from "./htmlCollectionToArray";
export * from "./list/htmlCollectionToArray";
export * from "./is";
export * from "./isDeepEqual";
export * from "./object/isDeepEqual";
export * from "./linkIsNative";
export * from "./nbsp";
export * from "./path";
export * from "./promisifyAPI";
export * from "./searchInString";
export * from "./string/nbsp";
export * from "./object/path";
export * from "./async/promisifyAPI";
export * from "./string/searchInString";
export * from "./state/loadingContainer";
15 changes: 15 additions & 0 deletions src/isIe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export default function detectIE() {
const ua = window.navigator.userAgent;

const msie = ua.indexOf("MSIE ");
if (msie > 0) {
return true;
}

const trident = ua.indexOf("Trident/");
if (trident > 0) {
return true;
}

return false;
}
File renamed without changes.
16 changes: 16 additions & 0 deletions src/list/multiGroupBy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { curry } from "ramda";

type FormattedObjectType<T> = { [key: string]: T[] };

export const multiGroupBy = curry(function <T>(
getGroupKeys: (el: T) => (string | number)[],
list: T[],
): FormattedObjectType<T> {
return [...list].reduce<FormattedObjectType<T>>((acc, el) => {
const groupKeys = getGroupKeys(el);
groupKeys.forEach((key) => {
if (key) acc[key] = acc[key] ? [...acc[key], el] : [el];
});
return acc;
}, {});
});
26 changes: 26 additions & 0 deletions src/localStorage/dataManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { compose, curry } from "ramda";

export interface DataManagerInterface {
setData: (key: string, elements: any[]) => void;
getData: (key: string) => any;
}

export class DataManager {
private inner: DataManagerInterface;

constructor(inner: DataManagerInterface) {
this.inner = inner;
}

setData = (keyName: string, elements: any[]) => {
return this.inner.setData(keyName, elements);
};

getData = (name: string) => {
return this.inner.getData(name);
};

map = (key: string, cb: (value: any) => any): void => {
compose(curry(this.inner.setData)(key), cb, this.inner.getData)(key);
};
}
13 changes: 13 additions & 0 deletions src/localStorage/localStorageService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { DataManagerInterface } from "./dataManager";

export class LocalStorageService implements DataManagerInterface {
setData = (key: string, value: any) => {
localStorage.setItem(key, JSON.stringify(value));
};

getData = (key: string) => {
const gotData = localStorage.getItem(key);
if (gotData === null || gotData === undefined) return null;
return JSON.parse(gotData);
};
}
File renamed without changes.
10 changes: 10 additions & 0 deletions src/object/parseJsonSelf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NullableType } from "..";

export function parseJsonSelf<T>(param: string, callbackError: (error: Error) => void): NullableType<T> {
try {
return JSON.parse(param) as T;
} catch (error) {
callbackError(error);
return null;
}
}
2 changes: 1 addition & 1 deletion src/path.ts → src/object/path.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { path as ramdaPath } from "ramda";

import { isString } from "./is";
import { isString } from "../is";

export function splitByPoint(path: string) {
return path.split(".");
Expand Down
20 changes: 20 additions & 0 deletions src/object/smartDeepMergeRight.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { mergeWithKey } from "ramda";

function isObject(x: any) {
return Object.prototype.toString.call(x) === "[object Object]";
}

export const smartDeepMergeRight = (deepLevelThreshold: number) => {
return function mergeDeepWithKey(lObj: any, rObj: any, _level = 1): any {
return mergeWithKey(
(_, lVal, rVal) => {
if (isObject(lVal) && isObject(rVal) && _level < deepLevelThreshold) {
return mergeDeepWithKey(lVal, rVal, _level + 1);
}
return rVal;
},
lObj,
rObj,
);
};
};
5 changes: 5 additions & 0 deletions src/replacementRamda/customNot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const customNot = function (cb: (el?: any) => any) {
return function (data: any): boolean {
return !cb(data);
};
};
5 changes: 5 additions & 0 deletions src/replacementRamda/customRamdaFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const customRamdaFilter = function <T>(cb: (el: T) => boolean) {
return function (list: T[]) {
return list.filter(cb);
};
};
5 changes: 5 additions & 0 deletions src/replacementRamda/returnBoolean.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const returnBoolean = function (cb: (el?: any) => any) {
return function (data: any): boolean {
return !!cb(data);
};
};
11 changes: 11 additions & 0 deletions src/request/decoders/booleanFieldDecoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Decoder from "jsonous";
import { ok } from "resulty";

import { numberFieldDecoder } from "./numberFieldDecoder";

export const booleanFieldDecoder = (key: string) => {
return new Decoder<boolean>((inputData) => {
const value = numberFieldDecoder(key, { defaultValue: 0 }).decodeAny(inputData).getOrElseValue(null);
return ok(!!value);
});
};
13 changes: 13 additions & 0 deletions src/request/decoders/codeTitileFieldDecoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Decoder, { string, succeed } from "jsonous";
import { isString } from "../../is";
import { fieldWithDefaultDecoder } from "./fieldWithDefaultDecoder";
import { NullableType } from "../..";

export function codeTitleFieldDecoder(
code: string | Decoder<NullableType<string>>,
title: string | Decoder<NullableType<string>>,
) {
return succeed({})
.assign("code", isString(code) ? fieldWithDefaultDecoder(code, string, "") : code)
.assign("title", isString(title) ? fieldWithDefaultDecoder(title, string, "") : title);
}
4 changes: 4 additions & 0 deletions src/request/decoders/constValueDecoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Decoder from "jsonous";
import { ok } from "resulty";

export const constValueDecoder = <T = any>(value: any) => new Decoder<T>(() => ok(value));
23 changes: 23 additions & 0 deletions src/request/decoders/enumDecoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Decoder from "jsonous";
import {err, ok} from "resulty";

export function enumDecoder<T>(key: string, map: { [key: string]: T }, defaultValue?: T, handler?: (value: any) => T) {
return new Decoder((value) => {
const fieldValue = value[key];
const valueInMap = map[fieldValue];

if (valueInMap === undefined) {
const availableTypesString = JSON.stringify(Object.keys(map));

return handler !== undefined
? ok<string, T>(handler(fieldValue))
: defaultValue !== undefined
? ok<string, T>(defaultValue)
: err<string, T>(
`Переданное значение "${fieldValue}" не соответствует ни одному из позволенных [${availableTypesString}].`,
);
}

return ok<string, T>(valueInMap);
});
}
6 changes: 6 additions & 0 deletions src/request/decoders/falseValueDecoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Decoder from "jsonous";
import { ok, err } from "resulty";

export const falseValueDecoder = new Decoder<false>(function (value) {
return value === false ? ok<string, false>(false) : err('Ожидалось "false"');
});
Loading