@designcrowd/library.brand-page 6.1.1-json-prereq-3 → 6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/src/{CreatedOnBrandCrowd-de-de-hj_ievMc.js → CreatedOnBrandCrowd-de-de-B5B5ThJ6.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-jAOSpfCw.js → CreatedOnBrandCrowd-en-us-a48CaORy.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-DZMVc-y3.js → CreatedOnBrandCrowd-es-es-xpuZ317-.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-DvB54H38.js → CreatedOnBrandCrowd-fr-ca-V-iUMArW.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-DvB54H38.js → CreatedOnBrandCrowd-fr-fr-V-iUMArW.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-bf-x1xhi.js → CreatedOnBrandCrowd-pt-br-DZ0NKSAy.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-bf-x1xhi.js → CreatedOnBrandCrowd-pt-pt-DZ0NKSAy.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-B-NY1B44.js → CreatedOnDcom-de-de-_950cgGp.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-Cd4C6KQf.js → CreatedOnDcom-en-us-DogKzH-g.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-DONlsQsm.js → CreatedOnDcom-es-es-CmGM3IPX.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-Dsv3FRpZ.js → CreatedOnDcom-fr-ca-BonEDkWZ.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-DOgyvY5C.js → CreatedOnDcom-fr-fr-DQHtKrd_.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-DX66MhJS.js → CreatedOnDcom-pt-br-CtYJSBjs.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-COe2G0bU.js → CreatedOnDcom-pt-pt-DoO9r4lA.js} +1 -1
- package/lib/src/brand-page/components/contact-form/ContactForm.mixin.js +7 -8
- package/lib/src/brand-page/components/mailing-list/MailingList.mixin.js +6 -4
- package/lib/src/brand-page/components/page-footer/PageFooter.mixin.d.ts +1 -0
- package/lib/src/brand-page/components/page-footer/PageFooter.mixin.js +4 -1
- package/lib/src/brand-page/components/payment/Payment.mixin.js +4 -3
- package/lib/src/brand-page/components/payment/__fixtures__/request-payment.d.ts +1 -0
- package/lib/src/brand-page/components/payment/__fixtures__/support-me.d.ts +1 -0
- package/lib/src/brand-page/components/payment/request-payment/RequestPayment.mixin.d.ts +1 -0
- package/lib/src/brand-page/components/payment/request-payment/RequestPayment.mixin.js +4 -1
- package/lib/src/brand-page/composables/consent.composable.d.ts +2 -0
- package/lib/src/brand-page/composables/consent.composable.js +9 -3
- package/lib/src/brand-page/models/brand-page-context.model.d.ts +7 -0
- package/lib/src/brand-page/models/index.d.ts +26 -34
- package/lib/src/brand-page/utils/context.util.d.ts +8 -0
- package/lib/src/brand-page/utils/context.util.js +8 -0
- package/lib/src/brand-page/utils/migration.util.js +0 -11
- package/lib/src/brand-page/utils/text.util.d.ts +1 -13
- package/lib/src/brand-page/utils/text.util.js +0 -64
- package/lib/src/brand-page/utils/vcard.util.js +4 -4
- package/lib/src/brand-page/utils/view-model.util.d.ts +0 -1
- package/lib/src/brand-page/utils/view-model.util.js +20 -68
- package/lib/src/brand-page/view-models.d.ts +3 -3
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +51 -18
- package/lib/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.d.ts +1 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.d.ts +9 -2
- package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.js +10 -6
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontSize.d.ts +20 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontSize.js +44 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/LineHeight.d.ts +27 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/LineHeight.js +44 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +103 -24
- package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.js +8 -0
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +9 -3
- package/lib/src/brand-page-maker/stores/ui/ui-store.d.ts +1 -1
- package/lib/src/brand-page-maker/utils/index.d.ts +0 -2
- package/lib/src/brand-page-maker/utils/index.js +0 -2
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +5 -28
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +5 -48
- package/lib/src/brand-page-maker/validators/field.validator.js +2 -10
- package/lib/src/clients/models.d.ts +2 -0
- package/lib/src/css/library.brand-page-brandCrowd.min.css +99 -102
- package/lib/src/css/library.brand-page-brandPage.min.css +99 -102
- package/lib/src/css/library.brand-page-designCom.min.css +99 -102
- package/lib/src/css/library.brand-page-preview.min.css +99 -102
- package/lib/src/index.d.ts +1 -1
- package/lib/src/index.mjs +219 -221
- package/lib/src/{lib-scDtk-Pi.js → lib-DtalJKI3.js} +72445 -75920
- package/lib/src/lib.js +1 -2
- package/lib/src/metadata-builder/ai-metadata-executor.d.ts +1 -0
- package/lib/src/metadata-builder/ai-metadata-executor.js +19 -0
- package/lib/src/metadata-builder/builders/section-builders/about-section-builder.js +3 -2
- package/lib/src/metadata-builder/builders/section-builders/banner-section-builder.js +3 -2
- package/lib/src/metadata-builder/builders/section-builders/booking-section-builder.js +3 -2
- package/lib/src/metadata-builder/builders/section-builders/contact-form-builder.js +4 -3
- package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +3 -2
- package/lib/src/metadata-builder/builders/section-builders/mailing-list-builder.js +2 -1
- package/lib/src/metadata-builder/builders/section-builders/mailing-list-section-builder.js +2 -1
- package/lib/src/metadata-builder/builders/section-builders/profile-section-builder.js +4 -3
- package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +3 -2
- package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +2 -1
- package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +11 -15
- package/lib/src/metadata-builder/builders/update-content-text-builder.d.ts +17 -0
- package/lib/src/metadata-builder/builders/update-content-text-builder.js +103 -0
- package/lib/src/metadata-builder/builders/update-content-text-style-builder.d.ts +16 -0
- package/lib/src/metadata-builder/builders/update-content-text-style-builder.js +216 -0
- package/lib/src/metadata-builder/helpers/rte.helpers.d.ts +13 -11
- package/lib/src/metadata-builder/helpers/rte.helpers.js +73 -14
- package/lib/src/metadata-builder/metadata-executor.js +4 -0
- package/lib/src/metadata-builder/models.d.ts +2 -0
- package/lib/src/metadata-builder/models.js +2 -0
- package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +19 -0
- package/lib/src/metadata-builder/parsers/ai-toolcall-parser.js +4 -0
- package/lib/src/metadata-builder/sanitizers/rte-schema-check.d.ts +8 -7
- package/lib/src/metadata-builder/sanitizers/rte-schema-check.js +52 -21
- package/lib/src/shared/content-settings/components/GenericTextInput.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/GenericTextInput.mixin.js +10 -35
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +3 -12
- package/lib/src/shared/content-settings/components/email-field/EmailField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/tel-field/TelField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.d.ts +2 -3
- package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.js +3 -10
- package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +1 -2
- package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +1 -4
- package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/components/youtube-video-field/YoutubeVideoField.mixin.d.ts +1 -1
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +1 -1
- package/lib/src/shared/logo-versions/LogoVersions.mixin.d.ts +1 -1
- package/lib/src/shared/my-designs/MyDesigns.mixin.d.ts +1 -1
- package/lib/src/shared/my-uploads/MyMedia.mixin.d.ts +1 -1
- package/lib/src/shared/my-uploads/MyUploads.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -1
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +1 -1
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +1 -1
- package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +1 -1
- package/lib/src/shared/template-settings/store/template-settings-store.d.ts +2 -0
- package/lib/src/shared/template-settings/store/template-settings-store.js +72 -24
- package/lib/src/shared/unsplash-library/UnsplashLibrary.mixin.d.ts +1 -1
- package/lib/src/utils/minify-brand-page-metadata.js +1 -4
- package/package.json +15 -17
- package/src/brand-page/components/contact-form/ContactForm.mixin.ts +9 -7
- package/src/brand-page/components/cookie-consent/CookieConsent.vue +1 -0
- package/src/brand-page/components/mailing-list/MailingList.mixin.ts +8 -3
- package/src/brand-page/components/navigation/navigation-carousel/NavigationCarousel.vue +5 -1
- package/src/brand-page/components/page-footer/PageFooter.mixin.ts +4 -1
- package/src/brand-page/components/page-footer/PageFooter.vue +1 -1
- package/src/brand-page/components/payment/Payment.mixin.ts +4 -3
- package/src/brand-page/components/payment/request-payment/RequestPayment.mixin.ts +8 -1
- package/src/brand-page/components/payment/request-payment/RequestPayment.vue +1 -1
- package/src/brand-page/components/save-contact/SaveContactWidget.vue +2 -1
- package/src/brand-page/components/shop/Shop.vue +6 -3
- package/src/brand-page/components/social-links/SocialLinks.vue +5 -2
- package/src/brand-page/components/text-wrapper/TextWrapper.vue +6 -17
- package/src/brand-page/composables/consent.composable.ts +18 -4
- package/src/brand-page/models/brand-page-context.model.ts +7 -0
- package/src/brand-page/models/index.ts +26 -35
- package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +3 -3
- package/src/brand-page/utils/context.util.test.ts +43 -0
- package/src/brand-page/utils/context.util.ts +10 -0
- package/src/brand-page/utils/migration.util.ts +0 -12
- package/src/brand-page/utils/style.util.test.ts +0 -51
- package/src/brand-page/utils/text.util.ts +4 -83
- package/src/brand-page/utils/vcard.util.ts +4 -6
- package/src/brand-page/utils/view-model.util.ts +26 -94
- package/src/brand-page/view-models.ts +2 -3
- package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +4 -5
- package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.test.ts +135 -0
- package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +62 -21
- package/src/brand-page-maker/composables/ai-chat/useAiMetadataBuilder.ts +1 -0
- package/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.ts +10 -6
- package/src/brand-page-maker/composables/rich-text-editor/extensions/FontSize.ts +73 -0
- package/src/brand-page-maker/composables/rich-text-editor/extensions/LineHeight.ts +85 -0
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +111 -27
- package/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.ts +9 -0
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +11 -3
- package/src/brand-page-maker/stores/ui/ui-store.ts +1 -1
- package/src/brand-page-maker/utils/index.ts +0 -2
- package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +3 -37
- package/src/brand-page-maker/utils/rich-text-editor.util.ts +11 -66
- package/src/brand-page-maker/validators/field.validator.ts +2 -10
- package/src/clients/models.ts +3 -0
- package/src/lib.ts +1 -9
- package/src/metadata-builder/ai-metadata-executor.ts +26 -0
- package/src/metadata-builder/builders/section-builders/about-section-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/banner-section-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/booking-section-builder.ts +5 -2
- package/src/metadata-builder/builders/section-builders/contact-form-builder.ts +4 -3
- package/src/metadata-builder/builders/section-builders/images-section-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/mailing-list-builder.ts +2 -1
- package/src/metadata-builder/builders/section-builders/mailing-list-section-builder.ts +2 -1
- package/src/metadata-builder/builders/section-builders/profile-section-builder.ts +6 -3
- package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +3 -2
- package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +2 -1
- package/src/metadata-builder/builders/section-builders/text-section-builder.ts +13 -19
- package/src/metadata-builder/builders/update-content-text-builder.ts +148 -0
- package/src/metadata-builder/builders/update-content-text-style-builder.ts +352 -0
- package/src/metadata-builder/helpers/rte.helpers.ts +101 -15
- package/src/metadata-builder/metadata-executor.ts +5 -0
- package/src/metadata-builder/models.ts +3 -0
- package/src/metadata-builder/parsers/ai-toolcall-parser.ts +27 -0
- package/src/metadata-builder/sanitizers/rte-schema-check.ts +53 -24
- package/src/shared/content-settings/components/GenericTextInput.mixin.ts +11 -42
- package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +3 -16
- package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.ts +4 -13
- package/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.vue +4 -6
- package/src/shared/content-settings/components/text-image-field/TextImageField.vue +3 -6
- package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +1 -6
- package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +1 -1
- package/src/shared/template-settings/store/template-settings-store.ts +93 -27
- package/src/utils/minify-brand-page-metadata.ts +1 -4
- package/lib/src/brand-page/utils/migration/migration-20.d.ts +0 -2
- package/lib/src/brand-page/utils/migration/migration-20.js +0 -66
- package/lib/src/brand-page-maker/__fixtures__/complex-rte.fixture.d.ts +0 -22
- package/lib/src/brand-page-maker/__fixtures__/complex-rte.fixture.js +0 -22
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.d.ts +0 -14
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.js +0 -39
- package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.d.ts +0 -28
- package/lib/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.js +0 -117
- package/lib/src/brand-page-maker/utils/rte-render.util.d.ts +0 -63
- package/lib/src/brand-page-maker/utils/rte-render.util.js +0 -95
- package/lib/src/brand-page-maker/utils/rte-sanitize.util.d.ts +0 -6
- package/lib/src/brand-page-maker/utils/rte-sanitize.util.js +0 -156
- package/src/brand-page/utils/migration/migration-20.server.test.ts +0 -125
- package/src/brand-page/utils/migration/migration-20.test.ts +0 -72
- package/src/brand-page/utils/migration/migration-20.ts +0 -87
- package/src/brand-page/utils/text.util.test.ts +0 -106
- package/src/brand-page/utils/view-model.pageid-rte.test.ts +0 -104
- package/src/brand-page-maker/__fixtures__/complex-rte.fixture.ts +0 -23
- package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.test.ts +0 -52
- package/src/brand-page-maker/composables/rich-text-editor/extensions/FontFamily.ts +0 -42
- package/src/brand-page-maker/composables/rich-text-editor/getRteExtensions.ts +0 -162
- package/src/brand-page-maker/utils/__snapshots__/rte-render-parity.test.ts.snap +0 -202
- package/src/brand-page-maker/utils/rte-features.test.ts +0 -378
- package/src/brand-page-maker/utils/rte-render-parity.test.ts +0 -164
- package/src/brand-page-maker/utils/rte-render.util.ts +0 -165
- package/src/brand-page-maker/utils/rte-sanitize-json.test.ts +0 -172
- package/src/brand-page-maker/utils/rte-sanitize.util.ts +0 -192
- package/src/brand-page-maker/validators/field.validator.test.ts +0 -55
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isURL, isEmail, isTel } from '@utils/validator.util';
|
|
2
2
|
import type { ItemFieldType, Validator } from '@brand-page-maker/models';
|
|
3
|
-
import { YOUTUBE_URL_RE
|
|
3
|
+
import { YOUTUBE_URL_RE } from '@brand-page-maker/utils';
|
|
4
4
|
import { validatorTr } from '@src/composables/useTranslate';
|
|
5
5
|
|
|
6
6
|
const addressValueValidator: Validator = {
|
|
@@ -76,15 +76,7 @@ export const dummyValidator: Validator = {
|
|
|
76
76
|
|
|
77
77
|
const nonEmptyStringValidator: Validator = {
|
|
78
78
|
validate: (name, value: any) => {
|
|
79
|
-
|
|
80
|
-
// An RTE field's stored value used to be inline HTML — an empty editor was
|
|
81
|
-
// "<p></p>", a NON-empty string, so the required check always passed for RTE
|
|
82
|
-
// fields (it only ever failed for genuinely empty PLAIN inputs). Now RTE
|
|
83
|
-
// fields are Tiptap JSON docs; treat any doc as "present" so behaviour
|
|
84
|
-
// stays identical. A plain string is still required to be non-empty.
|
|
85
|
-
const isValid = isTiptapDocument(value)
|
|
86
|
-
? true
|
|
87
|
-
: typeof value === 'string' && value.length > 0;
|
|
79
|
+
const isValid = typeof value === 'string' && value.length > 0;
|
|
88
80
|
|
|
89
81
|
return {
|
|
90
82
|
isValid,
|
package/src/clients/models.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { UserPersonalisationContent } from '@brand-page/models';
|
|
2
|
+
|
|
1
3
|
export interface Paginated<T> {
|
|
2
4
|
paginatedItems: T[];
|
|
3
5
|
page: number;
|
|
@@ -5,6 +7,7 @@ export interface Paginated<T> {
|
|
|
5
7
|
pageCount: number;
|
|
6
8
|
totalResultCount: number;
|
|
7
9
|
abTestValuesToBePushed?: Record<string, string>;
|
|
10
|
+
searchPersonalisation?: UserPersonalisationContent[];
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
export interface DesignTemplate {
|
package/src/lib.ts
CHANGED
|
@@ -62,6 +62,7 @@ export {
|
|
|
62
62
|
import LogoRender from './brand-page/components/logo/LogoRender.vue';
|
|
63
63
|
export { LogoRender };
|
|
64
64
|
export { default as Page } from './brand-page/components/page/Page.vue';
|
|
65
|
+
export { Loader } from '@designcrowd/fe-shared-lib';
|
|
65
66
|
|
|
66
67
|
export { default as CookieConsent } from './brand-page/components/cookie-consent/CookieConsent.vue';
|
|
67
68
|
export { default as SensitiveContentModal } from './brand-page/components/sensitive-content/SensitiveContentModal.vue';
|
|
@@ -85,15 +86,6 @@ export {
|
|
|
85
86
|
recalculateHeaderLogoSizes,
|
|
86
87
|
} from './brand-page/utils/logo.util';
|
|
87
88
|
export { sanitizeRTEHtml } from './brand-page-maker/utils';
|
|
88
|
-
// BP-5787: RTE JSON storage boundary helpers (render/normalise/sanitise/extract).
|
|
89
|
-
export {
|
|
90
|
-
renderRteToHtml,
|
|
91
|
-
toRteJson,
|
|
92
|
-
isTiptapDocument,
|
|
93
|
-
sanitizeRteJson,
|
|
94
|
-
getRteJsonPlainText,
|
|
95
|
-
type RichTextValue,
|
|
96
|
-
} from './brand-page-maker/utils';
|
|
97
89
|
export { getPageSlugFromPageTitle } from './brand-page-maker/utils/slug.util';
|
|
98
90
|
|
|
99
91
|
// AI-pipeline preview (longclaw per-turn snapshots): web-renderer's
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type BrandPageModel } from '../brand-page/models';
|
|
2
2
|
import type { EventTracker } from '../brand-page-maker/composables/useEventTracker';
|
|
3
|
+
import { buildUpdateTextRequest } from './builders/update-content-text-builder';
|
|
4
|
+
import { buildUpdateTextStyleRequest } from './builders/update-content-text-style-builder';
|
|
3
5
|
import type { UndoHandler } from './builders/undo-builder';
|
|
4
6
|
import type { Logger } from './logger';
|
|
5
7
|
import { MetadataExecutor } from './metadata-executor';
|
|
@@ -13,6 +15,8 @@ import {
|
|
|
13
15
|
AI_ASSISTANT_TOOL_NAMES,
|
|
14
16
|
SECTION_TOOL_MAP,
|
|
15
17
|
type ParsedToolCall,
|
|
18
|
+
type UpdateStyleToolArguments,
|
|
19
|
+
type UpdateTextToolArguments,
|
|
16
20
|
type DeleteSectionArguments,
|
|
17
21
|
type MoveSectionArguments,
|
|
18
22
|
type AddPageArguments,
|
|
@@ -33,6 +37,7 @@ export const executeToolCallsAsync = async (
|
|
|
33
37
|
toolcalls: ParsedToolCall[],
|
|
34
38
|
options: {
|
|
35
39
|
logger?: Logger;
|
|
40
|
+
maxCharacters?: number;
|
|
36
41
|
/**
|
|
37
42
|
* Callback invoked by the UndoBuilder at execution time to resolve the
|
|
38
43
|
* pre-prompt snapshot to restore to. The library is agnostic about where
|
|
@@ -57,6 +62,27 @@ export const executeToolCallsAsync = async (
|
|
|
57
62
|
const requests: MetadataBuilderRequest[] = toolcalls
|
|
58
63
|
.map((toolcall): MetadataBuilderRequest | null => {
|
|
59
64
|
switch (toolcall.function) {
|
|
65
|
+
case AI_ASSISTANT_TOOL_NAMES.UPDATE_TEXT: {
|
|
66
|
+
const arg = toolcall.arguments as unknown as UpdateTextToolArguments;
|
|
67
|
+
|
|
68
|
+
return buildUpdateTextRequest(toolcall.toolId, {
|
|
69
|
+
contentId: arg.contentId,
|
|
70
|
+
fieldName: arg.fieldName,
|
|
71
|
+
newText: arg.metadata.text,
|
|
72
|
+
maxCharacters: options.maxCharacters,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
case AI_ASSISTANT_TOOL_NAMES.UPDATE_STYLE: {
|
|
77
|
+
const arg = toolcall.arguments as unknown as UpdateStyleToolArguments;
|
|
78
|
+
|
|
79
|
+
return buildUpdateTextStyleRequest(toolcall.toolId, {
|
|
80
|
+
contentId: arg.contentId,
|
|
81
|
+
fieldName: arg.fieldName,
|
|
82
|
+
newStyles: arg.metadata.style,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
60
86
|
case AI_ASSISTANT_TOOL_NAMES.DELETE_SECTION: {
|
|
61
87
|
const arg = toolcall.arguments as unknown as DeleteSectionArguments;
|
|
62
88
|
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
BrandPageModel,
|
|
4
4
|
TextStyleDeclaration,
|
|
5
5
|
} from '../../../brand-page/models';
|
|
6
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
6
7
|
import type { BuilderResult } from '../../models';
|
|
7
8
|
import {
|
|
8
9
|
isTiptapDocument,
|
|
@@ -53,7 +54,7 @@ export class AboutSectionBuilder extends BaseSectionBuilder<AboutSectionContent>
|
|
|
53
54
|
|
|
54
55
|
if (aboutArgs.title !== undefined) {
|
|
55
56
|
if (isTiptapDocument(aboutArgs.title)) {
|
|
56
|
-
resolved.content.title = aboutArgs.title;
|
|
57
|
+
resolved.content.title = tiptapJsonToHtml(aboutArgs.title);
|
|
57
58
|
resolved.content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
58
59
|
resolved.content.titleStyle,
|
|
59
60
|
textStyleOptions,
|
|
@@ -65,7 +66,7 @@ export class AboutSectionBuilder extends BaseSectionBuilder<AboutSectionContent>
|
|
|
65
66
|
|
|
66
67
|
if (aboutArgs.paragraph !== undefined) {
|
|
67
68
|
if (isTiptapDocument(aboutArgs.paragraph)) {
|
|
68
|
-
resolved.content.paragraph = aboutArgs.paragraph;
|
|
69
|
+
resolved.content.paragraph = tiptapJsonToHtml(aboutArgs.paragraph);
|
|
69
70
|
resolved.content.paragraphStyle = resolveGlobalPresetIntoStyle(
|
|
70
71
|
resolved.content.paragraphStyle,
|
|
71
72
|
textStyleOptions,
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
BrandPageModel,
|
|
4
4
|
TextStyleDeclaration,
|
|
5
5
|
} from '../../../brand-page/models';
|
|
6
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
6
7
|
import type { BuilderResult } from '../../models';
|
|
7
8
|
import {
|
|
8
9
|
isTiptapDocument,
|
|
@@ -90,7 +91,7 @@ export class BannerSectionBuilder extends BaseSectionBuilder<BannerSectionConten
|
|
|
90
91
|
|
|
91
92
|
if (bannerArgs.title !== undefined) {
|
|
92
93
|
if (isTiptapDocument(bannerArgs.title)) {
|
|
93
|
-
resolved.content.title = bannerArgs.title;
|
|
94
|
+
resolved.content.title = tiptapJsonToHtml(bannerArgs.title);
|
|
94
95
|
resolved.content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
95
96
|
resolved.content.titleStyle,
|
|
96
97
|
textStyleOptions,
|
|
@@ -102,7 +103,7 @@ export class BannerSectionBuilder extends BaseSectionBuilder<BannerSectionConten
|
|
|
102
103
|
|
|
103
104
|
if (bannerArgs.description !== undefined) {
|
|
104
105
|
if (isTiptapDocument(bannerArgs.description)) {
|
|
105
|
-
resolved.content.description = bannerArgs.description;
|
|
106
|
+
resolved.content.description = tiptapJsonToHtml(bannerArgs.description);
|
|
106
107
|
resolved.content.descriptionStyle = resolveGlobalPresetIntoStyle(
|
|
107
108
|
resolved.content.descriptionStyle,
|
|
108
109
|
textStyleOptions,
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
BrandPageModel,
|
|
4
4
|
TextStyleDeclaration,
|
|
5
5
|
} from '../../../brand-page/models';
|
|
6
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
6
7
|
import type { BuilderResult } from '../../models';
|
|
7
8
|
import {
|
|
8
9
|
isTiptapDocument,
|
|
@@ -50,7 +51,7 @@ export class BookingSectionBuilder extends BaseSectionBuilder<BookingSectionCont
|
|
|
50
51
|
|
|
51
52
|
if (bookingArgs.title !== undefined) {
|
|
52
53
|
if (isTiptapDocument(bookingArgs.title)) {
|
|
53
|
-
resolved.content.title = bookingArgs.title;
|
|
54
|
+
resolved.content.title = tiptapJsonToHtml(bookingArgs.title);
|
|
54
55
|
resolved.content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
55
56
|
resolved.content.titleStyle,
|
|
56
57
|
textStyleOptions,
|
|
@@ -62,7 +63,9 @@ export class BookingSectionBuilder extends BaseSectionBuilder<BookingSectionCont
|
|
|
62
63
|
|
|
63
64
|
if (bookingArgs.description !== undefined) {
|
|
64
65
|
if (isTiptapDocument(bookingArgs.description)) {
|
|
65
|
-
resolved.content.description =
|
|
66
|
+
resolved.content.description = tiptapJsonToHtml(
|
|
67
|
+
bookingArgs.description,
|
|
68
|
+
);
|
|
66
69
|
resolved.content.descriptionStyle = resolveGlobalPresetIntoStyle(
|
|
67
70
|
resolved.content.descriptionStyle,
|
|
68
71
|
textStyleOptions,
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
BrandPageModel,
|
|
4
4
|
TextStyleDeclaration,
|
|
5
5
|
} from '../../../brand-page/models';
|
|
6
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
6
7
|
import {
|
|
7
8
|
isTiptapDocument,
|
|
8
9
|
type ContactFormSectionArguments,
|
|
@@ -49,7 +50,7 @@ export class ContactFormBuilder extends BaseSectionBuilder<ContactFormContent> {
|
|
|
49
50
|
|
|
50
51
|
if (args.title !== undefined) {
|
|
51
52
|
if (isTiptapDocument(args.title)) {
|
|
52
|
-
content.title = args.title;
|
|
53
|
+
content.title = tiptapJsonToHtml(args.title);
|
|
53
54
|
content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
54
55
|
content.titleStyle,
|
|
55
56
|
textStyleOptions,
|
|
@@ -61,7 +62,7 @@ export class ContactFormBuilder extends BaseSectionBuilder<ContactFormContent> {
|
|
|
61
62
|
|
|
62
63
|
if (args.description !== undefined) {
|
|
63
64
|
if (isTiptapDocument(args.description)) {
|
|
64
|
-
content.description = args.description;
|
|
65
|
+
content.description = tiptapJsonToHtml(args.description);
|
|
65
66
|
content.descriptionStyle = resolveGlobalPresetIntoStyle(
|
|
66
67
|
content.descriptionStyle,
|
|
67
68
|
textStyleOptions,
|
|
@@ -73,7 +74,7 @@ export class ContactFormBuilder extends BaseSectionBuilder<ContactFormContent> {
|
|
|
73
74
|
|
|
74
75
|
if (args.success_message !== undefined) {
|
|
75
76
|
if (isTiptapDocument(args.success_message)) {
|
|
76
|
-
content.successMessage = args.success_message;
|
|
77
|
+
content.successMessage = tiptapJsonToHtml(args.success_message);
|
|
77
78
|
content.successMessageStyle = resolveGlobalPresetIntoStyle(
|
|
78
79
|
content.successMessageStyle,
|
|
79
80
|
textStyleOptions,
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
BrandPageModel,
|
|
4
4
|
TextStyleDeclaration,
|
|
5
5
|
} from '../../../brand-page/models';
|
|
6
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
6
7
|
import type { BuilderResult } from '../../models';
|
|
7
8
|
import {
|
|
8
9
|
isTiptapDocument,
|
|
@@ -141,7 +142,7 @@ export class ImagesSectionBuilder extends BaseSectionBuilder<ImagesSectionConten
|
|
|
141
142
|
|
|
142
143
|
if (args.title !== undefined) {
|
|
143
144
|
if (isTiptapDocument(args.title)) {
|
|
144
|
-
content.title = args.title;
|
|
145
|
+
content.title = tiptapJsonToHtml(args.title);
|
|
145
146
|
content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
146
147
|
content.titleStyle,
|
|
147
148
|
textStyleOptions,
|
|
@@ -153,7 +154,7 @@ export class ImagesSectionBuilder extends BaseSectionBuilder<ImagesSectionConten
|
|
|
153
154
|
|
|
154
155
|
if (args.description !== undefined) {
|
|
155
156
|
if (isTiptapDocument(args.description)) {
|
|
156
|
-
content.description = args.description;
|
|
157
|
+
content.description = tiptapJsonToHtml(args.description);
|
|
157
158
|
content.descriptionStyle = resolveGlobalPresetIntoStyle(
|
|
158
159
|
content.descriptionStyle,
|
|
159
160
|
textStyleOptions,
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
MailingListContent,
|
|
5
5
|
TextStyleDeclaration,
|
|
6
6
|
} from '../../../brand-page/models';
|
|
7
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
7
8
|
import {
|
|
8
9
|
isTiptapDocument,
|
|
9
10
|
type MailingListSectionArguments,
|
|
@@ -49,7 +50,7 @@ export class MailingListBuilder extends BaseSectionBuilder<MailingListContent> {
|
|
|
49
50
|
|
|
50
51
|
if (mailingListArgs.title !== undefined) {
|
|
51
52
|
if (isTiptapDocument(mailingListArgs.title)) {
|
|
52
|
-
content.title = mailingListArgs.title;
|
|
53
|
+
content.title = tiptapJsonToHtml(mailingListArgs.title);
|
|
53
54
|
content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
54
55
|
content.titleStyle,
|
|
55
56
|
textStyleOptions,
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
BrandPageModel,
|
|
4
4
|
TextStyleDeclaration,
|
|
5
5
|
} from '../../../brand-page/models';
|
|
6
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
6
7
|
import type { BuilderResult } from '../../models';
|
|
7
8
|
import {
|
|
8
9
|
isTiptapDocument,
|
|
@@ -47,7 +48,7 @@ export class MailingListSectionBuilder extends BaseSectionBuilder<MailingListCon
|
|
|
47
48
|
|
|
48
49
|
if (mailingListArgs.title !== undefined) {
|
|
49
50
|
if (isTiptapDocument(mailingListArgs.title)) {
|
|
50
|
-
resolved.content.title = mailingListArgs.title;
|
|
51
|
+
resolved.content.title = tiptapJsonToHtml(mailingListArgs.title);
|
|
51
52
|
resolved.content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
52
53
|
resolved.content.titleStyle,
|
|
53
54
|
textStyleOptions,
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
BrandPageModel,
|
|
4
4
|
TextStyleDeclaration,
|
|
5
5
|
} from '../../../brand-page/models';
|
|
6
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
6
7
|
import type { BuilderResult } from '../../models';
|
|
7
8
|
import {
|
|
8
9
|
isTiptapDocument,
|
|
@@ -40,7 +41,7 @@ export class ProfileSectionBuilder extends BaseSectionBuilder<ProfileContent> {
|
|
|
40
41
|
|
|
41
42
|
if (profileArgs.name !== undefined) {
|
|
42
43
|
if (isTiptapDocument(profileArgs.name)) {
|
|
43
|
-
resolved.content.name = profileArgs.name;
|
|
44
|
+
resolved.content.name = tiptapJsonToHtml(profileArgs.name);
|
|
44
45
|
resolved.content.nameStyle = resolveGlobalPresetIntoStyle(
|
|
45
46
|
resolved.content.nameStyle,
|
|
46
47
|
textStyleOptions,
|
|
@@ -52,7 +53,7 @@ export class ProfileSectionBuilder extends BaseSectionBuilder<ProfileContent> {
|
|
|
52
53
|
|
|
53
54
|
if (profileArgs.title !== undefined) {
|
|
54
55
|
if (isTiptapDocument(profileArgs.title)) {
|
|
55
|
-
resolved.content.title = profileArgs.title;
|
|
56
|
+
resolved.content.title = tiptapJsonToHtml(profileArgs.title);
|
|
56
57
|
resolved.content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
57
58
|
resolved.content.titleStyle,
|
|
58
59
|
textStyleOptions,
|
|
@@ -64,7 +65,9 @@ export class ProfileSectionBuilder extends BaseSectionBuilder<ProfileContent> {
|
|
|
64
65
|
|
|
65
66
|
if (profileArgs.description !== undefined) {
|
|
66
67
|
if (isTiptapDocument(profileArgs.description)) {
|
|
67
|
-
resolved.content.description =
|
|
68
|
+
resolved.content.description = tiptapJsonToHtml(
|
|
69
|
+
profileArgs.description,
|
|
70
|
+
);
|
|
68
71
|
resolved.content.descriptionStyle = resolveGlobalPresetIntoStyle(
|
|
69
72
|
resolved.content.descriptionStyle,
|
|
70
73
|
textStyleOptions,
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
TextShapeItem,
|
|
6
6
|
TextStyleDeclaration,
|
|
7
7
|
} from '../../../brand-page/models';
|
|
8
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
8
9
|
import type { BuilderResult } from '../../models';
|
|
9
10
|
import {
|
|
10
11
|
isTiptapDocument,
|
|
@@ -194,7 +195,7 @@ export class ShapesSectionBuilder extends BaseSectionBuilder<ShapesSectionConten
|
|
|
194
195
|
|
|
195
196
|
if (args.title !== undefined) {
|
|
196
197
|
if (isTiptapDocument(args.title)) {
|
|
197
|
-
content.title = args.title;
|
|
198
|
+
content.title = tiptapJsonToHtml(args.title);
|
|
198
199
|
content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
199
200
|
content.titleStyle,
|
|
200
201
|
textStyleOptions,
|
|
@@ -206,7 +207,7 @@ export class ShapesSectionBuilder extends BaseSectionBuilder<ShapesSectionConten
|
|
|
206
207
|
|
|
207
208
|
if (args.description !== undefined) {
|
|
208
209
|
if (isTiptapDocument(args.description)) {
|
|
209
|
-
content.description = args.description;
|
|
210
|
+
content.description = tiptapJsonToHtml(args.description);
|
|
210
211
|
content.descriptionStyle = resolveGlobalPresetIntoStyle(
|
|
211
212
|
content.descriptionStyle,
|
|
212
213
|
textStyleOptions,
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
BrandPageModel,
|
|
5
5
|
TextStyleDeclaration,
|
|
6
6
|
} from '../../../brand-page/models';
|
|
7
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
7
8
|
import {
|
|
8
9
|
isTiptapDocument,
|
|
9
10
|
type TestimonialItem,
|
|
@@ -172,7 +173,7 @@ export class TestimonialSectionBuilder extends BaseSectionBuilder<TestimonialSec
|
|
|
172
173
|
|
|
173
174
|
if (args.title !== undefined) {
|
|
174
175
|
if (isTiptapDocument(args.title)) {
|
|
175
|
-
content.title = args.title;
|
|
176
|
+
content.title = tiptapJsonToHtml(args.title);
|
|
176
177
|
content.titleStyle = resolveGlobalPresetIntoStyle(
|
|
177
178
|
content.titleStyle,
|
|
178
179
|
textStyleOptions,
|
|
@@ -4,9 +4,9 @@ import type {
|
|
|
4
4
|
TextItem,
|
|
5
5
|
TextStyleDeclaration,
|
|
6
6
|
BrandPageModel,
|
|
7
|
-
RichTextValue,
|
|
8
7
|
} from '../../../brand-page/models';
|
|
9
8
|
import type { TextStyleOptions } from '../../../brand-page/models/styles.model';
|
|
9
|
+
import { tiptapJsonToHtml } from '../../helpers/rte.helpers';
|
|
10
10
|
import {
|
|
11
11
|
isTiptapDocument,
|
|
12
12
|
type TextSectionArguments,
|
|
@@ -26,18 +26,12 @@ import {
|
|
|
26
26
|
repositionItemByAnchor,
|
|
27
27
|
} from '../item-id-utils';
|
|
28
28
|
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* text-style preset resolution for rich content.
|
|
34
|
-
*/
|
|
35
|
-
const resolveText = (
|
|
36
|
-
value: unknown,
|
|
37
|
-
): { value: RichTextValue; wasTiptap: boolean } => {
|
|
38
|
-
if (isTiptapDocument(value)) return { value, wasTiptap: true };
|
|
29
|
+
/** Resolve a RichTextField (string or TiptapDocument) to a plain HTML string. */
|
|
30
|
+
const resolveText = (value: unknown): { html: string; wasTiptap: boolean } => {
|
|
31
|
+
if (isTiptapDocument(value))
|
|
32
|
+
return { html: tiptapJsonToHtml(value), wasTiptap: true };
|
|
39
33
|
|
|
40
|
-
return {
|
|
34
|
+
return { html: typeof value === 'string' ? value : '', wasTiptap: false };
|
|
41
35
|
};
|
|
42
36
|
|
|
43
37
|
const clearTextStyleTypeIfTiptap = (
|
|
@@ -61,11 +55,11 @@ const createTextItem = (
|
|
|
61
55
|
item.text_style ? { ...baseStyle, ...item.text_style } : { ...baseStyle }
|
|
62
56
|
) as TextStyleDeclaration;
|
|
63
57
|
|
|
64
|
-
const {
|
|
58
|
+
const { html, wasTiptap } = resolveText(item.text);
|
|
65
59
|
|
|
66
60
|
return {
|
|
67
61
|
id: item.item_id || generateItemId(),
|
|
68
|
-
text:
|
|
62
|
+
text: html,
|
|
69
63
|
textStyle: clearTextStyleTypeIfTiptap(
|
|
70
64
|
textStyle,
|
|
71
65
|
wasTiptap,
|
|
@@ -117,9 +111,9 @@ const mergeTextItems = (
|
|
|
117
111
|
if (!existing) continue;
|
|
118
112
|
|
|
119
113
|
if (item.text !== undefined) {
|
|
120
|
-
const {
|
|
114
|
+
const { html, wasTiptap } = resolveText(item.text);
|
|
121
115
|
|
|
122
|
-
existing.text =
|
|
116
|
+
existing.text = html;
|
|
123
117
|
existing.textStyle = clearTextStyleTypeIfTiptap(
|
|
124
118
|
existing.textStyle || {},
|
|
125
119
|
wasTiptap,
|
|
@@ -166,12 +160,12 @@ const applySingleTextField = (
|
|
|
166
160
|
textStyleOptions: TextStyleOptions | undefined,
|
|
167
161
|
): void => {
|
|
168
162
|
if (args.text !== undefined) {
|
|
169
|
-
const {
|
|
163
|
+
const { html, wasTiptap } = resolveText(args.text);
|
|
170
164
|
|
|
171
165
|
if (Array.isArray(content.textItems) && content.textItems.length > 0) {
|
|
172
166
|
content.textItems[0] = {
|
|
173
167
|
...content.textItems[0],
|
|
174
|
-
text:
|
|
168
|
+
text: html,
|
|
175
169
|
textStyle: clearTextStyleTypeIfTiptap(
|
|
176
170
|
content.textItems[0].textStyle || {},
|
|
177
171
|
wasTiptap,
|
|
@@ -182,7 +176,7 @@ const applySingleTextField = (
|
|
|
182
176
|
content.textItems = [
|
|
183
177
|
{
|
|
184
178
|
id: generateItemId(),
|
|
185
|
-
text:
|
|
179
|
+
text: html,
|
|
186
180
|
textStyle: clearTextStyleTypeIfTiptap(
|
|
187
181
|
{ ...(content.textStyle || {}) },
|
|
188
182
|
wasTiptap,
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { type BrandPageModel } from '../../brand-page/models';
|
|
2
|
+
import type { Logger } from '../logger';
|
|
3
|
+
import {
|
|
4
|
+
BaseMetadataBuilder,
|
|
5
|
+
BUILDER_TYPES,
|
|
6
|
+
type BuilderResult,
|
|
7
|
+
type MetadataBuilderRequest,
|
|
8
|
+
} from '../models';
|
|
9
|
+
import { hasRTEContent, replaceTextInRTE } from '../../brand-page-maker/utils';
|
|
10
|
+
|
|
11
|
+
export interface UpdateTextPayload {
|
|
12
|
+
contentId: string;
|
|
13
|
+
fieldName: string;
|
|
14
|
+
newText: string;
|
|
15
|
+
maxCharacters?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const buildUpdateTextRequest = (
|
|
19
|
+
id: string,
|
|
20
|
+
payload: UpdateTextPayload,
|
|
21
|
+
): MetadataBuilderRequest<UpdateTextPayload> => {
|
|
22
|
+
return {
|
|
23
|
+
id,
|
|
24
|
+
type: BUILDER_TYPES.UPDATE_CONTENT_TEXT,
|
|
25
|
+
payload,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const updateTextField = (target: any, fieldName: string, newText: string) => {
|
|
30
|
+
// Check if this is an array item path like "textItems.0.text"
|
|
31
|
+
const match = fieldName.match(/^(\w+)\.(\d+)\.(\w+)$/);
|
|
32
|
+
|
|
33
|
+
if (match) {
|
|
34
|
+
const [, arrayName, index, property] = match;
|
|
35
|
+
const array = target[arrayName];
|
|
36
|
+
|
|
37
|
+
if (Array.isArray(array) && array[+index]) {
|
|
38
|
+
const existingText = array[+index][property];
|
|
39
|
+
const updatedValue =
|
|
40
|
+
existingText &&
|
|
41
|
+
typeof existingText === 'string' &&
|
|
42
|
+
hasRTEContent(existingText)
|
|
43
|
+
? replaceTextInRTE(existingText, newText)
|
|
44
|
+
: newText;
|
|
45
|
+
|
|
46
|
+
// Create a new array with the updated item to trigger reactivity
|
|
47
|
+
const newArray = [...array];
|
|
48
|
+
|
|
49
|
+
newArray[+index] = {
|
|
50
|
+
...newArray[+index],
|
|
51
|
+
[property]: updatedValue,
|
|
52
|
+
};
|
|
53
|
+
target[arrayName] = newArray;
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
// Simple field
|
|
57
|
+
const existingText = target[fieldName];
|
|
58
|
+
|
|
59
|
+
if (
|
|
60
|
+
existingText &&
|
|
61
|
+
typeof existingText === 'string' &&
|
|
62
|
+
hasRTEContent(existingText)
|
|
63
|
+
) {
|
|
64
|
+
target[fieldName] = replaceTextInRTE(existingText, newText);
|
|
65
|
+
} else {
|
|
66
|
+
target[fieldName] = newText;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export class UpdateContentTextBuilder extends BaseMetadataBuilder<UpdateTextPayload> {
|
|
72
|
+
constructor(
|
|
73
|
+
request: MetadataBuilderRequest<UpdateTextPayload>,
|
|
74
|
+
logger?: Logger,
|
|
75
|
+
) {
|
|
76
|
+
super(request, logger);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
validateAsync(): Promise<{ errors: string[] }> {
|
|
80
|
+
const newText = this.request.payload?.newText ?? '';
|
|
81
|
+
|
|
82
|
+
const errors: string[] = [];
|
|
83
|
+
|
|
84
|
+
const maxChars = this.request.payload?.maxCharacters ?? 2000;
|
|
85
|
+
|
|
86
|
+
if (newText.length > maxChars) {
|
|
87
|
+
errors.push(`Text exceeds maximum allowed length of ${maxChars}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this.log({
|
|
91
|
+
message: `Validation called`,
|
|
92
|
+
errors,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return Promise.resolve({ errors: errors });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async buildAsync(model: BrandPageModel): Promise<BuilderResult> {
|
|
99
|
+
this.log(`Build called`);
|
|
100
|
+
|
|
101
|
+
const { contentId, fieldName, newText } = this.request.payload!;
|
|
102
|
+
|
|
103
|
+
const validation = await this.validateAsync();
|
|
104
|
+
|
|
105
|
+
if (validation.errors.length) {
|
|
106
|
+
return {
|
|
107
|
+
request: this.request,
|
|
108
|
+
model,
|
|
109
|
+
errors: validation.errors,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let updated = false;
|
|
114
|
+
|
|
115
|
+
for (const page of model.pages) {
|
|
116
|
+
for (const content of page.contents) {
|
|
117
|
+
// Use includes to handle potential ID format differences
|
|
118
|
+
if (content.id.includes(contentId) || contentId.includes(content.id)) {
|
|
119
|
+
this.log({
|
|
120
|
+
message: `Content found`,
|
|
121
|
+
model,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
updateTextField(content, fieldName, newText);
|
|
125
|
+
|
|
126
|
+
this.log({
|
|
127
|
+
message: `Successfully updated text content.`,
|
|
128
|
+
model,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
updated = true;
|
|
132
|
+
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
request: this.request,
|
|
140
|
+
model,
|
|
141
|
+
errors: updated
|
|
142
|
+
? undefined
|
|
143
|
+
: [
|
|
144
|
+
`Could not update the text because content with ID "${contentId}" not found.`,
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|