react-cm-ui
Version:
React UI for Healthy Church
205 lines (170 loc) • 6.23 kB
JavaScript
import {
get,
uniqBy,
find,
} from 'lodash';
const extractRoute = (route, prefix, shouldAddRoute = true) => {
const path = route.props && route.props.path ? route.props.path : route.path;
let paths = [];
if (!path) {
if (Array.isArray(route)) {
route.forEach((r) => {
paths = paths.concat(extractRoute(r, prefix, shouldAddRoute));
});
return paths;
}
// eslint-disable-next-line no-use-before-define
return extractChildRoutes(route, prefix);
}
const currentPath = (`${prefix || ''}${path}`.replace(/\/+/g, '/'));
const pathString = `${currentPath.startsWith('/') ? '' : '/'}${currentPath}`;
let title = get(route, 'title');
const couldItBeHome = path === '/' && !title;
if (couldItBeHome) {
title = 'Home';
}
if (!route.childRoutes) {
paths.push({
path: pathString,
title: title || pathString.split('/').filter((subPath) => subPath !== '').reverse()[0],
});
}
// eslint-disable-next-line no-use-before-define
paths = paths.concat(extractChildRoutes(route, `${currentPath}/`));
return paths;
};
const extractChildRoutes = (route, prefix) => {
let paths = [];
const shouldAddIndexRoute = route.indexRoute && route.path;
if (shouldAddIndexRoute) {
const indexRouteString = `${prefix}`.replace('//', '/');
let title = get(route, 'indexRoute.title');
const couldItBeHome = indexRouteString === '/' && !title;
if (couldItBeHome) {
title = 'Home';
}
paths.push({
path: indexRouteString,
title: title || indexRouteString.split('/').filter((subPath) => subPath !== '').reverse()[0],
});
}
const childRoutes = route.props && route.props.children ?
route.props.children :
route.childRoutes;
if (childRoutes) {
if (Array.isArray(childRoutes)) {
childRoutes.forEach((r) => {
paths = paths.concat(extractRoute(r, prefix, shouldAddIndexRoute));
});
} else {
paths = paths.concat(extractRoute(childRoutes, prefix, shouldAddIndexRoute));
}
}
return paths;
};
export const parsePath = (path, params, inversed = true) => {
const paramsKeys = Object.keys(params);
let formattedPath = path;
for (let i = 0; i < paramsKeys.length; i += 1) {
const currentKey = paramsKeys[i];
const currentValue = params[currentKey];
formattedPath = inversed ?
formattedPath.replace(currentValue, `:${currentKey}`) :
formattedPath.replace(`:${currentKey}`, currentValue);
}
return formattedPath || '';
};
export const transformPathsWithOptionalParams = (paths) => {
let optionalPaths = [];
const replacements = { '(': '', ')': '' };
for (let i = 0; i < paths.length; i += 1) {
const auxPath = paths[i];
if (auxPath.path.includes('(')) {
const subPaths = auxPath.path.split('(');
let pathPrefix = subPaths[0];
optionalPaths.push({
path: pathPrefix,
title: auxPath.title,
});
for (let j = 1; j < subPaths.length; j += 1) {
const pathSufix = subPaths[j];
let optionalPath;
const isNestedOptionalPath = pathSufix.includes('))');
if (isNestedOptionalPath) {
const previousSufix = subPaths[j - 1];
pathPrefix = `${pathPrefix}${previousSufix}`;
optionalPath = `${pathPrefix}${pathSufix}`;
} else {
optionalPath = `${pathPrefix}${pathSufix}`;
}
optionalPaths.push({
path: optionalPath,
title: auxPath.title,
});
}
} else {
optionalPaths.push(auxPath);
}
}
optionalPaths = optionalPaths
.map((auxPath) => ({
...auxPath,
path: auxPath.path.replace(/[()]/g, (char) => replacements[char]),
}))
.map((auxPath) => {
if (auxPath.path.length > 2) {
return {
...auxPath,
path: auxPath.path.replace(/\/$/, ''),
};
}
return auxPath;
});
return optionalPaths;
};
export const routesToArray = (route) => {
let paths = [];
if (Array.isArray(route)) {
route.forEach((r) => {
paths = paths.concat(extractRoute(r));
});
} else {
paths = paths.concat(extractRoute(route));
}
paths = transformPathsWithOptionalParams(paths);
paths = uniqBy(paths, 'path');
return paths;
};
export const getPathNameBreadcrumbs = (
pathName,
pathParams,
routerPushFunction,
existentRoutes,
routesNameMapper,
) => {
const originalPath = parsePath(pathName, pathParams);
const pathNames = pathName.split('/').filter((x) => x);
const originalPathNames = originalPath.split('/').filter((x) => x);
const pathBreadcrumbs = pathNames
.reduce((currentBreadcrumbs, path, index) => {
const reverseParsedPath = `/${originalPathNames.slice(0, index + 1).join('/')}`;
const existentPath = find(existentRoutes, { path: reverseParsedPath });
if (existentPath) {
const to = `/${pathNames.slice(0, index + 1).join('/')}`;
const customRouteNameMapper = find(routesNameMapper, { route: existentPath.path });
currentBreadcrumbs.push({
to,
originalPath: reverseParsedPath,
title: get(customRouteNameMapper, 'title') || existentPath.title,
onBreadcrumbClick: () => routerPushFunction(to),
});
}
return currentBreadcrumbs;
}, [{
to: '/',
originalPath: '/',
title: 'Home',
onBreadcrumbClick: () => routerPushFunction('/'),
}]);
return pathBreadcrumbs;
};