Добавление функции для построения url ссылок внутри приложения, добавление функции triggerLink для сервисов (#31)

This commit is contained in:
Nikolay
2020-12-28 00:26:20 +03:00
committed by GitHub
parent 27de662b5f
commit e8635972c6
6 changed files with 148 additions and 11 deletions

View File

@ -10,7 +10,8 @@ import SearchIcon from '@material-ui/icons/Search';
import {Avatar} from '@material-ui/core';
import {useParams} from '_hooks/useParams';
import {PageType} from '_enums/common';
import {PAGE_TITLE, ROUTES} from '_consts/common';
import {PAGE_TITLE} from '_consts/common';
import {buildPath} from '../../../core/utils/buildPath';
const NO_NAME_AVATAR = 'https://d.newsweek.com/en/full/425257/02-10-putin-economy.jpg';
@ -33,7 +34,7 @@ const TopMenu: React.FC = () => {
const history = useHistory();
const handleGoRoot = () => {
history.push(ROUTES.MAIN);
history.push(buildPath({pageType: PageType.Main}));
};
const title = PAGE_TITLE[pageType];

View File

@ -0,0 +1,56 @@
import {PageType} from '../../enums/common';
import {buildPath, BuildPathOptions} from '../buildPath';
describe('buildPath', () => {
it('Путь до страницы', () => {
const options: BuildPathOptions = {
pageType: PageType.Tags
};
expect(buildPath(options)).toBe(`/${PageType.Tags}`);
});
it('Путь с route параметрами', () => {
const options: BuildPathOptions = {
pageType: PageType.Tags,
params: ['mode', '/id', 'fine'],
};
expect(buildPath(options)).toBe(`/${PageType.Tags}/mode/id/fine`);
});
it('Путь c query', () => {
const options: BuildPathOptions = {
pageType: PageType.Tags,
query: {
foo: 'bar',
},
};
expect(buildPath(options)).toBe(`/${PageType.Tags}?foo=bar`);
});
it('Путь c query значениями undefined', () => {
const options: BuildPathOptions = {
pageType: PageType.Tags,
query: {
foo: undefined,
},
};
expect(buildPath(options)).toBe(`/${PageType.Tags}?foo=`);
});
it('Старые query должны быть затерты', () => {
const options: BuildPathOptions = {
pageType: PageType.Tags,
};
history.pushState(null, '', '/name?like=true');
expect(buildPath(options)).toBe(`/${PageType.Tags}`);
});
it('Старые query должны остаться в url', () => {
const options: BuildPathOptions = {
pageType: PageType.Tags,
withQuery: true,
};
history.pushState(null, '', '/name?like=true');
expect(buildPath(options)).toBe(`/${PageType.Tags}?like=true`);
});
});

View File

@ -0,0 +1,23 @@
import {decode, ParsedUrlQueryInput, stringify} from 'querystring';
import {PageType} from '../enums/common';
export type BuildPathOptions = {
pageType: PageType;
params?: Array<string>;
query?: ParsedUrlQueryInput;
withQuery?: boolean,
};
const makePath = (params: Array<string>) => params.map(param => {
return param.startsWith('/') ? param.slice(1) : param;
}).join('/');
export const buildPath = ({pageType, params, query, withQuery}: BuildPathOptions) => {
const path = makePath([pageType, ...(params ?? [])]);
const previousQuery = decode(location.search.slice(1));
const stringifyQuery = stringify({
...(withQuery ? previousQuery : {}),
...query,
});
return [`/${path}`, stringifyQuery].filter(Boolean).join('?');
};

View File

@ -0,0 +1,33 @@
type Options = {
download?: boolean | string;
target?: '_self' | '_blank';
};
const DEFAULT_OPTIONS = {
target: '_self',
download: false,
} as const;
/**
* Использование этой функции требуется для открытия ссылок в новых
* вкладках из методов сервиса. Внутри компонентов его не используем.
*/
export const triggerLink = (link: string, options?: Options) => {
const finalOptions = {
...DEFAULT_OPTIONS,
...options
};
const a = document.createElement('a');
a.href = link;
a.target = finalOptions.target;
if (finalOptions.download === true) {
a.download = 'yes';
} else if (typeof finalOptions.download === 'string') {
a.download = finalOptions.download;
}
a.dispatchEvent(new MouseEvent('click'));
document.removeChild(a);
};