Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add siteRelativeEntityType link to multiple entities #1522

Merged
1 change: 1 addition & 0 deletions packages/common/src/content/_internal/computeProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export function computeProps(
content.slug || content.id,
content.typeKeywords
),
siteRelativeEntityType: getHubRelativeUrl(content.type),
workspaceRelative: getRelativeWorkspaceUrl("content", content.id),
thumbnail: thumbnailUrl,
contentEditUrl: getContentEditUrl(model.item, requestOptions),
Expand Down
29 changes: 22 additions & 7 deletions packages/common/src/content/_internal/internalContentUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import {
ISpatialReference,
IUser,
} from "@esri/arcgis-rest-types";
import { IHubContent, IHubLocation, PublisherSource } from "../../core";
import {
IHubContent,
IHubLocation,
PublisherSource,
getTypeFromEntity,
} from "../../core";
import {
IHubGeography,
GeographyProvenance,
Expand Down Expand Up @@ -224,22 +229,25 @@ export const isProxiedCSV = (
/**
* Get the relative URL to use for the item in a hub site
* @param type
* @param identifier
* @param identifier optional, if not pass, will return a URL to the entities,
* e.g. /initiatives, /projects
* NOTE: not all entities have the entities route set up, in that case, we will
* not return an URL, so they will be redirected back to the site home
* @param typeKeywords
* @returns
* @private
*/
export const getHubRelativeUrl = (
type: string,
identifier: string,
identifier?: string,
typeKeywords?: string[]
): string => {
// solution types have their own logic
let contentUrl =
getSolutionUrl(type, identifier, typeKeywords) ||
getInitiativeTemplateUrl(type, identifier, typeKeywords);
const family = getFamily(type);
if (!contentUrl) {
const family = getFamily(type);
const familiesWithPluralizedRoute = [
"app",
"dataset",
Expand All @@ -253,9 +261,9 @@ export const getHubRelativeUrl = (
];
// default to the catchall content route
let path = "/content";
// the exception
if (family === "feedback") {
// the exception
path = "/feedback/surveys";
path = identifier ? "/feedback/surveys" : "";
} else if (isPageType(type, typeKeywords)) {
// pages are in the document family,
// but instead of showing the page's metadata on /documents/about
Expand All @@ -265,7 +273,14 @@ export const getHubRelativeUrl = (
// the rule: route name is plural of family name
path = `/${family}s`;
}
contentUrl = `${path}/${identifier}`;
contentUrl = identifier ? `${path}/${identifier}` : `${path}`;
}
// TODO: once an entity has its entities route set up, add it to this list
const entitiesHaveEntitiesRoute = ["initiative", "project"];
// if there is no identifier and the entity does not have the entities route
// set up, do not return an url
if (!identifier && !entitiesHaveEntitiesRoute.includes(family)) {
contentUrl = "";
}
return contentUrl;
};
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/core/types/IHubEntityBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export interface IHubEntityLinks {
* Relative url of the entity, within a site
*/
siteRelative?: string;

siteRelativeEntityType?: string;

/**
* Relative workspace url of the entity, within a site
*/
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/events/_internal/computeLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function computeLinks(event: IEvent): IHubEntityLinks {
return {
self: siteRelative,
siteRelative,
siteRelativeEntityType: getHubRelativeUrl("event"),
workspaceRelative: getRelativeWorkspaceUrl("Event", event.id),
// TODO
// thumbnail: "",
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/groups/_internal/computeLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { IHubEntityLinks } from "../../core/types";
import { getRelativeWorkspaceUrl } from "../../core/getRelativeWorkspaceUrl";
import { getGroupHomeUrl } from "../../urls/getGroupHomeUrl";
import { getGroupThumbnailUrl } from "../../search/utils";
import { getHubRelativeUrl } from "../../content/_internal/internalContentUtils";

/**
* Compute the links that get appended to a Hub Group
Expand All @@ -26,6 +27,7 @@ export function computeLinks(
return {
self: getGroupHomeUrl(group.id, requestOptions),
siteRelative: `/groups/${group.id}`,
siteRelativeEntityType: getHubRelativeUrl("Group"),
workspaceRelative: getRelativeWorkspaceUrl("Group", group.id),
thumbnail: getGroupThumbnailUrl(requestOptions.portal, group, token),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function computeLinks(
return {
self: getItemHomeUrl(item.id, requestOptions),
siteRelative: getHubRelativeUrl(item.type, getItemIdentifier(item)),
siteRelativeEntityType: getHubRelativeUrl(item.type),
workspaceRelative: getRelativeWorkspaceUrl(
item.type,
getItemIdentifier(item)
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/initiatives/_internal/computeLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function computeLinks(
return {
self: getItemHomeUrl(item.id, requestOptions),
siteRelative: getHubRelativeUrl(item.type, getItemIdentifier(item)),
siteRelativeEntityType: getHubRelativeUrl(item.type),
workspaceRelative: getRelativeWorkspaceUrl(
item.type,
getItemIdentifier(item)
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/pages/_internal/computeProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getItemHomeUrl } from "../../urls/get-item-home-url";
import { IHubPage } from "../../core/types/IHubPage";
import { getRelativeWorkspaceUrl } from "../../core/getRelativeWorkspaceUrl";
import { computeBaseProps } from "../../core/_internal/computeBaseProps";
import { getHubRelativeUrl } from "../../content/_internal/internalContentUtils";

/**
* Given a model and a page, set various computed properties that can't be directly mapped
Expand Down Expand Up @@ -37,6 +38,7 @@ export function computeProps(
page.links = {
self: getItemHomeUrl(page.id, requestOptions),
siteRelative: `/pages/${page.id}`,
siteRelativeEntityType: getHubRelativeUrl("page"),
workspaceRelative: getRelativeWorkspaceUrl("page", page.id),
layoutRelative: `/pages/${page.id}/edit`,
thumbnail: thumbnailUrl,
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/projects/_internal/computeLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function computeLinks(
return {
self: getItemHomeUrl(item.id, requestOptions),
siteRelative: getHubRelativeUrl(item.type, getItemIdentifier(item)),
siteRelativeEntityType: getHubRelativeUrl(item.type),
workspaceRelative: getRelativeWorkspaceUrl(
item.type,
getItemIdentifier(item)
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/sites/_internal/computeLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function computeLinks(
return {
self: item.url,
siteRelative: getHubRelativeUrl(item.type, item.id, item.typeKeywords),
siteRelativeEntityType: getHubRelativeUrl(item.type),
layoutRelative: "/edit",
workspaceRelative: getRelativeWorkspaceUrl(
item.type,
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/templates/_internal/computeLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function computeLinks(
return {
self: itemHomeUrl,
siteRelative: siteRelativeUrl,
siteRelativeEntityType: getHubRelativeUrl(item.type),
workspaceRelative: isDeployed
? itemHomeUrl
: getRelativeWorkspaceUrl(item.type, getItemIdentifier(item)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import {
getContentEditUrl,
getExtentObject,
deriveLocationFromItem,
getHubRelativeUrl,
} from "../../../src/content/_internal/internalContentUtils";
import * as internalContentUtils from "../../../src/content/_internal/internalContentUtils";
import { IHubRequestOptions } from "../../../src/types";
import { cloneObject } from "../../../src/util";
import { MOCK_HUB_REQOPTS } from "../../mocks/mock-auth";
import { IHubLocation } from "../../../src";
import * as _enrichmentsModule from "../../../src/items/_enrichments";
import { IHubAdditionalResource } from "../../../src/core/types/IHubAdditionalResource";

describe("getContentEditUrl", () => {
let requestOptions: IHubRequestOptions;
Expand Down Expand Up @@ -471,3 +471,75 @@ describe("deriveLocationFromItem", () => {
});
});
});

describe("getHubRelativeUrl", () => {
describe("handle when there is an identifier", () => {
const identifier = "a-slug";
it("should handle a family that does not have a puralized route", () => {
// 'report template' should be in the 'content' family
const result = getHubRelativeUrl("report template", identifier);
expect(result).toBe(`/content/${identifier}`);
});
it("should handle initiatives", () => {
const result = getHubRelativeUrl("Hub Initiative", identifier);
expect(result).toBe(`/initiatives/${identifier}`);
});
it("should handle projects", () => {
const result = getHubRelativeUrl("Hub Project", identifier);
expect(result).toBe(`/projects/${identifier}`);
});
it("should handle initiative templates", () => {
let result = getHubRelativeUrl("Hub Initiative", identifier, [
"hubInitiativeTemplate",
]);
expect(result).toBe(`/initiatives/templates/${identifier}/about`);
result = getHubRelativeUrl("Hub Initiative Template", identifier);
expect(result).toBe(`/initiatives/templates/${identifier}/about`);
});
it("should handle solution templates", () => {
let result = getHubRelativeUrl("Web Mapping Application", identifier, [
"hubSolutionTemplate",
]);
expect(result).toBe(`/templates/${identifier}/about`);
result = getHubRelativeUrl("Web Mapping Application", identifier);
expect(result).toBe(`/apps/${identifier}`);
result = getHubRelativeUrl("Solution", identifier);
expect(result).toBe(`/templates/${identifier}/about`);
result = getHubRelativeUrl("Solution", identifier, ["Deployed"]);
expect(result).toBe(`/content/${identifier}/about`);
});
it("should handle feedback", () => {
const result = getHubRelativeUrl("Form", identifier);
expect(result).toBe(`/feedback/surveys/${identifier}`);
});
it("should handle discussion", () => {
const result = getHubRelativeUrl("Discussion", identifier);
expect(result).toBe(`/discussions/${identifier}`);
});
});
describe("handle when there is no identifier", () => {
it("should handle a family that does not have a puralized route", () => {
// 'report template' should be in the 'content' family
let result = getHubRelativeUrl("report template");
expect(result).toBe("");
result = getHubRelativeUrl("StoryMap");
expect(result).toBe("");
});
it("should handle initiatives", () => {
const result = getHubRelativeUrl("Hub Initiative");
expect(result).toBe(`/initiatives`);
});
it("should handle projects", () => {
const result = getHubRelativeUrl("Hub Project");
expect(result).toBe(`/projects`);
});
it("should handle feedback", () => {
const result = getHubRelativeUrl("Form");
expect(result).toBe("");
});
it("should handle discussion", () => {
const result = getHubRelativeUrl("Discussion");
expect(result).toBe("");
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ describe("PropertyMapper", () => {
links: {
self: "/events/event-title-31c",
siteRelative: "/events/event-title-31c",
siteRelativeEntityType: "",
workspaceRelative: "/workspace/events/31c",
},
slug: "event-title-31c",
Expand Down
1 change: 1 addition & 0 deletions packages/common/test/events/_internal/computeLinks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe("computeLinks", () => {
expect(results).toEqual({
self: "/events/my-events-are-awesome-123-31c",
siteRelative: "/events/my-events-are-awesome-123-31c",
siteRelativeEntityType: "",
workspaceRelative: "/workspace/events/31c",
});
});
Expand Down
1 change: 1 addition & 0 deletions packages/common/test/groups/_internal/computeLinks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe("computeLinks", () => {
const chk = computeLinks(group, authdCtxMgr.context.requestOptions);

expect(chk.siteRelative).toBe("/groups/00c");
expect(chk.siteRelativeEntityType).toBe("");
expect(chk.workspaceRelative).toBe("/workspace/groups/00c");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe("computeLinks", () => {
const chk = computeLinks(item, authdCtxMgr.context.requestOptions);

expect(chk.siteRelative).toBe("/initiatives/templates/mock-slug/about");
expect(chk.siteRelativeEntityType).toBe("");
expect(chk.workspaceRelative).toBe(
"/workspace/initiativeTemplates/mock-slug"
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ describe("computeLinks", () => {
const chk = computeLinks(item, authdCtxMgr.context.requestOptions);

expect(chk.siteRelative).toBe("/initiatives/mock-slug");
expect(chk.siteRelativeEntityType).toBe("/initiatives");
expect(chk.workspaceRelative).toBe("/workspace/initiatives/mock-slug");
});
it("generates a links hash using the initiative's id when no slug is available", () => {
const chk = computeLinks(item, authdCtxMgr.context.requestOptions);

expect(chk.siteRelative).toBe("/initiatives/00c");
expect(chk.siteRelativeEntityType).toBe("/initiatives");
expect(chk.workspaceRelative).toBe("/workspace/initiatives/00c");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ describe("computeLinks", () => {
const chk = computeLinks(item, authdCtxMgr.context.requestOptions);

expect(chk.siteRelative).toBe("/projects/00c");
expect(chk.siteRelativeEntityType).toBe("/projects");
expect(chk.workspaceRelative).toBe("/workspace/projects/00c");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ describe("eventToSearchResult", () => {
links: {
self: `/events/my-event-title-${event.id}`,
siteRelative: `/events/my-event-title-${event.id}`,
siteRelativeEntityType: "",
workspaceRelative: `/workspace/events/${event.id}`,
},
tags: event.tags,
Expand Down Expand Up @@ -93,6 +94,7 @@ describe("eventToSearchResult", () => {
links: {
self: `/events/my-event-title-${event.id}`,
siteRelative: `/events/my-event-title-${event.id}`,
siteRelativeEntityType: "",
workspaceRelative: `/workspace/events/${event.id}`,
},
tags: event.tags,
Expand Down
1 change: 1 addition & 0 deletions packages/common/test/sites/_internal/computeLinks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe("computeLinks", () => {

expect(chk.self).toBe("https://some-url.com");
expect(chk.siteRelative).toBe("/content/00c");
expect(chk.siteRelativeEntityType).toBe("");
expect(chk.workspaceRelative).toBe("/workspace/sites/00c");
expect(chk.layoutRelative).toBe("/edit");
});
Expand Down
Loading