Skip to content

Commit

Permalink
feat: add a partners case to well known item catalog (#1517)
Browse files Browse the repository at this point in the history
  • Loading branch information
benstoltz authored May 24, 2024
1 parent db8646c commit 0ddf25f
Show file tree
Hide file tree
Showing 7 changed files with 346 additions and 19 deletions.
20 changes: 20 additions & 0 deletions packages/common/src/ArcGISContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,11 @@ export interface IArcGISContext {
*/
survey123Url: string;

/**
* Is the current users org type a community org?
*/
isCommunityOrg: boolean;

/**
* Return the token for a given app, if defined
* @param app
Expand Down Expand Up @@ -801,6 +806,21 @@ export class ArcGISContext implements IArcGISContext {
return this._trustedOrgs;
}

/**
* Returns whether the current user's org type is a community org
*/
public get isCommunityOrg(): boolean {
let result = false;
if (this._portalSelf) {
const orgType = getProp(
this._portalSelf,
"portalProperties.hub.settings.orgType"
);
result = orgType === "community";
}
return result;
}

/**
* Return the whole array of user resource tokens
*/
Expand Down
26 changes: 16 additions & 10 deletions packages/common/src/associations/wellKnownAssociationCatalogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,24 @@ export const getAvailableToRequestAssociationCatalogs = (
entity,
associationType
)?.filters;

// Default catalogs to include
const catalogNames: WellKnownCatalog[] = [
"myContent",
"favorites",
"organization",
"world",
"community",
"partners",
];
return catalogNames.map((name: WellKnownCatalog) => {
const options: IGetWellKnownCatalogOptions = {
user: context.currentUser,
filters,
collectionNames: [associationType as WellKnownCollection],
};
return getWellKnownCatalog(i18nScope, name, "item", options);
});

return catalogNames
.map((name: WellKnownCatalog) => {
const options: IGetWellKnownCatalogOptions = {
user: context.currentUser,
filters,
collectionNames: [associationType as WellKnownCollection],
context,
};
return getWellKnownCatalog(i18nScope, name, "item", options);
})
.filter(Boolean);
};
7 changes: 5 additions & 2 deletions packages/common/src/search/_internal/buildCatalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import { EntityType, IFilter, IHubCatalog, IHubCollection } from "../types";
* @param catalogName - well known catalog name
* @param filters - filters to build the catalog scope
* @param collections - collections to include in the catalog
* @param targetEntity - target entity type for the catalog
* @param title - optional title override for the catalog
* @returns {IHubCatalog}
*/
export function buildCatalog(
i18nScope: string,
catalogName: string,
filters: IFilter[],
collections: IHubCollection[],
targetEntity: EntityType
targetEntity: EntityType,
title?: string
): IHubCatalog {
const scopes = {
[targetEntity]: {
Expand All @@ -25,7 +28,7 @@ export function buildCatalog(
};
return {
schemaVersion: 1,
title: `{{${i18nScope}catalog.${catalogName}:translate}}`,
title: title || `{{${i18nScope}catalog.${catalogName}:translate}}`,
scopes,
collections,
};
Expand Down
96 changes: 95 additions & 1 deletion packages/common/src/search/wellKnownCatalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { HubFamily } from "../types";
import { EntityType, IFilter, IHubCatalog, IHubCollection } from "./types";
import { buildCatalog } from "./_internal/buildCatalog";
import { getProp } from "../objects";
import { IArcGISContext } from "..";

/**
* This is used to determine what IHubCatalog definition JSON object
Expand All @@ -16,7 +17,9 @@ export type WellKnownCatalog =
| "world"
| "editGroups"
| "viewGroups"
| "allGroups";
| "allGroups"
| "partners"
| "community";

/**
* This is used to determine what IHubCollection definition JSON object
Expand All @@ -29,6 +32,9 @@ export type WellKnownCollection =
| "solution"
| "projectAndInitiative";

/**TODO: On the next breaking change User and context should be
* removed from this interface and passed into the function as a single required context.
*/
/**
* A list of optional arguments to pass into getWellKnownCatalog
* user is the owner of the entity
Expand All @@ -40,6 +46,8 @@ export interface IGetWellKnownCatalogOptions {
collectionNames?: WellKnownCollection[];
/** additional filters to apply to the catalog scope */
filters?: IFilter[];
/** optional context */
context?: IArcGISContext;
}

/**
Expand Down Expand Up @@ -91,6 +99,9 @@ function validateUserExistence(
}
}

/** TODO: On the next breaking change we need to pull context and user out of options
* and make context a required parameter. User can be pulled out of context.
*/
/**
* Get an ITEM catalog based on the name and optional requests
* @param i18nScope Translation scope to be interpolated into the catalog
Expand All @@ -106,6 +117,7 @@ function getWellknownItemCatalog(
i18nScope = dotifyString(i18nScope);
let catalog;
const additionalFilters = getProp(options, "filters") || [];
const context = getProp(options, "context");
const collections = getWellknownCollections(
i18nScope,
"item",
Expand Down Expand Up @@ -148,6 +160,53 @@ function getWellknownItemCatalog(
"item"
);
break;
case "partners":
// Get trusted orgs that aren't the current user's org or the community org
const trustedOrgIds = context.trustedOrgIds.filter((orgId: string) => {
return (
orgId !== context.currentUser.orgId &&
orgId !== _getCOrgOrEOrgId(context)
);
});
// only build the catalog if there are trusted orgs
if (trustedOrgIds.length) {
catalog = buildCatalog(
i18nScope,
catalogName,
[
{
predicates: [
{
orgid: trustedOrgIds,
searchUserAccess: "includeTrustedOrgs",
},
],
},
...additionalFilters,
],
collections,
"item"
);
}
break;
case "community":
const communityOrgId = _getCOrgOrEOrgId(context);
// only build the catalog if there is a community org id
if (communityOrgId) {
catalog = buildCatalog(
i18nScope,
catalogName,
[{ predicates: [{ orgid: communityOrgId }] }, ...additionalFilters],
collections,
"item",
// If we're in a community org, use the community org name
// as the catalog title
context.isCommunityOrg
? _getEOrgName(communityOrgId, context)
: undefined
);
}
break;
case "world":
catalog = buildCatalog(
i18nScope,
Expand All @@ -164,6 +223,41 @@ function getWellknownItemCatalog(
return catalog;
}

/**
* Get the c-org or e-org ID. Defaults to the communityOrgId if the user is currently authed into
* an e-org; otherwise it looks up the trusted org relationship to get the e-org id
* @param context IArcGISContext
* @returns orgid of the c-org or e-org
*/
function _getCOrgOrEOrgId(context: IArcGISContext): string {
// extract the c-org / e-org relationship
const cOrgEOrgTrustedRelationship = context.trustedOrgs.find(
(org) => org.from.orgId === context.currentUser.orgId
);

// if we're in a community org, and there is a trusted org
// relationship, use the orgId from there (which would be
// the e-org id). Otherwise, use the c-org id
return context.isCommunityOrg && cOrgEOrgTrustedRelationship
? cOrgEOrgTrustedRelationship.to.orgId
: context.communityOrgId;
}

/**
* If the user is in a community org, get the e-org name from the trusted org relationship
* @param eOrgId E-org id
* @param context IArcGISContext
* @returns E-org name
*/
function _getEOrgName(eOrgId: string, context: IArcGISContext): string {
// extract the c-org / e-org relationship
const communityTrustedOrgRelationship = context.trustedOrgs.find(
(org) => org.to.orgId === eOrgId
);

return communityTrustedOrgRelationship.to.name;
}

/**
* Get a group catalog based on the name and optional requests
* @param i18nScope Translation scope to be interpolated into the catalog
Expand Down
3 changes: 3 additions & 0 deletions packages/common/test/ArcGISContextManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const onlinePortalSelfResponse = {
orgId: "FAKE_C_ORGID",
portalHostname: "my-community.maps.arcgis.com",
},
orgType: "enterprise",
},
},
},
Expand Down Expand Up @@ -284,6 +285,7 @@ describe("ArcGISContext:", () => {
expect(mgr.context.hubEnabled).toBeFalsy();
expect(mgr.context.isAlphaOrg).toBeFalsy();
expect(mgr.context.isBetaOrg).toBeFalsy();
expect(mgr.context.isCommunityOrg).toBeFalsy();
expect(mgr.context.environment).toBe("production");
// Hub Urls
const base = mgr.context.hubUrl;
Expand Down Expand Up @@ -489,6 +491,7 @@ describe("ArcGISContext:", () => {
expect(mgr.context.trustedOrgs).toEqual(
onlinePartneredOrgResponse.trustedOrgs
);
expect(mgr.context.isCommunityOrg).toBeFalsy();
});
it("verify tokens when passed session", async () => {
const t = new Date().getTime();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ describe("getAvailableToRequestAssociationCatalogs", () => {
"getWellKnownCatalog"
).and.returnValues(
{ schemaVersion: 1, title: "mock-myContent" },
{ schemaVersion: 1, title: "mock-favorites" },
{ schemaVersion: 1, title: "mock-organization" },
{ schemaVersion: 1, title: "mock-world" }
{ schemaVersion: 1, title: "mock-community" },
{ schemaVersion: 1, title: "mock-partners" }
);
});
afterEach(() => {
Expand Down Expand Up @@ -206,17 +206,20 @@ describe("getAvailableToRequestAssociationCatalogs", () => {
"some-scope",
{ type: "Hub Project" } as HubEntity,
"initiative",
{} as ArcGISContext
{
trustedOrgIds: ["abc123", "def456", "ghi789"],
communityOrgId: "mock-community-org",
} as ArcGISContext
);

expect(getAvailableToRequestEntitiesQuerySpy).toHaveBeenCalledTimes(1);
expect(getWellknownCatalogSpy).toHaveBeenCalledTimes(4);
expect(catalogs.length).toBe(4);
expect(catalogs).toEqual([
{ schemaVersion: 1, title: "mock-myContent" },
{ schemaVersion: 1, title: "mock-favorites" },
{ schemaVersion: 1, title: "mock-organization" },
{ schemaVersion: 1, title: "mock-world" },
{ schemaVersion: 1, title: "mock-community" },
{ schemaVersion: 1, title: "mock-partners" },
]);
});
});
Loading

0 comments on commit 0ddf25f

Please sign in to comment.