From 258f0ef5e339cafe4ad940f460bb02feb2d5b7b4 Mon Sep 17 00:00:00 2001 From: Jon Snyder Date: Thu, 26 Oct 2023 22:27:02 -0600 Subject: [PATCH] Add infobox to new types, add description for decision context, add beta badges, move decisionContext to be inside personalization object. --- scripts/helpers/createExtensionManifest.js | 43 ++++++++---- src/view/actions/evaluateRulesets.jsx | 78 ++++++++++++++++------ src/view/actions/sendEvent.jsx | 16 +++-- src/view/events/subscribeRulesetItems.jsx | 7 ++ src/view/forms/notice.jsx | 43 ++++++++++++ src/view/forms/simpleMap.jsx | 19 +++++- 6 files changed, 165 insertions(+), 41 deletions(-) create mode 100644 src/view/forms/notice.jsx diff --git a/scripts/helpers/createExtensionManifest.js b/scripts/helpers/createExtensionManifest.js index 17e74740..6a775a11 100644 --- a/scripts/helpers/createExtensionManifest.js +++ b/scripts/helpers/createExtensionManifest.js @@ -436,6 +436,20 @@ const createExtensionManifest = ({ version }) => { }, includeRenderedPropositions: { type: "boolean" + }, + decisionContext: { + anyOf: [ + { + type: "string", + pattern: "^%[^%]+%$" + }, + { + type: "object", + additionalProperties: { + type: "string" + } + } + ] } }, additionalProperties: false @@ -774,19 +788,24 @@ const createExtensionManifest = ({ version }) => { renderDecisions: { type: "boolean" }, - decisionContext: { - anyOf: [ - { - type: "string", - pattern: "^%[^%]+%$" - }, - { - type: "object", - additionalProperties: { - type: "string" - } + personalization: { + type: "object", + properties: { + decisionContext: { + anyOf: [ + { + type: "string", + pattern: "^%[^%]+%$" + }, + { + type: "object", + additionalProperties: { + type: "string" + } + } + ] } - ] + } } }, libPath: "dist/lib/actions/evaluateRulesets/index.js", diff --git a/src/view/actions/evaluateRulesets.jsx b/src/view/actions/evaluateRulesets.jsx index 05a1a646..1b886edb 100644 --- a/src/view/actions/evaluateRulesets.jsx +++ b/src/view/actions/evaluateRulesets.jsx @@ -14,28 +14,62 @@ import form from "../forms/form"; import instancePicker from "../forms/instancePicker"; import checkbox from "../forms/checkbox"; import simpleMap from "../forms/simpleMap"; +import notice from "../forms/notice"; -const evaluateRulesetsForm = form({}, [ - instancePicker({ name: "instanceName" }), - checkbox({ - name: "renderDecisions", - label: "Render decisions", - description: - "Select this option to render decisions. If you do not select this option, decisions will not be rendered.", - defaultValue: false - }), - simpleMap({ - name: "decisionContext", - label: "Decision context", - singularLabel: "Context item", - dataElementDescription: - "Provide a data element that resolves to a map of strings", - keyLabel: "Key", - keyLabelPlural: "Keys", - keyDescription: "Enter the context key", - valueLabel: "Value", - valueDescription: "Enter the context value" - }) -]); +const wrapGetInitialValues = getInitialValues => ({ initInfo }) => { + const { personalization = {}, ...otherSettings } = initInfo.settings || {}; + return getInitialValues({ + initInfo: { + ...initInfo, + settings: { ...personalization, ...otherSettings } + } + }); +}; + +const wrapGetSettings = getSettings => ({ values }) => { + const { decisionContext, ...settings } = getSettings({ values }); + if (decisionContext) { + settings.personalization = {}; + settings.personalization.decisionContext = decisionContext; + } + return settings; +}; + +const evaluateRulesetsForm = form( + { + wrapGetInitialValues, + wrapGetSettings + }, + [ + notice({ + title: "Evaluate rulesets action", + description: + "This action manually triggers ruleset evaluation. Rulesets are returned from Adobe Journey Optimizer in-browser-messages.", + beta: true + }), + instancePicker({ name: "instanceName" }), + checkbox({ + name: "renderDecisions", + label: "Render visual personalization decisions", + description: + "Check this to render visual personalization decisions for the ruleset items that match.", + defaultValue: false + }), + simpleMap({ + name: "decisionContext", + label: "Decision context", + singularLabel: "Context item", + description: + "Provide the keys and values that the rulesets will use to determine which experience to deliver.", + dataElementDescription: + "Provide a data element that resolves to a map of key/value pairs.", + keyLabel: "Key", + keyLabelPlural: "Keys", + keyDescription: "Enter the context key.", + valueLabel: "Value", + valueDescription: "Enter the context value." + }) + ] +); renderForm(evaluateRulesetsForm); diff --git a/src/view/actions/sendEvent.jsx b/src/view/actions/sendEvent.jsx index a07b4dc7..aee11f59 100644 --- a/src/view/actions/sendEvent.jsx +++ b/src/view/actions/sendEvent.jsx @@ -80,13 +80,15 @@ const wrapGetSettings = getSettings => ({ values }) => { surfaces, sendDisplayEvent, includeRenderedPropositions, + decisionContext, ...settings } = getSettings({ values }); if ( decisionScopes || surfaces || sendDisplayEvent === false || - includeRenderedPropositions + includeRenderedPropositions || + decisionContext ) { settings.personalization = {}; } @@ -102,6 +104,9 @@ const wrapGetSettings = getSettings => ({ values }) => { if (includeRenderedPropositions) { settings.personalization.includeRenderedPropositions = includeRenderedPropositions; } + if (decisionContext) { + settings.personalization.decisionContext = decisionContext; + } return settings; }; @@ -238,13 +243,16 @@ const decisionContext = simpleMap({ name: "decisionContext", label: "Decision context", singularLabel: "Context item", + description: + "Provide the keys and values that the rulesets will use to determine which experience to deliver.", dataElementDescription: - "Provide a data element that resolves to a map of strings", + "Provide a data element that resolves to a map of key/value pairs.", keyLabel: "Key", keyLabelPlural: "Keys", - keyDescription: "Enter the context key", + keyDescription: "Enter the context key.", valueLabel: "Value", - valueDescription: "Enter the context value" + valueDescription: "Enter the context value.", + beta: true }); const configOverrideFields = configOverrides(); diff --git a/src/view/events/subscribeRulesetItems.jsx b/src/view/events/subscribeRulesetItems.jsx index c3cc8338..74efa019 100644 --- a/src/view/events/subscribeRulesetItems.jsx +++ b/src/view/events/subscribeRulesetItems.jsx @@ -15,8 +15,15 @@ import form from "../forms/form"; import instancePicker from "../forms/instancePicker"; import fieldArray from "../forms/fieldArray"; import { validateSurface } from "../utils/surfaceUtils"; +import notice from "../forms/notice"; const subscribeRulesetItemsForm = form({}, [ + notice({ + title: "Subscribe ruleset items", + description: + "This event will trigger the rule whenever there are ruleset items that have matched. This is a good place to add an action to render the ruleset items. You can use the data element `%event.propositions%` to access the propositions. Or within a custom code action it is available as `event.propositions`.", + beta: true + }), instancePicker({ name: "instanceName" }), fieldArray({ name: "schemas", diff --git a/src/view/forms/notice.jsx b/src/view/forms/notice.jsx new file mode 100644 index 00000000..6118ebe1 --- /dev/null +++ b/src/view/forms/notice.jsx @@ -0,0 +1,43 @@ +/* +Copyright 2023 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import React from "react"; +import BetaBadge from "../components/betaBadge"; +import Alert from "../components/alert"; + +/** @typedef {import("./form").Form} Form */ +/** + * This create a notice as part of a form + * @param {object} options - Options for the notice + * @param {string} options.title - The title of the notice + * @param {string} options.description - The description of the notice + * @param {boolean} [options.beta] - Whether or not this is a beta feature. + * @returns {Form} A notice form element. + */ +export default function notice({ title, description, beta }) { + const titleElement = ( + <> + {title} + {beta && } + + ); + + return { + Component: () => { + return ( + + {description} + + ); + } + }; +} diff --git a/src/view/forms/simpleMap.jsx b/src/view/forms/simpleMap.jsx index 1fd21777..44c78116 100644 --- a/src/view/forms/simpleMap.jsx +++ b/src/view/forms/simpleMap.jsx @@ -20,6 +20,7 @@ import DataElementSelector from "../components/dataElementSelector"; import singleDataElementRegex from "../constants/singleDataElementRegex"; import { DATA_ELEMENT_REQUIRED } from "../constants/validationErrorMessages"; import FormElementContainer from "../components/formElementContainer"; +import BetaBadge from "../components/betaBadge"; const FORM = "form"; const DATA_ELEMENT = "dataElement"; @@ -36,6 +37,8 @@ const DATA_ELEMENT = "dataElement"; * @param {string} options.label - The label to use for the field. * @param {string} options.singularLabel - The singular label to use for the add * button. (i.e. "entry" for "Add entry") + * @param {string} options.description - The description to use for the field. + * This appears just below the radio buttons and above the array items. * @param {string} [options.dataElementDescription] - The description to use for * the data element field. Usually you would use this to describe the type the * data element should be. @@ -45,18 +48,22 @@ const DATA_ELEMENT = "dataElement"; * @param {string} [options.valueLabel] - The label to use for the value field. * @param {string} [options.valueDescription] - The description to use for the * value field. + * @param {boolean} [options.beta] - If true, a beta badge will be shown next to + * the label. * @returns {Form} A form field for an array of strings. */ export default function simpleMap({ name, label, singularLabel, + description, dataElementDescription, keyLabel, keyLabelPlural, keyDescription, valueLabel, - valueDescription + valueDescription, + beta }) { const itemSchema = object() .shape({ @@ -157,13 +164,19 @@ export default function simpleMap({ const [{ value: items }, , { setValue: setItems }] = useField( `${namePrefix}${name}` ); - + const labelElement = ( + <> + {label} + {beta && } + + ); return ( <> Manually enter {label.toLowerCase()}.