@firecms/core
Version:
Awesome Firebase/Firestore-based headless open-source CMS
129 lines (117 loc) • 4.96 kB
text/typescript
import { EntityCollection, EntityCustomView } from "../types";
import { getCollectionPathsCombinations, removeInitialAndTrailingSlashes } from "./navigation_utils";
import { resolveEntityView } from "./resolutions";
export type NavigationViewInternal<M extends Record<string, any> = any> =
| NavigationViewEntityInternal<M>
| NavigationViewCollectionInternal<M>
| NavigationViewEntityCustomInternal<M>;
export interface NavigationViewEntityInternal<M extends Record<string, any>> {
type: "entity";
entityId: string;
path: string;
fullIdPath: string;
fullPath: string;
parentCollection: EntityCollection<M>;
}
export interface NavigationViewCollectionInternal<M extends Record<string, any>> {
type: "collection";
id: string;
path: string;
fullIdPath: string;
fullPath: string;
collection: EntityCollection<M>;
}
export interface NavigationViewEntityCustomInternal<M extends Record<string, any>> {
type: "custom_view";
path: string;
fullIdPath: string;
fullPath: string;
entityId: string;
view: EntityCustomView<M>;
}
export function getNavigationEntriesFromPath(props: {
path: string,
collections: EntityCollection[] | undefined,
currentFullPath?: string,
currentFullIdPath?: string,
contextEntityViews?: EntityCustomView<any>[]
}): NavigationViewInternal [] {
const {
path,
collections = [],
currentFullPath,
currentFullIdPath
} = props;
const subpaths = removeInitialAndTrailingSlashes(path).split("/");
const subpathCombinations = getCollectionPathsCombinations(subpaths);
const result: NavigationViewInternal[] = [];
for (let i = 0; i < subpathCombinations.length; i++) {
const subpathCombination = subpathCombinations[i];
let collection: EntityCollection<any> | undefined;
collection = collections && collections.find((entry) => entry.id === subpathCombination);
if (!collection) {
collection = collections && collections.find((entry) => entry.path === subpathCombination);
}
if (collection) {
const collectionPath = currentFullPath && currentFullPath.length > 0
? (currentFullPath + "/" + collection.path)
: collection.path;
const fullIdPath = currentFullIdPath && currentFullIdPath.length > 0
? (currentFullIdPath + "/" + collection.id)
: collection.id;
result.push({
type: "collection",
id: collection.id,
path: collectionPath,
fullPath: collectionPath,
fullIdPath,
collection
});
const restOfThePath = removeInitialAndTrailingSlashes(removeInitialAndTrailingSlashes(path).replace(subpathCombination, ""));
const nextSegments = restOfThePath.length > 0 ? restOfThePath.split("/") : [];
if (nextSegments.length > 0) {
const entityId = nextSegments[0];
const fullPath = collectionPath + "/" + entityId;
result.push({
type: "entity",
entityId,
path: collectionPath,
fullIdPath,
fullPath: fullPath,
parentCollection: collection
});
if (nextSegments.length > 1) {
const newPath = nextSegments.slice(1).join("/");
if (!collection) {
throw Error("collection not found resolving path: " + collection);
}
const entityViews = collection.entityViews;
const customView = entityViews && entityViews
.map((entry) => resolveEntityView(entry, props.contextEntityViews))
.filter(Boolean)
.find((entry) => entry!.key === newPath);
if (customView) {
result.push({
type: "custom_view",
path: collectionPath,
entityId: entityId,
fullIdPath,
fullPath: fullPath + "/" + customView.key,
view: customView
});
} else if (collection.subcollections) {
result.push(...getNavigationEntriesFromPath({
path: newPath,
collections: collection.subcollections,
currentFullPath: fullPath,
currentFullIdPath: fullIdPath,
contextEntityViews: props.contextEntityViews
}));
}
}
}
break;
}
}
return result;
}