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

feat(): association group creation form and permission #1413

Merged
merged 27 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
de59356
feat(): add permissions for association group
jordantsanz Feb 14, 2024
614810b
feat(): add build defaults centralized system?
jordantsanz Feb 14, 2024
cfcefff
feat(): add editorModule func
jordantsanz Feb 20, 2024
0e3106f
fix(): rebase
jordantsanz Feb 20, 2024
0d2f80a
fix(): typing for defaults
jordantsanz Feb 20, 2024
8695c27
fix(): integrate with getWellKNownGroup
jordantsanz Feb 20, 2024
5e1c9ac
test(): add tests for buildDefaults
jordantsanz Feb 20, 2024
0b6499a
fix(): update translation strings
jordantsanz Feb 20, 2024
c00440f
fix(): remove text defaults
jordantsanz Feb 20, 2024
32d35a8
feat(): add buildDefaults to all entities and stat card
jordantsanz Feb 21, 2024
bec2315
Merge branch 'master' of github.com:Esri/hub.js into f/9089-associati…
jordantsanz Feb 21, 2024
090a708
refactor(): implement createViewGroup and createEditGroup defaults
jordantsanz Feb 21, 2024
e87b49f
fix(): fix coverage
jordantsanz Feb 21, 2024
30b8f02
feat(): add new util for assoc group initialization
jordantsanz Feb 22, 2024
3ac94b1
fix(): update getWellKNownGroup
jordantsanz Feb 26, 2024
aa0bbeb
fix(): update default group
jordantsanz Feb 26, 2024
2bd019f
fix(): add protected call
jordantsanz Feb 26, 2024
829b84a
fix(): add protected call
jordantsanz Feb 26, 2024
30084de
fix(): use protectGroup
jordantsanz Feb 26, 2024
65949bc
refactor(): make cleaner
jordantsanz Feb 26, 2024
54e03f8
fix(): rebump jobs
jordantsanz Feb 26, 2024
f55f091
fix(): pr feedback, doc and update setEntityAssocGroup
jordantsanz Feb 26, 2024
9b76033
fix(): remove priv and update membershipAccess default
jordantsanz Feb 26, 2024
c876d41
Merge branch 'master' of github.com:Esri/hub.js into f/9089-associati…
jordantsanz Feb 26, 2024
b04e023
fix(): add disabled options if no priv
jordantsanz Feb 26, 2024
6f3db7b
test(): 100% coverage
jordantsanz Feb 27, 2024
db258d1
Merge branch 'master' into f/9089-association-group
jordantsanz Feb 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions packages/common/src/core/schemas/internal/getEditorSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
IConfigurationSchema,
IUiSchema,
IEditorConfig,
IConfigurationValues,
IEditorModuleType,
IEntityEditorModuleType,
} from "../types";
import { filterSchemaToUiSchema } from "./filterSchemaToUiSchema";
import { SiteEditorType } from "../../../sites/_internal/SiteSchema";
Expand Down Expand Up @@ -46,14 +49,15 @@ export async function getEditorSchemas(
// the entity type and the provided editor type
let schema: IConfigurationSchema;
let uiSchema: IUiSchema;
let defaults: IConfigurationValues;
switch (editorType) {
case "site":
const { SiteSchema } = await import(
"../../../sites/_internal/SiteSchema"
);
schema = cloneObject(SiteSchema);

const siteModule = await {
const siteModule: IEntityEditorModuleType = await {
"hub:site:edit": () =>
import("../../../sites/_internal/SiteUiSchemaEdit"),
"hub:site:create": () =>
Expand All @@ -79,7 +83,7 @@ export async function getEditorSchemas(
);
schema = cloneObject(DiscussionSchema);

const discussionModule = await {
const discussionModule: IEntityEditorModuleType = await {
"hub:discussion:edit": () =>
import("../../../discussions/_internal/DiscussionUiSchemaEdit"),
"hub:discussion:create": () =>
Expand All @@ -101,7 +105,7 @@ export async function getEditorSchemas(
);
schema = cloneObject(ProjectSchema);

const projectModule = await {
const projectModule: IEntityEditorModuleType = await {
"hub:project:edit": () =>
import("../../../projects/_internal/ProjectUiSchemaEdit"),
"hub:project:create": () =>
Expand All @@ -122,7 +126,7 @@ export async function getEditorSchemas(
);
schema = cloneObject(InitiativeSchema);

const initiativeModule = await {
const initiativeModule: IEntityEditorModuleType = await {
"hub:initiative:edit": () =>
import("../../../initiatives/_internal/InitiativeUiSchemaEdit"),
"hub:initiative:create": () =>
Expand All @@ -142,7 +146,7 @@ export async function getEditorSchemas(
);
schema = cloneObject(PageSchema);

const pageModule = await {
const pageModule: IEntityEditorModuleType = await {
"hub:page:edit": () =>
import("../../../pages/_internal/PageUiSchemaEdit"),
}[type as PageEditorType]();
Expand All @@ -160,7 +164,7 @@ export async function getEditorSchemas(
);
schema = cloneObject(ContentSchema);

const contentModule = await {
const contentModule: IEntityEditorModuleType = await {
"hub:content:edit": () =>
import("../../../content/_internal/ContentUiSchemaEdit"),
"hub:content:discussions": () =>
Expand All @@ -182,7 +186,7 @@ export async function getEditorSchemas(
);
schema = cloneObject(TemplateSchema);

const templateModule = await {
const templateModule: IEditorModuleType = await {
jordantsanz marked this conversation as resolved.
Show resolved Hide resolved
"hub:template:edit": () =>
import("../../../templates/_internal/TemplateUiSchemaEdit"),
}[type as TemplateEditorType]();
Expand All @@ -200,9 +204,11 @@ export async function getEditorSchemas(
);
schema = cloneObject(GroupSchema);

const groupModule = await {
const groupModule: IEditorModuleType = await {
"hub:group:create:followers": () =>
import("../../../groups/_internal/GroupUiSchemaCreateFollowers"),
"hub:group:create:association": () =>
import("../../../groups/_internal/GroupUiSchemaCreateAssociation"),
"hub:group:create:view": () =>
import("../../../groups/_internal/GroupUiSchemaCreateView"),
"hub:group:create:edit": () =>
Expand All @@ -220,14 +226,23 @@ export async function getEditorSchemas(
context
);

// if we have the buildDefaults fn, then construct the defaults
if (groupModule.buildDefaults) {
jordantsanz marked this conversation as resolved.
Show resolved Hide resolved
defaults = await groupModule.buildDefaults(
i18nScope,
options as EntityEditorOptions,
context
);
}

break;

case "initiativeTemplate":
const { InitiativeTemplateSchema } = await import(
"../../../initiative-templates/_internal/InitiativeTemplateSchema"
);
schema = cloneObject(InitiativeTemplateSchema);
const initiativeTemplateModule = await {
const initiativeTemplateModule: IEditorModuleType = await {
"hub:initiativeTemplate:edit": () =>
import(
"../../../initiative-templates/_internal/InitiativeTemplateUiSchemaEdit"
Expand Down Expand Up @@ -256,5 +271,5 @@ export async function getEditorSchemas(
// filter out properties not used in the UI schema
schema = filterSchemaToUiSchema(schema, uiSchema);

return Promise.resolve({ schema, uiSchema });
return Promise.resolve({ schema, uiSchema, defaults });
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import {
* @param context
* @returns
*/
export const buildUiSchema = (
export const buildUiSchema = async (
i18nScope: string,
config: EntityEditorOptions,
context: IArcGISContext
): IUiSchema => {
): Promise<IUiSchema> => {
return {
type: "Layout",
elements: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { UiSchemaRuleEffects, IUiSchema } from "../../types";
* Exports the uiSchema of the stat card
* @returns
*/
export const buildUiSchema = (
export const buildUiSchema = async (
i18nScope: string,
config: IStatCardEditorOptions,
context: IArcGISContext
): IUiSchema => {
): Promise<IUiSchema> => {
const { themeColors } = config;
return {
type: "Layout",
Expand Down
50 changes: 50 additions & 0 deletions packages/common/src/core/schemas/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ import { ContentEditorTypes } from "../../content/_internal/ContentSchema";
import { TemplateEditorTypes } from "../../templates/_internal/TemplateSchema";
import { GroupEditorTypes } from "../../groups/_internal/GroupSchema";
import { InitiativeTemplateEditorTypes } from "../../initiative-templates/_internal/InitiativeTemplateSchema";
import {
CardEditorOptions,
EntityEditorOptions,
} from "./internal/EditorOptions";
import { IArcGISContext } from "../../ArcGISContext";

export interface IEditorConfig {
schema: IConfigurationSchema;
uiSchema: IUiSchema;
defaults?: IConfigurationValues;
}

/**
Expand Down Expand Up @@ -67,6 +73,50 @@ export const validEditorTypes = [
...validCardEditorTypes,
] as const;

/**
* An editor's module when dynamically imported depending on the EditorType. This
* will always have a buildUiSchema function, and sometimes it will have a
* buildDefaults function to override default values in the editor.
*/
export type IEditorModuleType = IEntityEditorModuleType | ICardEditorModuleType;

/**
* An entity editor's module when dynamically imported depending on the EditorType. This
* will always have a buildUiSchema function, and sometimes it will have a
* buildDefaults function to override default values in the editor.
*/
export interface IEntityEditorModuleType {
buildUiSchema: (
i18nScope: string,
options: EntityEditorOptions,
context: IArcGISContext
) => Promise<IUiSchema>;
buildDefaults?: (
i18nScope: string,
options: EntityEditorOptions,
context: IArcGISContext
) => Promise<IConfigurationValues>;
}

/**
* A card editor's module when dynamically imported depending on the EditorType. This
* will always have a buildUiSchema function, and sometimes it will have a
* buildDefaults function to override default values in the editor.
*/
export interface ICardEditorModuleType {
buildUiSchema: (
i18nScope: string,
config: CardEditorOptions,
context: IArcGISContext
) => Promise<IUiSchema>;

buildDefaults?: (
i18nScope: string,
options: CardEditorOptions,
context: IArcGISContext
) => Promise<IConfigurationValues>;
}

export enum UiSchemaRuleEffects {
SHOW = "SHOW",
HIDE = "HIDE",
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/groups/_internal/GroupSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const GroupEditorTypes = [
"hub:group:discussions",
// editor to create a followers group
"hub:group:create:followers",
// editor to create an association group
"hub:group:create:association",
"hub:group:create:view",
"hub:group:create:edit",
] as const;
Expand Down
132 changes: 132 additions & 0 deletions packages/common/src/groups/_internal/GroupUiSchemaCreateAssociation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import {
IConfigurationValues,
IUiSchema,
UiSchemaRuleEffects,
} from "../../core/schemas/types";
import { IArcGISContext } from "../../ArcGISContext";
import { EntityEditorOptions } from "../../core/schemas/internal/EditorOptions";
import { getWellKnownGroup } from "../getWellKnownGroup";

/**
* @private
* constructs the complete uiSchema for creating an association
* group. This defines how the schema properties should be
* rendered in the association group creation experience
*/
export const buildUiSchema = async (
i18nScope: string,
options: EntityEditorOptions,
context: IArcGISContext
): Promise<IUiSchema> => {
return {
type: "Layout",
elements: [
{
type: "Section",
options: { section: "stepper", scale: "l" },
elements: [
{
type: "Section",
labelKey: `${i18nScope}.sections.details.label`,
options: {
section: "step",
},
elements: [
{
labelKey: `${i18nScope}.fields.name.label`,
scope: "/properties/name",
type: "Control",
options: {
messages: [
{
type: "ERROR",
keyword: "required",
icon: true,
labelKey: `${i18nScope}.fields.name.requiredError`,
},
{
type: "ERROR",
keyword: "maxLength",
icon: true,
labelKey: `${i18nScope}.fields.name.maxLengthError`,
},
],
},
},
{
labelKey: `${i18nScope}.fields.summary.label`,
scope: "/properties/summary",
type: "Control",
options: {
control: "hub-field-input-input",
type: "textarea",
rows: 4,
messages: [
{
type: "ERROR",
keyword: "maxLength",
icon: true,
labelKey: `${i18nScope}.fields.summary.maxLengthError`,
},
],
},
},
],
},
{
type: "Section",
labelKey: `${i18nScope}.sections.membershipAccess.label`,
options: {
section: "step",
},
rule: {
effect: UiSchemaRuleEffects.DISABLE,
condition: {
scope: "/properties/name",
schema: { const: "" },
},
},
elements: [
{
labelKey: `${i18nScope}.fields.membershipAccess.label`,
scope: "/properties/membershipAccess",
type: "Control",
options: {
control: "hub-field-input-radio",
labels: [
`{{${i18nScope}.fields.membershipAccess.org:translate}}`,
`{{${i18nScope}.fields.membershipAccess.collab:translate}}`,
`{{${i18nScope}.fields.membershipAccess.createAssociation.any:translate}}`,
],
disabled: [false, false, options.isSharedUpdate],
},
},
{
labelKey: `${i18nScope}.fields.contributeContent.label`,
scope: "/properties/isViewOnly",
type: "Control",
options: {
control: "hub-field-input-radio",
labels: [
`{{${i18nScope}.fields.contributeContent.all:translate}}`,
`{{${i18nScope}.fields.contributeContent.createAssociation.admins:translate}}`,
],
},
},
],
},
],
},
],
};
};

export const buildDefaults = async (
jordantsanz marked this conversation as resolved.
Show resolved Hide resolved
i18nScope: string,
options: EntityEditorOptions,
context: IArcGISContext
): Promise<IConfigurationValues> => {
return {
...getWellKnownGroup("hubAssociationsGroup", context),
jordantsanz marked this conversation as resolved.
Show resolved Hide resolved
};
};
Loading
Loading