mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 01:20:24 +03:00
Refactored many helpers to Typescript
This commit is contained in:
parent
7c67fa4149
commit
62df46d648
18 changed files with 145 additions and 113 deletions
15
package-lock.json
generated
15
package-lock.json
generated
|
@ -3090,6 +3090,12 @@
|
|||
"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/geojson": {
|
||||
"version": "7946.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
|
||||
"integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/glob": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
|
||||
|
@ -3299,6 +3305,15 @@
|
|||
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/leaflet": {
|
||||
"version": "1.5.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.5.17.tgz",
|
||||
"integrity": "sha512-2XYq9k6kNjhNI7PaTz8Rdxcc8Vzwu97OaS9CtcrTxnTSxFUGwjlGjTDvhTLJU+JRSfZ4lBwGcl0SjZHALdVr6g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/geojson": "*"
|
||||
}
|
||||
},
|
||||
"@types/minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
"@types/classnames": "^2.2.10",
|
||||
"@types/enzyme": "^3.10.5",
|
||||
"@types/jest": "^26.0.10",
|
||||
"@types/leaflet": "^1.5.17",
|
||||
"@types/moment": "^2.13.0",
|
||||
"@types/ramda": "^0.27.14",
|
||||
"@types/react": "^16.9.46",
|
||||
|
|
|
@ -6,7 +6,7 @@ import { homepage } from '../package.json';
|
|||
import registerServiceWorker from './registerServiceWorker';
|
||||
import container from './container';
|
||||
import store from './container/store';
|
||||
import { fixLeafletIcons } from './utils/utils';
|
||||
import { fixLeafletIcons } from './utils/helpers/leaflet';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
|
|
|
@ -10,4 +10,4 @@ const formatDateFromFormat = (date?: NullableDate, format?: string): NullableDat
|
|||
|
||||
export const formatDate = (format = 'YYYY-MM-DD') => (date?: NullableDate) => formatDateFromFormat(date, format);
|
||||
|
||||
export const formatIsoDate = (date: NullableDate) => formatDateFromFormat(date, undefined);
|
||||
export const formatIsoDate = (date?: NullableDate) => formatDateFromFormat(date, undefined);
|
||||
|
|
16
src/utils/helpers/leaflet.js
Normal file
16
src/utils/helpers/leaflet.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
// TODO Migrate this file to Typescript
|
||||
|
||||
import L from 'leaflet';
|
||||
import marker2x from 'leaflet/dist/images/marker-icon-2x.png';
|
||||
import marker from 'leaflet/dist/images/marker-icon.png';
|
||||
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
|
||||
export const fixLeafletIcons = () => {
|
||||
delete L.Icon.Default.prototype._getIconUrl;
|
||||
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: marker2x,
|
||||
iconUrl: marker,
|
||||
shadowUrl: markerShadow,
|
||||
});
|
||||
};
|
|
@ -1,8 +0,0 @@
|
|||
const TEN_ROUNDING_NUMBER = 10;
|
||||
const { ceil } = Math;
|
||||
|
||||
const formatter = new Intl.NumberFormat('en-US');
|
||||
|
||||
export const prettify = (number) => formatter.format(number);
|
||||
|
||||
export const roundTen = (number) => ceil(number / TEN_ROUNDING_NUMBER) * TEN_ROUNDING_NUMBER;
|
7
src/utils/helpers/numbers.ts
Normal file
7
src/utils/helpers/numbers.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
const TEN_ROUNDING_NUMBER = 10;
|
||||
const { ceil } = Math;
|
||||
const formatter = new Intl.NumberFormat('en-US');
|
||||
|
||||
export const prettify = (number: number) => formatter.format(number);
|
||||
|
||||
export const roundTen = (number: number) => ceil(number / TEN_ROUNDING_NUMBER) * TEN_ROUNDING_NUMBER;
|
|
@ -1,27 +0,0 @@
|
|||
import { max, min, range } from 'ramda';
|
||||
|
||||
export const ELLIPSIS = '...';
|
||||
|
||||
export const progressivePagination = (currentPage, pageCount) => {
|
||||
const delta = 2;
|
||||
const pages = range(
|
||||
max(delta, currentPage - delta),
|
||||
min(pageCount - 1, currentPage + delta) + 1,
|
||||
);
|
||||
|
||||
if (currentPage - delta > delta) {
|
||||
pages.unshift(ELLIPSIS);
|
||||
}
|
||||
if (currentPage + delta < pageCount - 1) {
|
||||
pages.push(ELLIPSIS);
|
||||
}
|
||||
|
||||
pages.unshift(1);
|
||||
pages.push(pageCount);
|
||||
|
||||
return pages;
|
||||
};
|
||||
|
||||
export const keyForPage = (pageNumber, index) => pageNumber !== ELLIPSIS ? pageNumber : `${pageNumber}_${index}`;
|
||||
|
||||
export const isPageDisabled = (pageNumber) => pageNumber === ELLIPSIS;
|
29
src/utils/helpers/pagination.ts
Normal file
29
src/utils/helpers/pagination.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { max, min, range } from 'ramda';
|
||||
|
||||
export const ELLIPSIS = '...';
|
||||
|
||||
type NumberOrEllipsis = number | '...';
|
||||
|
||||
export const progressivePagination = (currentPage: number, pageCount: number): NumberOrEllipsis[] => {
|
||||
const delta = 2;
|
||||
const pages: NumberOrEllipsis[] = range(
|
||||
max(delta, currentPage - delta),
|
||||
min(pageCount - 1, currentPage + delta) + 1,
|
||||
);
|
||||
|
||||
if (currentPage - delta > delta) {
|
||||
pages.unshift(ELLIPSIS);
|
||||
}
|
||||
if (currentPage + delta < pageCount - 1) {
|
||||
pages.push(ELLIPSIS);
|
||||
}
|
||||
|
||||
pages.unshift(1);
|
||||
pages.push(pageCount);
|
||||
|
||||
return pages;
|
||||
};
|
||||
|
||||
export const keyForPage = (pageNumber: NumberOrEllipsis, index: number) => pageNumber !== ELLIPSIS ? pageNumber : `${pageNumber}_${index}`;
|
||||
|
||||
export const isPageDisabled = (pageNumber: NumberOrEllipsis) => pageNumber === ELLIPSIS;
|
|
@ -1,27 +0,0 @@
|
|||
import { compare } from 'compare-versions';
|
||||
import { identity, memoizeWith } from 'ramda';
|
||||
import { hasValue } from '../utils';
|
||||
|
||||
export const versionMatch = (versionToMatch, { maxVersion, minVersion }) => {
|
||||
if (!hasValue(versionToMatch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const matchesMinVersion = !minVersion || compare(versionToMatch, minVersion, '>=');
|
||||
const matchesMaxVersion = !maxVersion || compare(versionToMatch, maxVersion, '<=');
|
||||
|
||||
return !!(matchesMaxVersion && matchesMinVersion);
|
||||
};
|
||||
|
||||
const versionIsValidSemVer = memoizeWith(identity, (version) => {
|
||||
try {
|
||||
return compare(version, version, '=');
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
export const versionToPrintable = (version) => !versionIsValidSemVer(version) ? version : `v${version}`;
|
||||
|
||||
export const versionToSemVer = (defaultValue = 'latest') =>
|
||||
(version) => versionIsValidSemVer(version) ? version : defaultValue;
|
32
src/utils/helpers/version.ts
Normal file
32
src/utils/helpers/version.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { compare } from 'compare-versions';
|
||||
import { identity, memoizeWith } from 'ramda';
|
||||
import { Empty, hasValue } from '../utils';
|
||||
|
||||
export interface Versions {
|
||||
maxVersion?: string;
|
||||
minVersion?: string;
|
||||
}
|
||||
|
||||
export const versionMatch = (versionToMatch: string | Empty, { maxVersion, minVersion }: Versions): boolean => {
|
||||
if (!hasValue(versionToMatch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const matchesMinVersion = !minVersion || compare(versionToMatch, minVersion, '>=');
|
||||
const matchesMaxVersion = !maxVersion || compare(versionToMatch, maxVersion, '<=');
|
||||
|
||||
return matchesMaxVersion && matchesMinVersion;
|
||||
};
|
||||
|
||||
const versionIsValidSemVer = memoizeWith(identity, (version: string) => {
|
||||
try {
|
||||
return compare(version, version, '=');
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
export const versionToPrintable = (version: string) => !versionIsValidSemVer(version) ? version : `v${version}`;
|
||||
|
||||
export const versionToSemVer = (defaultValue = 'latest') =>
|
||||
(version: string) => versionIsValidSemVer(version) ? version : defaultValue;
|
|
@ -1,32 +0,0 @@
|
|||
import L from 'leaflet';
|
||||
import marker2x from 'leaflet/dist/images/marker-icon-2x.png';
|
||||
import marker from 'leaflet/dist/images/marker-icon.png';
|
||||
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
import { isEmpty, isNil, range } from 'ramda';
|
||||
|
||||
export const determineOrderDir = (clickedField, currentOrderField, currentOrderDir) => {
|
||||
if (currentOrderField !== clickedField) {
|
||||
return 'ASC';
|
||||
}
|
||||
|
||||
const newOrderMap = {
|
||||
ASC: 'DESC',
|
||||
DESC: undefined,
|
||||
};
|
||||
|
||||
return currentOrderDir ? newOrderMap[currentOrderDir] : 'ASC';
|
||||
};
|
||||
|
||||
export const fixLeafletIcons = () => {
|
||||
delete L.Icon.Default.prototype._getIconUrl;
|
||||
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: marker2x,
|
||||
iconUrl: marker,
|
||||
shadowUrl: markerShadow,
|
||||
});
|
||||
};
|
||||
|
||||
export const rangeOf = (size, mappingFn, startAt = 1) => range(startAt, size + 1).map(mappingFn);
|
||||
|
||||
export const hasValue = (value) => !isNil(value) && !isEmpty(value);
|
23
src/utils/utils.ts
Normal file
23
src/utils/utils.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { isEmpty, isNil, range } from 'ramda';
|
||||
|
||||
export type OrderDir = 'ASC' | 'DESC' | undefined;
|
||||
|
||||
export const determineOrderDir = (currentField: string, newField: string, currentOrderDir: OrderDir): OrderDir => {
|
||||
if (currentField !== newField) {
|
||||
return 'ASC';
|
||||
}
|
||||
|
||||
const newOrderMap: Record<'ASC' | 'DESC', OrderDir> = {
|
||||
ASC: 'DESC',
|
||||
DESC: undefined,
|
||||
};
|
||||
|
||||
return currentOrderDir ? newOrderMap[currentOrderDir] : 'ASC';
|
||||
};
|
||||
|
||||
export const rangeOf = <T>(size: number, mappingFn: (value: number) => T, startAt = 1): T[] =>
|
||||
range(startAt, size + 1).map(mappingFn);
|
||||
|
||||
export type Empty = null | undefined | '' | never[];
|
||||
|
||||
export const hasValue = <T>(value: T | Empty): value is T => !isNil(value) && !isEmpty(value);
|
19
test/utils/helpers/leaflet.test.js
Normal file
19
test/utils/helpers/leaflet.test.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import L from 'leaflet';
|
||||
import marker2x from 'leaflet/dist/images/marker-icon-2x.png';
|
||||
import marker from 'leaflet/dist/images/marker-icon.png';
|
||||
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
import { fixLeafletIcons } from '../../../src/utils/helpers/leaflet';
|
||||
|
||||
describe('leaflet', () => {
|
||||
describe('fixLeafletIcons', () => {
|
||||
it('updates icons used by leaflet', () => {
|
||||
fixLeafletIcons();
|
||||
|
||||
const { iconRetinaUrl, iconUrl, shadowUrl } = L.Icon.Default.prototype.options;
|
||||
|
||||
expect(iconRetinaUrl).toEqual(marker2x);
|
||||
expect(iconUrl).toEqual(marker);
|
||||
expect(shadowUrl).toEqual(markerShadow);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,8 +1,4 @@
|
|||
import L from 'leaflet';
|
||||
import marker2x from 'leaflet/dist/images/marker-icon-2x.png';
|
||||
import marker from 'leaflet/dist/images/marker-icon.png';
|
||||
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
import { determineOrderDir, fixLeafletIcons, rangeOf } from '../../src/utils/utils';
|
||||
import { determineOrderDir, rangeOf } from '../../src/utils/utils';
|
||||
|
||||
describe('utils', () => {
|
||||
describe('determineOrderDir', () => {
|
||||
|
@ -27,18 +23,6 @@ describe('utils', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('fixLeafletIcons', () => {
|
||||
it('updates icons used by leaflet', () => {
|
||||
fixLeafletIcons();
|
||||
|
||||
const { iconRetinaUrl, iconUrl, shadowUrl } = L.Icon.Default.prototype.options;
|
||||
|
||||
expect(iconRetinaUrl).toEqual(marker2x);
|
||||
expect(iconUrl).toEqual(marker);
|
||||
expect(shadowUrl).toEqual(markerShadow);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rangeOf', () => {
|
||||
const func = (i) => `result_${i}`;
|
||||
const size = 5;
|
||||
|
|
Loading…
Reference in a new issue