Skip to content
Open
5 changes: 5 additions & 0 deletions .changeset/brown-moose-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@esri/hub-common": patch
---

hide incomplete download format configuration ui and prevent saving discussion settings on enterprise
7 changes: 6 additions & 1 deletion packages/common/src/content/HubContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,12 @@ export class HubContent

// 2. Apply transforms to relevant entity values so they
// can be consumed by the editor
if (shouldShowDownloadsConfiguration(this.entity)) {
if (
shouldShowDownloadsConfiguration(
this.entity,
this.context.hubRequestOptions
)
) {
editor.downloadFormats = getDownloadConfigurationDisplayFormats(
this.entity
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const buildUiSchema = async (
i18nScope: string,
options: EntityEditorOptions,
_context: IArcGISContext
// eslint-disable-next-line @typescript-eslint/require-await
): Promise<IUiSchema> => {
const uiSchema: IUiSchema = {
type: "Layout",
Expand Down Expand Up @@ -147,7 +148,12 @@ export const buildUiSchema = async (
});
}

if (shouldShowDownloadsConfiguration(options as IHubEditableContent)) {
if (
shouldShowDownloadsConfiguration(
options as IHubEditableContent,
_context.hubRequestOptions
)
) {
const downloadsSection = getDownloadsSection(
i18nScope,
options as IHubEditableContent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IHubEditableContent } from "../../core/types/IHubEditableContent";
import { canUseExportImageFlow } from "../../downloads/_internal/canUseExportImageFlow";
import { IHubRequestOptions } from "../../hub-types";
import { getProp } from "../../objects/get-prop";

/**
Expand All @@ -11,11 +12,18 @@ import { getProp } from "../../objects/get-prop";
* could be downloaded with a change in item / service settings.
*
* @param entity entity to check
* @param hubRequestOptions hub request options (temporarily to ensure not portal)
* @returns whether downloads configuration should be shown
*/
export function shouldShowDownloadsConfiguration(
entity: IHubEditableContent
entity: IHubEditableContent,
hubRequestOptions: IHubRequestOptions
): boolean {
// Enterprise can't support download configuration at this time
if (hubRequestOptions.isPortal) {
return false;
}

// NOTE: At this time, product has asked that we hide the downloads configuration
// for multi-layer service entities.
const isReferenceLayerEntity =
Expand Down
34 changes: 20 additions & 14 deletions packages/common/src/content/edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,14 @@ export async function createContent(
const newContent = mapper.storeToEntity(model, {}) as IHubEditableContent;

// create the entity settings
const entitySetting = await createOrUpdateEntitySettings(
newContent,
requestOptions
);
newContent.entitySettingsId = entitySetting.id;
newContent.discussionSettings = entitySetting.settings.discussions;
if (!requestOptions.isPortal) {
const entitySetting = await createOrUpdateEntitySettings(
newContent,
requestOptions
);
newContent.entitySettingsId = entitySetting.id;
newContent.discussionSettings = entitySetting.settings.discussions;
}

// TODO:
// newContent = computeProps(model, newContent, requestOptions);
Expand Down Expand Up @@ -157,8 +159,10 @@ export async function updateContent(
const isMainEntityExtractDisabled =
isHostedFeatureServiceMainEntity(content) &&
downloadFlow !== "createReplica";
const wasDownloadsConfigurationDisplayed =
shouldShowDownloadsConfiguration(content);
const wasDownloadsConfigurationDisplayed = shouldShowDownloadsConfiguration(
content,
requestOptions
);
if (
wasDownloadsConfigurationDisplayed && // whether the downloads configuration was displayed
downloadFlow && // whether the entity can be downloaded
Expand Down Expand Up @@ -249,12 +253,14 @@ export async function updateContent(
);

// create or update entity settings
const entitySetting = await createOrUpdateEntitySettings(
updatedContent,
requestOptions
);
updatedContent.entitySettingsId = entitySetting.id;
updatedContent.discussionSettings = entitySetting.settings.discussions;
if (!requestOptions.isPortal) {
const entitySetting = await createOrUpdateEntitySettings(
updatedContent,
requestOptions
);
updatedContent.entitySettingsId = entitySetting.id;
updatedContent.discussionSettings = entitySetting.settings.discussions;
}

return updatedContent;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { shouldShowDownloadsConfiguration } from "../../../src/content/_internal/shouldShowDownloadsConfiguration";

describe("shouldShowDownloadsConfiguration", () => {
const hubRequestOptions = { isPortal: false } as any;
const portalRequestOptions = { isPortal: true } as any;

it("returns false if isPortal is true", () => {
const entity = {
type: "Feature Service",
url: "https://example.com/arcgis/rest/services/test/0",
} as any;
expect(shouldShowDownloadsConfiguration(entity, portalRequestOptions)).toBe(
false
);
});

it("returns true for reference layer entity (Feature Service with /<layerId> url)", () => {
const entity = {
type: "Feature Service",
url: "https://example.com/arcgis/rest/services/test/2",
} as any;
expect(shouldShowDownloadsConfiguration(entity, hubRequestOptions)).toBe(
true
);
});

it("returns true for reference layer entity (Map Service with /<layerId> url)", () => {
const entity = {
type: "Map Service",
url: "https://example.com/arcgis/rest/services/test/5",
} as any;
expect(shouldShowDownloadsConfiguration(entity, hubRequestOptions)).toBe(
true
);
});

it("returns false for Feature Service without layerId in url", () => {
const entity = {
type: "Feature Service",
url: "https://example.com/arcgis/rest/services/test",
} as any;
expect(shouldShowDownloadsConfiguration(entity, hubRequestOptions)).toBe(
false
);
});

it("returns true for single layer entity", () => {
const entity = {
type: "Feature Service",
url: "https://example.com/arcgis/rest/services/test",
extendedProps: { server: { layers: [{ id: 0 }] } },
} as any;
expect(shouldShowDownloadsConfiguration(entity, hubRequestOptions)).toBe(
true
);
});

it("returns false for multi-layer entity", () => {
const entity = {
type: "Feature Service",
url: "https://example.com/arcgis/rest/services/test",
extendedProps: { server: { layers: [{ id: 0 }, { id: 1 }] } },
} as any;
expect(shouldShowDownloadsConfiguration(entity, hubRequestOptions)).toBe(
false
);
});

it("returns true if canUseExportImageFlow returns true", () => {
const entity = {
type: "Image Service",
url: "https://example.com/arcgis/rest/services/test",
typeKeywords: [],
} as any;

expect(shouldShowDownloadsConfiguration(entity, hubRequestOptions)).toBe(
true
);
});

it("returns false if none of the conditions are met", () => {
const entity = { type: "PDF" } as any;
expect(shouldShowDownloadsConfiguration(entity, hubRequestOptions)).toBe(
false
);
});
});
81 changes: 81 additions & 0 deletions packages/common/test/content/edit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,46 @@
expect(modelToCreate.item.properties.orgUrlKey).toBe("dcdev");
expect(createOrUpdateEntitySettingsSpy).toHaveBeenCalledTimes(1);
});
it("doesn't set entity settings in enterprise", async () => {
const createSpy = spyOn(modelUtils, "createModel").and.callFake(

Check failure on line 126 in packages/common/test/content/edit.spec.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20)

test/content/edit.spec.ts > content editing: > create content: > doesn't set entity settings in enterprise

ReferenceError: spyOn is not defined ❯ test/content/edit.spec.ts:126:25

Check failure on line 126 in packages/common/test/content/edit.spec.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 18)

test/content/edit.spec.ts > content editing: > create content: > doesn't set entity settings in enterprise

ReferenceError: spyOn is not defined ❯ test/content/edit.spec.ts:126:25
(m: IModel) => {
const newModel = cloneObject(m);
newModel.item.id = GUID;
return Promise.resolve(newModel);
}
);
createOrUpdateEntitySettingsSpy = spyOn(
createOrUpdateEntitySettingsUtils,
"createOrUpdateEntitySettings"
).and.returnValue(
Promise.resolve({
id: GUID,
...DEFAULT_SETTINGS,
})
);
const chk = await createContent(
{
name: "Hello World",
orgUrlKey: "dcdev",
type: "Web Map",
},
{
...MOCK_HUB_REQOPTS,
authentication: myMockAuth,
isPortal: true,
}
);

expect(chk.id).toBe(GUID);
expect(chk.name).toBe("Hello World");
// should create the item
expect(createSpy.calls.count()).toBe(1);
const modelToCreate = createSpy.calls.argsFor(0)[0];
expect(modelToCreate.item.title).toBe("Hello World");
// expect(modelToCreate.item.type).toBe("Hub Content");
expect(modelToCreate.item.properties.orgUrlKey).toBe("dcdev");
expect(createOrUpdateEntitySettingsSpy.calls.count()).toBe(0);
});
});
describe("update content:", () => {
let getItemSpy: ReturnType<typeof vi.fn>;
Expand Down Expand Up @@ -203,6 +243,47 @@
expect(updateServiceSpy).not.toHaveBeenCalled();
expect(createOrUpdateEntitySettingsSpy).toHaveBeenCalledTimes(1);
});
it("doesn't update entity settings in portal", async () => {
const content: IHubEditableContent = {
itemControl: "edit",
id: GUID,
name: "Hello World",
tags: ["Transportation"],
description: "Some longer description",
slug: "dcdev-wat-blarg",
orgUrlKey: "dcdev",
owner: "dcdev_dude",
type: "Hub Initiative",
createdDate: new Date(1595878748000),
createdDateSource: "item.created",
updatedDate: new Date(1595878750000),
updatedDateSource: "item.modified",
thumbnailUrl: "",
permissions: [],
schemaVersion: 1,
canEdit: false,
canDelete: false,
location: { type: "none" },
licenseInfo: "",
schedule: { mode: "automatic" },
};
const chk = await updateContent(content, {
...MOCK_HUB_REQOPTS,
authentication: myMockAuth,
isPortal: true,
});
expect(chk.id).toBe(GUID);
expect(chk.name).toBe("Hello World");
expect(chk.description).toBe("Some longer description");
expect(getItemSpy.calls.count()).toBe(1);

Check failure on line 278 in packages/common/test/content/edit.spec.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20)

test/content/edit.spec.ts > content editing: > update content: > doesn't update entity settings in portal

TypeError: Cannot read properties of undefined (reading 'count') ❯ test/content/edit.spec.ts:278:31

Check failure on line 278 in packages/common/test/content/edit.spec.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 18)

test/content/edit.spec.ts > content editing: > update content: > doesn't update entity settings in portal

TypeError: Cannot read properties of undefined (reading 'count') ❯ test/content/edit.spec.ts:278:31
expect(updateModelSpy.calls.count()).toBe(1);
const modelToUpdate = updateModelSpy.calls.argsFor(0)[0];
expect(modelToUpdate.item.description).toBe(content.description);
// No service is associated with Hub Initiatives
expect(getServiceSpy).not.toHaveBeenCalled();
expect(updateServiceSpy).not.toHaveBeenCalled();
expect(createOrUpdateEntitySettingsSpy.calls.count()).toBe(0);
});
it("handles when a location is explicitly set", async () => {
const content: IHubEditableContent = {
itemControl: "edit",
Expand Down
Loading