@useinsider/guido 3.19.0-beta.cac604e → 3.19.0-beta.cd75ff0
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/README.md +1 -0
- package/dist/@types/config/schemas.js +39 -37
- package/dist/components/Guido.vue.js +4 -4
- package/dist/components/Guido.vue2.js +83 -75
- package/dist/components/organisms/AutoSaveController.vue2.js +10 -8
- package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
- package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
- package/dist/components/organisms/header/EditorActions.vue.js +5 -5
- package/dist/components/organisms/header/EditorActions.vue2.js +83 -46
- package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
- package/dist/components/organisms/header/LeftSlot.vue2.js +16 -12
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +20 -0
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +50 -0
- package/dist/components/wrappers/WpDrawer.vue.js +9 -7
- package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
- package/dist/components/wrappers/WpModal.vue.js +1 -1
- package/dist/components/wrappers/WpModal.vue2.js +4 -3
- package/dist/composables/useAuthError.js +52 -0
- package/dist/composables/useAutoSave.js +44 -42
- package/dist/composables/useHtmlCompiler.js +37 -26
- package/dist/composables/useHtmlValidator.js +2 -0
- package/dist/composables/useHttp.js +64 -54
- package/dist/composables/useLegacyStrategyConversion.js +23 -19
- package/dist/composables/useSave.js +92 -45
- package/dist/composables/useSaveValidation.js +284 -0
- package/dist/composables/useSaveValidationRollout.js +20 -0
- package/dist/composables/useStripo.js +24 -20
- package/dist/composables/useToaster.js +17 -15
- package/dist/composables/validators/useCouponBlockValidator.js +24 -21
- package/dist/composables/validators/useLiquidValidator.js +15 -15
- package/dist/composables/validators/useUnsubscribeBlockValidator.js +34 -27
- package/dist/config/migrator/index.js +14 -13
- package/dist/config/migrator/recommendationPartnerMigrator.js +50 -0
- package/dist/enums/extensions/recommendationBlock.js +30 -29
- package/dist/enums/save-validation.js +4 -0
- package/dist/extensions/Blocks/Recommendation/block.js +54 -88
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +32 -51
- package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +11 -12
- package/dist/guido.css +1 -1
- package/dist/services/settingsApi.js +11 -0
- package/dist/src/@types/config/schemas.d.ts +4 -0
- package/dist/src/@types/save-validation.d.ts +19 -0
- package/dist/src/components/Guido.vue.d.ts +17 -1
- package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
- package/dist/src/components/organisms/header/EditorActions.vue.d.ts +17 -1
- package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +17 -1
- package/dist/src/components/organisms/header/RightSlot.vue.d.ts +17 -1
- package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +2 -0
- package/dist/src/components/wrappers/WpDrawer.vue.d.ts +4 -3
- package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
- package/dist/src/composables/useAuthError.d.ts +12 -0
- package/dist/src/composables/useAutoSave.d.ts +4 -1
- package/dist/src/composables/useConfig.d.ts +2 -0
- package/dist/src/composables/useHtmlValidator.d.ts +21 -0
- package/dist/src/composables/useHttp.d.ts +2 -0
- package/dist/src/composables/useSave.d.ts +6 -1
- package/dist/src/composables/useSaveValidation.d.ts +6 -0
- package/dist/src/composables/useSaveValidationRollout.d.ts +4 -0
- package/dist/src/composables/validators/useCouponBlockValidator.d.ts +3 -0
- package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +10 -0
- package/dist/src/config/migrator/index.d.ts +2 -1
- package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +1 -1
- package/dist/src/enums/save-validation.d.ts +27 -0
- package/dist/src/extensions/Blocks/Recommendation/block.d.ts +0 -6
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +0 -5
- package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +13 -7
- package/dist/src/services/settingsApi.d.ts +6 -0
- package/dist/src/stores/config.d.ts +32 -0
- package/dist/src/stores/save-validation.d.ts +22 -0
- package/dist/src/stores/setup-settings.d.ts +4 -0
- package/dist/src/utils/templatePreparation.d.ts +30 -0
- package/dist/stores/config.js +84 -67
- package/dist/stores/save-validation.js +30 -0
- package/dist/stores/setup-settings.js +10 -0
- package/dist/utils/templatePreparation.js +39 -36
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Empties recommendation blocks copied in from another account and stamps the
|
|
3
|
+
* current one, before the editor ever sees the template (SD-151945).
|
|
4
|
+
*
|
|
5
|
+
* Runs at load rather than on document change: the stamp makes it a one-time
|
|
6
|
+
* pass per template, the campaign-URL rule only ever applies to the loaded HTML,
|
|
7
|
+
* and Stripo takes the result as the original document, so nothing is dirtied.
|
|
8
|
+
*/
|
|
9
|
+
export interface PartnerScopeMigrationOptions {
|
|
10
|
+
partnerName: string;
|
|
11
|
+
/** `undefined` when the host does not pass the map — the unstamped check is then off. */
|
|
12
|
+
campaignUrls?: Record<string, unknown>;
|
|
13
|
+
rrsEnabled: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @param html Template HTML, already normalized by `migrateRecommendation`.
|
|
17
|
+
* @returns Migrated HTML, or the original when no block needed a reset or a stamp.
|
|
18
|
+
*/
|
|
19
|
+
export declare function migrateRecommendationPartnerScope(html: string, { partnerName, campaignUrls, rrsEnabled }: PartnerScopeMigrationOptions): string;
|
|
@@ -8,8 +8,8 @@ export declare const URLS: {
|
|
|
8
8
|
NEWSLETTER_RECOMMENDATIONS_PATH: string;
|
|
9
9
|
MIGRATE_STRATEGIES_PATH: string;
|
|
10
10
|
TEMPLATE_MIGRATE_STRATEGIES_PATH: string;
|
|
11
|
-
RECOMMENDATION_STRATEGY_CREATE_PATH: string;
|
|
12
11
|
};
|
|
12
|
+
export declare const strategyCreatePath: () => string;
|
|
13
13
|
export declare const strategyEditPath: (strategyId: string | number) => string;
|
|
14
14
|
export declare const MIGRATION_PATHS: Record<RrsMigrationTarget['scope'], string>;
|
|
15
15
|
export declare const QUERY_PARAMS: {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable discriminators for each save-validation rule site — one per rule that
|
|
3
|
+
* can produce a drawer row, kept in sync with the collector + legacy validator chains.
|
|
4
|
+
*/
|
|
5
|
+
export declare enum SaveValidationRule {
|
|
6
|
+
CouponTagModified = "coupon-tag-modified",
|
|
7
|
+
DuplicateUnsubBlock = "duplicate-unsub-block",
|
|
8
|
+
UnsubBlockMissingTemplate = "unsub-block-missing-template",
|
|
9
|
+
LiquidSyntax = "liquid-syntax",
|
|
10
|
+
InvalidLinks = "invalid-links",
|
|
11
|
+
LinkCheckInProgress = "link-check-in-progress",
|
|
12
|
+
CustomFieldScript = "custom-field-script",
|
|
13
|
+
EmptyHtml = "empty-html",
|
|
14
|
+
MismatchedBraces = "mismatched-braces",
|
|
15
|
+
InvalidDynamicTag = "invalid-dynamic-tag",
|
|
16
|
+
InvalidCustomField = "invalid-custom-field",
|
|
17
|
+
ConditionsSyntax = "conditions-syntax",
|
|
18
|
+
WrongEqualityOperator = "wrong-equality-operator",
|
|
19
|
+
MissingIfEndif = "missing-if-endif",
|
|
20
|
+
ConditionTagSpacing = "condition-tag-spacing",
|
|
21
|
+
BracesInsideIfTag = "braces-inside-if-tag",
|
|
22
|
+
RecommendationRequiredFields = "recommendation-required-fields",
|
|
23
|
+
RecommendationFilters = "recommendation-filters",
|
|
24
|
+
InvalidImageType = "invalid-image-type",
|
|
25
|
+
CheckboxUnsubGroup = "checkbox-unsub-group",
|
|
26
|
+
RadioButtonUnsubGroup = "radio-button-unsub-group"
|
|
27
|
+
}
|
|
@@ -137,12 +137,6 @@ export declare class RecommendationBlock extends Block {
|
|
|
137
137
|
* heals templates saved before this feature without dirtying current ones.
|
|
138
138
|
*/
|
|
139
139
|
private _healHidePriceAttr;
|
|
140
|
-
/**
|
|
141
|
-
* Empties a block copied in from another account: its strategy and attribute types
|
|
142
|
-
* are account-scoped and would not resolve here (SD-151945). Layout, locale and
|
|
143
|
-
* currency stay. The write stamps the current account, so the next pass is a no-op.
|
|
144
|
-
*/
|
|
145
|
-
private _resetForeignPartnerConfig;
|
|
146
140
|
/**
|
|
147
141
|
* Gets the recommendation-id from a block node
|
|
148
142
|
*/
|
|
@@ -543,11 +543,6 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
|
|
|
543
543
|
openRemoveStrategyModal(): void;
|
|
544
544
|
closeRemoveStrategyModal(): void;
|
|
545
545
|
fetchStrategies(): Promise<void>;
|
|
546
|
-
/**
|
|
547
|
-
* Drops what the store still holds for a block whose account-scoped config was just
|
|
548
|
-
* reset in the document (SD-151945), so the panel re-seeds from the emptied node.
|
|
549
|
-
*/
|
|
550
|
-
resetPartnerScopedConfig(id: number): void;
|
|
551
546
|
/**
|
|
552
547
|
* Clears what a block inherited from the id it arrived holding, so the panel fetches for it.
|
|
553
548
|
* A re-dropped saved module can keep the source's id — and its "already fetched" entry —
|
|
@@ -4,24 +4,30 @@ import type { RecommendationNodeConfig } from '../types/nodeConfig';
|
|
|
4
4
|
* string or an entry that names a strategy.
|
|
5
5
|
*/
|
|
6
6
|
export declare function isDefinedCampaignUrl(value: unknown): boolean;
|
|
7
|
-
/** Recommendation block ids present in the HTML the host loaded the editor with. */
|
|
8
|
-
export declare function loadedRecommendationIds(html: string): Set<number>;
|
|
9
7
|
export interface PartnerScopeInputs {
|
|
10
8
|
config: Pick<RecommendationNodeConfig, 'strategyId' | 'partnerName'>;
|
|
11
9
|
blockId: number;
|
|
12
10
|
partnerName: string;
|
|
13
11
|
/** `undefined` when the host does not pass the map — the unstamped check is then off. */
|
|
14
12
|
campaignUrls: Record<string, unknown> | undefined;
|
|
15
|
-
|
|
13
|
+
/** With RRS off `buildCampaignUrl` drops the block's map entry, so the map says nothing. */
|
|
14
|
+
rrsEnabled: boolean;
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
18
17
|
* Whether a block carries another account's strategy config (SD-151945).
|
|
19
18
|
*
|
|
20
19
|
* A stamped block is judged by its stamp. An unstamped one predates the stamp, so it
|
|
21
20
|
* falls back to the backend's own signal: a cross-account duplicate drops the block's
|
|
22
|
-
* strategy entry from the campaign URL map but leaves the HTML untouched. That
|
|
23
|
-
* only holds
|
|
24
|
-
*
|
|
21
|
+
* strategy entry from the campaign URL map but leaves the HTML untouched. That signal
|
|
22
|
+
* only holds while RRS is on, and only for the HTML the host loaded — which is what
|
|
23
|
+
* the caller, a load-time migrator, runs on.
|
|
25
24
|
*/
|
|
26
|
-
export declare function carriesForeignPartnerConfig({ config, blockId, partnerName, campaignUrls,
|
|
25
|
+
export declare function carriesForeignPartnerConfig({ config, blockId, partnerName, campaignUrls, rrsEnabled }: PartnerScopeInputs): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Whether an unstamped block's ownership can be decided at all. `carriesForeignPartnerConfig`
|
|
28
|
+
* answers `false` both for "clean" and for "cannot tell", and stamping on the latter would
|
|
29
|
+
* record a foreign block as this account's and silence every later check. A block with no
|
|
30
|
+
* strategy reference has nothing foreign to carry, so it is always decidable.
|
|
31
|
+
*/
|
|
32
|
+
export declare function canJudgeUnstampedBlock({ config, campaignUrls, rrsEnabled }: Pick<PartnerScopeInputs, 'config' | 'campaignUrls' | 'rrsEnabled'>): boolean;
|
|
27
33
|
export declare function withoutCustomAttributes(composition: string[]): string[];
|
|
@@ -107,6 +107,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
107
107
|
autosave: boolean;
|
|
108
108
|
allowlistEnabled: boolean;
|
|
109
109
|
linkTrackingIds: boolean;
|
|
110
|
+
allowSaveWithErrors: boolean;
|
|
110
111
|
reusableRecommendationStrategy: boolean;
|
|
111
112
|
};
|
|
112
113
|
blocks: {
|
|
@@ -251,6 +252,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
251
252
|
autosave: boolean;
|
|
252
253
|
allowlistEnabled: boolean;
|
|
253
254
|
linkTrackingIds: boolean;
|
|
255
|
+
allowSaveWithErrors: boolean;
|
|
254
256
|
reusableRecommendationStrategy: boolean;
|
|
255
257
|
};
|
|
256
258
|
blocks: {
|
|
@@ -395,6 +397,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
395
397
|
autosave: boolean;
|
|
396
398
|
allowlistEnabled: boolean;
|
|
397
399
|
linkTrackingIds: boolean;
|
|
400
|
+
allowSaveWithErrors: boolean;
|
|
398
401
|
reusableRecommendationStrategy: boolean;
|
|
399
402
|
};
|
|
400
403
|
blocks: {
|
|
@@ -539,6 +542,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
539
542
|
autosave: boolean;
|
|
540
543
|
allowlistEnabled: boolean;
|
|
541
544
|
linkTrackingIds: boolean;
|
|
545
|
+
allowSaveWithErrors: boolean;
|
|
542
546
|
reusableRecommendationStrategy: boolean;
|
|
543
547
|
};
|
|
544
548
|
blocks: {
|
|
@@ -683,6 +687,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
683
687
|
autosave: boolean;
|
|
684
688
|
allowlistEnabled: boolean;
|
|
685
689
|
linkTrackingIds: boolean;
|
|
690
|
+
allowSaveWithErrors: boolean;
|
|
686
691
|
reusableRecommendationStrategy: boolean;
|
|
687
692
|
};
|
|
688
693
|
blocks: {
|
|
@@ -827,6 +832,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
827
832
|
autosave: boolean;
|
|
828
833
|
allowlistEnabled: boolean;
|
|
829
834
|
linkTrackingIds: boolean;
|
|
835
|
+
allowSaveWithErrors: boolean;
|
|
830
836
|
reusableRecommendationStrategy: boolean;
|
|
831
837
|
};
|
|
832
838
|
blocks: {
|
|
@@ -971,6 +977,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
971
977
|
autosave: boolean;
|
|
972
978
|
allowlistEnabled: boolean;
|
|
973
979
|
linkTrackingIds: boolean;
|
|
980
|
+
allowSaveWithErrors: boolean;
|
|
974
981
|
reusableRecommendationStrategy: boolean;
|
|
975
982
|
};
|
|
976
983
|
blocks: {
|
|
@@ -1115,6 +1122,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1115
1122
|
autosave: boolean;
|
|
1116
1123
|
allowlistEnabled: boolean;
|
|
1117
1124
|
linkTrackingIds: boolean;
|
|
1125
|
+
allowSaveWithErrors: boolean;
|
|
1118
1126
|
reusableRecommendationStrategy: boolean;
|
|
1119
1127
|
};
|
|
1120
1128
|
blocks: {
|
|
@@ -1259,6 +1267,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1259
1267
|
autosave: boolean;
|
|
1260
1268
|
allowlistEnabled: boolean;
|
|
1261
1269
|
linkTrackingIds: boolean;
|
|
1270
|
+
allowSaveWithErrors: boolean;
|
|
1262
1271
|
reusableRecommendationStrategy: boolean;
|
|
1263
1272
|
};
|
|
1264
1273
|
blocks: {
|
|
@@ -1403,6 +1412,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1403
1412
|
autosave: boolean;
|
|
1404
1413
|
allowlistEnabled: boolean;
|
|
1405
1414
|
linkTrackingIds: boolean;
|
|
1415
|
+
allowSaveWithErrors: boolean;
|
|
1406
1416
|
reusableRecommendationStrategy: boolean;
|
|
1407
1417
|
};
|
|
1408
1418
|
blocks: {
|
|
@@ -1547,6 +1557,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1547
1557
|
autosave: boolean;
|
|
1548
1558
|
allowlistEnabled: boolean;
|
|
1549
1559
|
linkTrackingIds: boolean;
|
|
1560
|
+
allowSaveWithErrors: boolean;
|
|
1550
1561
|
reusableRecommendationStrategy: boolean;
|
|
1551
1562
|
};
|
|
1552
1563
|
blocks: {
|
|
@@ -1691,6 +1702,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1691
1702
|
autosave: boolean;
|
|
1692
1703
|
allowlistEnabled: boolean;
|
|
1693
1704
|
linkTrackingIds: boolean;
|
|
1705
|
+
allowSaveWithErrors: boolean;
|
|
1694
1706
|
reusableRecommendationStrategy: boolean;
|
|
1695
1707
|
};
|
|
1696
1708
|
blocks: {
|
|
@@ -1835,6 +1847,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1835
1847
|
autosave: boolean;
|
|
1836
1848
|
allowlistEnabled: boolean;
|
|
1837
1849
|
linkTrackingIds: boolean;
|
|
1850
|
+
allowSaveWithErrors: boolean;
|
|
1838
1851
|
reusableRecommendationStrategy: boolean;
|
|
1839
1852
|
};
|
|
1840
1853
|
blocks: {
|
|
@@ -1979,6 +1992,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
1979
1992
|
autosave: boolean;
|
|
1980
1993
|
allowlistEnabled: boolean;
|
|
1981
1994
|
linkTrackingIds: boolean;
|
|
1995
|
+
allowSaveWithErrors: boolean;
|
|
1982
1996
|
reusableRecommendationStrategy: boolean;
|
|
1983
1997
|
};
|
|
1984
1998
|
blocks: {
|
|
@@ -2123,6 +2137,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2123
2137
|
autosave: boolean;
|
|
2124
2138
|
allowlistEnabled: boolean;
|
|
2125
2139
|
linkTrackingIds: boolean;
|
|
2140
|
+
allowSaveWithErrors: boolean;
|
|
2126
2141
|
reusableRecommendationStrategy: boolean;
|
|
2127
2142
|
};
|
|
2128
2143
|
blocks: {
|
|
@@ -2267,6 +2282,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2267
2282
|
autosave: boolean;
|
|
2268
2283
|
allowlistEnabled: boolean;
|
|
2269
2284
|
linkTrackingIds: boolean;
|
|
2285
|
+
allowSaveWithErrors: boolean;
|
|
2270
2286
|
reusableRecommendationStrategy: boolean;
|
|
2271
2287
|
};
|
|
2272
2288
|
blocks: {
|
|
@@ -2411,6 +2427,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2411
2427
|
autosave: boolean;
|
|
2412
2428
|
allowlistEnabled: boolean;
|
|
2413
2429
|
linkTrackingIds: boolean;
|
|
2430
|
+
allowSaveWithErrors: boolean;
|
|
2414
2431
|
reusableRecommendationStrategy: boolean;
|
|
2415
2432
|
};
|
|
2416
2433
|
blocks: {
|
|
@@ -2454,6 +2471,18 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2454
2471
|
};
|
|
2455
2472
|
} | null;
|
|
2456
2473
|
} & import("pinia").PiniaCustomStateProperties<ConfigStoreState>) => number;
|
|
2474
|
+
/**
|
|
2475
|
+
* Transactional campaigns keep the hard save block. Reactive getter, so
|
|
2476
|
+
* consumers stay safe in setup where a raw config read snapshots null (SD-147945).
|
|
2477
|
+
*/
|
|
2478
|
+
isTransactional(): boolean;
|
|
2479
|
+
/**
|
|
2480
|
+
* Soft-save policy: may the editor persist a template with validation errors?
|
|
2481
|
+
* Default true (host sets features.allowSaveWithErrors=false for transactional +
|
|
2482
|
+
* unsub). Reactive getter defaulting true — reading via isFeatureEnabled would
|
|
2483
|
+
* floor to false pre-init and momentarily hide the soft-save option (SD-147430).
|
|
2484
|
+
*/
|
|
2485
|
+
allowSaveWithErrors(): boolean;
|
|
2457
2486
|
/**
|
|
2458
2487
|
* Get the username
|
|
2459
2488
|
*/
|
|
@@ -2555,6 +2584,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2555
2584
|
autosave: boolean;
|
|
2556
2585
|
allowlistEnabled: boolean;
|
|
2557
2586
|
linkTrackingIds: boolean;
|
|
2587
|
+
allowSaveWithErrors: boolean;
|
|
2558
2588
|
reusableRecommendationStrategy: boolean;
|
|
2559
2589
|
};
|
|
2560
2590
|
blocks: {
|
|
@@ -2699,6 +2729,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2699
2729
|
autosave: boolean;
|
|
2700
2730
|
allowlistEnabled: boolean;
|
|
2701
2731
|
linkTrackingIds: boolean;
|
|
2732
|
+
allowSaveWithErrors: boolean;
|
|
2702
2733
|
reusableRecommendationStrategy: boolean;
|
|
2703
2734
|
};
|
|
2704
2735
|
blocks: {
|
|
@@ -2845,6 +2876,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
|
|
|
2845
2876
|
autosave: boolean;
|
|
2846
2877
|
allowlistEnabled: boolean;
|
|
2847
2878
|
linkTrackingIds: boolean;
|
|
2879
|
+
allowSaveWithErrors: boolean;
|
|
2848
2880
|
reusableRecommendationStrategy: boolean;
|
|
2849
2881
|
};
|
|
2850
2882
|
blocks: {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SaveValidationError, SaveValidationIntent } from '@@/Types/save-validation';
|
|
2
|
+
interface SaveValidationState {
|
|
3
|
+
errors: SaveValidationError[];
|
|
4
|
+
isDrawerOpen: boolean;
|
|
5
|
+
intent: SaveValidationIntent | null;
|
|
6
|
+
}
|
|
7
|
+
export declare const useSaveValidationStore: import("pinia").StoreDefinition<"guidoSaveValidation", SaveValidationState, {
|
|
8
|
+
errorCount: (state: {
|
|
9
|
+
errors: {
|
|
10
|
+
rule: import("../enums/save-validation").SaveValidationRule;
|
|
11
|
+
message: string;
|
|
12
|
+
detail?: string | undefined;
|
|
13
|
+
type: import("../enums/toaster").ToasterTypeOptions;
|
|
14
|
+
}[];
|
|
15
|
+
isDrawerOpen: boolean;
|
|
16
|
+
intent: SaveValidationIntent | null;
|
|
17
|
+
} & import("pinia").PiniaCustomStateProperties<SaveValidationState>) => number;
|
|
18
|
+
}, {
|
|
19
|
+
open(errors: SaveValidationError[], intent: SaveValidationIntent): void;
|
|
20
|
+
close(): void;
|
|
21
|
+
}>;
|
|
22
|
+
export {};
|
|
@@ -15,6 +15,36 @@ import type { SavedTemplateDetails } from '@@/Types/stripo';
|
|
|
15
15
|
* same source), so it is reliably present regardless of how the block was added.
|
|
16
16
|
*/
|
|
17
17
|
export declare function getHtmlReferencedUnsubscribePages(html: string): number[];
|
|
18
|
+
/**
|
|
19
|
+
* Hydrates the recommendation extension store from the persisted `esd-ext-config`
|
|
20
|
+
* JSON blob on each `.recommendation-block-v2` element in the raw editor HTML.
|
|
21
|
+
*
|
|
22
|
+
* Why this runs before `compileHtml`:
|
|
23
|
+
* The HTML compiler's `prepareRecommendationBlocks` rule asks
|
|
24
|
+
* `useRecommendation.buildCampaignUrl(id)` to assemble each block's API URL
|
|
25
|
+
* from `blockStates[id].recommendationConfigs`. That Pinia entry is normally
|
|
26
|
+
* populated by `RecommendationBlockControl._syncNodeConfigToStore`, which
|
|
27
|
+
* only fires when the user *selects* the block. Saving without ever
|
|
28
|
+
* selecting a migrated block would otherwise build the URL from empty/
|
|
29
|
+
* default state and the campaign URL would not be saved.
|
|
30
|
+
*
|
|
31
|
+
* Why we read raw HTML, not compiled HTML:
|
|
32
|
+
* Stripo's `compileEmail()` strips editor-only attributes (`esd-*`) from the
|
|
33
|
+
* compiled output, so `esd-ext-config` is gone by the time the compiler
|
|
34
|
+
* pipeline sees the HTML. The raw HTML from `getTemplateData()` preserves
|
|
35
|
+
* the attribute as the migrator wrote it.
|
|
36
|
+
*
|
|
37
|
+
* Reference data pre-load:
|
|
38
|
+
* When the template has recommendation blocks, this also pre-loads the
|
|
39
|
+
* shared reference data (languages / currency list) so the save-time
|
|
40
|
+
* required-fields validator can check each block's locale and currency
|
|
41
|
+
* against the partner's real options. Best-effort — on a fetch failure the
|
|
42
|
+
* validator degrades to its empty-list guard (`requiredFields.ts`) instead
|
|
43
|
+
* of blocking the save or stranding the Save button.
|
|
44
|
+
*/
|
|
45
|
+
declare function hydrateRecommendationStoreFromRawHtml(rawHtml: string): Promise<void>;
|
|
18
46
|
export declare const useTemplatePreparation: () => {
|
|
19
47
|
prepareTemplateDetails: () => Promise<Omit<SavedTemplateDetails, "metadata">>;
|
|
48
|
+
hydrateRecommendationStore: typeof hydrateRecommendationStoreFromRawHtml;
|
|
20
49
|
};
|
|
50
|
+
export {};
|
package/dist/stores/config.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import "../@types/config/schemas.js";
|
|
1
|
+
import { MessageType as r } from "../@types/config/schemas.js";
|
|
2
2
|
import "../@types/config/defaults.js";
|
|
3
|
-
import { parseConfig as
|
|
4
|
-
import { defineStore as
|
|
5
|
-
const
|
|
3
|
+
import { parseConfig as a } from "../@types/config/validator.js";
|
|
4
|
+
import { defineStore as o } from "pinia";
|
|
5
|
+
const g = o("guido-config", {
|
|
6
6
|
state: () => ({
|
|
7
7
|
initialized: !1,
|
|
8
8
|
config: null
|
|
@@ -11,135 +11,152 @@ const s = a("guido-config", {
|
|
|
11
11
|
/**
|
|
12
12
|
* Get the identity configuration
|
|
13
13
|
*/
|
|
14
|
-
identity: (
|
|
15
|
-
var
|
|
16
|
-
return ((
|
|
14
|
+
identity: (i) => {
|
|
15
|
+
var e;
|
|
16
|
+
return ((e = i.config) == null ? void 0 : e.identity) ?? null;
|
|
17
17
|
},
|
|
18
18
|
/**
|
|
19
19
|
* Get the partner configuration
|
|
20
20
|
*/
|
|
21
|
-
partner: (
|
|
22
|
-
var
|
|
23
|
-
return ((
|
|
21
|
+
partner: (i) => {
|
|
22
|
+
var e;
|
|
23
|
+
return ((e = i.config) == null ? void 0 : e.partner) ?? null;
|
|
24
24
|
},
|
|
25
25
|
/**
|
|
26
26
|
* Get the template configuration
|
|
27
27
|
*/
|
|
28
|
-
template: (
|
|
29
|
-
var
|
|
30
|
-
return ((
|
|
28
|
+
template: (i) => {
|
|
29
|
+
var e;
|
|
30
|
+
return ((e = i.config) == null ? void 0 : e.template) ?? null;
|
|
31
31
|
},
|
|
32
32
|
/**
|
|
33
33
|
* Get the editor configuration
|
|
34
34
|
*/
|
|
35
|
-
editor: (
|
|
36
|
-
var
|
|
37
|
-
return ((
|
|
35
|
+
editor: (i) => {
|
|
36
|
+
var e;
|
|
37
|
+
return ((e = i.config) == null ? void 0 : e.editor) ?? null;
|
|
38
38
|
},
|
|
39
39
|
/**
|
|
40
40
|
* Get the UI configuration
|
|
41
41
|
*/
|
|
42
|
-
ui: (
|
|
43
|
-
var
|
|
44
|
-
return ((
|
|
42
|
+
ui: (i) => {
|
|
43
|
+
var e;
|
|
44
|
+
return ((e = i.config) == null ? void 0 : e.ui) ?? null;
|
|
45
45
|
},
|
|
46
46
|
/**
|
|
47
47
|
* Get the features configuration
|
|
48
48
|
*/
|
|
49
|
-
features: (
|
|
50
|
-
var
|
|
51
|
-
return ((
|
|
49
|
+
features: (i) => {
|
|
50
|
+
var e;
|
|
51
|
+
return ((e = i.config) == null ? void 0 : e.features) ?? null;
|
|
52
52
|
},
|
|
53
53
|
/**
|
|
54
54
|
* Get the blocks configuration
|
|
55
55
|
*/
|
|
56
|
-
blocks: (
|
|
57
|
-
var
|
|
58
|
-
return ((
|
|
56
|
+
blocks: (i) => {
|
|
57
|
+
var e;
|
|
58
|
+
return ((e = i.config) == null ? void 0 : e.blocks) ?? null;
|
|
59
59
|
},
|
|
60
60
|
/**
|
|
61
61
|
* Get the compiler configuration
|
|
62
62
|
*/
|
|
63
|
-
compiler: (
|
|
64
|
-
var
|
|
65
|
-
return ((
|
|
63
|
+
compiler: (i) => {
|
|
64
|
+
var e;
|
|
65
|
+
return ((e = i.config) == null ? void 0 : e.compiler) ?? null;
|
|
66
66
|
},
|
|
67
67
|
/**
|
|
68
68
|
* Get the callbacks configuration
|
|
69
69
|
*/
|
|
70
|
-
callbacks: (
|
|
71
|
-
var
|
|
72
|
-
return ((
|
|
70
|
+
callbacks: (i) => {
|
|
71
|
+
var e;
|
|
72
|
+
return ((e = i.config) == null ? void 0 : e.callbacks) ?? null;
|
|
73
73
|
},
|
|
74
74
|
/**
|
|
75
75
|
* Get the template ID
|
|
76
76
|
*/
|
|
77
|
-
templateId: (
|
|
78
|
-
var
|
|
79
|
-
return ((t = (
|
|
77
|
+
templateId: (i) => {
|
|
78
|
+
var e, t;
|
|
79
|
+
return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.templateId) ?? "";
|
|
80
80
|
},
|
|
81
81
|
/**
|
|
82
82
|
* Get the user ID
|
|
83
83
|
*/
|
|
84
|
-
userId: (
|
|
85
|
-
var
|
|
86
|
-
return ((t = (
|
|
84
|
+
userId: (i) => {
|
|
85
|
+
var e, t;
|
|
86
|
+
return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.userId) ?? "";
|
|
87
87
|
},
|
|
88
88
|
/**
|
|
89
89
|
* Get the variation ID
|
|
90
90
|
*/
|
|
91
|
-
variationId: (
|
|
92
|
-
var
|
|
93
|
-
return ((t = (
|
|
91
|
+
variationId: (i) => {
|
|
92
|
+
var e, t;
|
|
93
|
+
return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.variationId) ?? "";
|
|
94
94
|
},
|
|
95
95
|
/**
|
|
96
96
|
* Get the campaign ID
|
|
97
97
|
*/
|
|
98
|
-
campaignId: (
|
|
99
|
-
var
|
|
100
|
-
return ((t = (
|
|
98
|
+
campaignId: (i) => {
|
|
99
|
+
var e, t;
|
|
100
|
+
return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.campaignId) ?? "";
|
|
101
101
|
},
|
|
102
102
|
/**
|
|
103
103
|
* Get the template-library ID of the host template
|
|
104
104
|
*/
|
|
105
|
-
templateLibraryId: (
|
|
106
|
-
var
|
|
107
|
-
return ((t = (
|
|
105
|
+
templateLibraryId: (i) => {
|
|
106
|
+
var e, t;
|
|
107
|
+
return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.templateLibraryId) ?? "";
|
|
108
108
|
},
|
|
109
109
|
/**
|
|
110
110
|
* Get the partner name
|
|
111
111
|
*/
|
|
112
|
-
partnerName: (
|
|
113
|
-
var
|
|
114
|
-
return ((t = (
|
|
112
|
+
partnerName: (i) => {
|
|
113
|
+
var e, t;
|
|
114
|
+
return ((t = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : t.name) ?? "";
|
|
115
115
|
},
|
|
116
116
|
/**
|
|
117
117
|
* Get the product type
|
|
118
118
|
*/
|
|
119
|
-
productType: (
|
|
120
|
-
var
|
|
121
|
-
return ((t = (
|
|
119
|
+
productType: (i) => {
|
|
120
|
+
var e, t;
|
|
121
|
+
return ((t = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : t.productType) ?? 60;
|
|
122
122
|
},
|
|
123
123
|
/**
|
|
124
124
|
* Get the message type
|
|
125
125
|
*/
|
|
126
|
-
messageType: (
|
|
127
|
-
var
|
|
128
|
-
return ((t = (
|
|
126
|
+
messageType: (i) => {
|
|
127
|
+
var e, t;
|
|
128
|
+
return ((t = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : t.messageType) ?? 1;
|
|
129
|
+
},
|
|
130
|
+
/**
|
|
131
|
+
* Transactional campaigns keep the hard save block. Reactive getter, so
|
|
132
|
+
* consumers stay safe in setup where a raw config read snapshots null (SD-147945).
|
|
133
|
+
*/
|
|
134
|
+
isTransactional() {
|
|
135
|
+
return this.messageType === r.TRANSACTIONAL;
|
|
136
|
+
},
|
|
137
|
+
/**
|
|
138
|
+
* Soft-save policy: may the editor persist a template with validation errors?
|
|
139
|
+
* Default true (host sets features.allowSaveWithErrors=false for transactional +
|
|
140
|
+
* unsub). Reactive getter defaulting true — reading via isFeatureEnabled would
|
|
141
|
+
* floor to false pre-init and momentarily hide the soft-save option (SD-147430).
|
|
142
|
+
*/
|
|
143
|
+
allowSaveWithErrors() {
|
|
144
|
+
var i;
|
|
145
|
+
return ((i = this.features) == null ? void 0 : i.allowSaveWithErrors) ?? !0;
|
|
129
146
|
},
|
|
130
147
|
/**
|
|
131
148
|
* Get the username
|
|
132
149
|
*/
|
|
133
|
-
username: (
|
|
134
|
-
var
|
|
135
|
-
return ((t = (
|
|
150
|
+
username: (i) => {
|
|
151
|
+
var e, t;
|
|
152
|
+
return ((t = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : t.username) ?? "Guido User";
|
|
136
153
|
},
|
|
137
154
|
/**
|
|
138
155
|
* Check if header should be shown
|
|
139
156
|
*/
|
|
140
|
-
showHeader: (
|
|
141
|
-
var
|
|
142
|
-
return ((t = (
|
|
157
|
+
showHeader: (i) => {
|
|
158
|
+
var e, t;
|
|
159
|
+
return ((t = (e = i.config) == null ? void 0 : e.ui) == null ? void 0 : t.showHeader) ?? !0;
|
|
143
160
|
},
|
|
144
161
|
/**
|
|
145
162
|
* Check if a specific feature is enabled.
|
|
@@ -147,18 +164,18 @@ const s = a("guido-config", {
|
|
|
147
164
|
* flash on during loading, then disappear once config resolves.
|
|
148
165
|
*/
|
|
149
166
|
// eslint-disable-next-line @stylistic/max-len
|
|
150
|
-
isFeatureEnabled: (
|
|
167
|
+
isFeatureEnabled: (i) => (e) => {
|
|
151
168
|
var t, n;
|
|
152
|
-
return ((n = (t =
|
|
169
|
+
return ((n = (t = i.config) == null ? void 0 : t.features) == null ? void 0 : n[e]) ?? !1;
|
|
153
170
|
}
|
|
154
171
|
},
|
|
155
172
|
actions: {
|
|
156
173
|
/**
|
|
157
174
|
* Initialize the config store with validated configuration
|
|
158
175
|
*/
|
|
159
|
-
init(
|
|
160
|
-
const
|
|
161
|
-
this.config =
|
|
176
|
+
init(i) {
|
|
177
|
+
const e = a(i);
|
|
178
|
+
this.config = e, this.initialized = !0;
|
|
162
179
|
},
|
|
163
180
|
/**
|
|
164
181
|
* Reset the config store
|
|
@@ -169,5 +186,5 @@ const s = a("guido-config", {
|
|
|
169
186
|
}
|
|
170
187
|
});
|
|
171
188
|
export {
|
|
172
|
-
|
|
189
|
+
g as useConfigStore
|
|
173
190
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { defineStore as n } from "pinia";
|
|
2
|
+
function i(e) {
|
|
3
|
+
const t = /* @__PURE__ */ new Set();
|
|
4
|
+
return e.filter((r) => {
|
|
5
|
+
const s = JSON.stringify([r.rule, r.message, r.detail ?? ""]);
|
|
6
|
+
return t.has(s) ? !1 : (t.add(s), !0);
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
const o = n("guidoSaveValidation", {
|
|
10
|
+
state: () => ({
|
|
11
|
+
errors: [],
|
|
12
|
+
isDrawerOpen: !1,
|
|
13
|
+
intent: null
|
|
14
|
+
}),
|
|
15
|
+
getters: {
|
|
16
|
+
errorCount: (e) => e.errors.length
|
|
17
|
+
},
|
|
18
|
+
actions: {
|
|
19
|
+
open(e, t) {
|
|
20
|
+
this.errors = i(e), this.intent = t, this.isDrawerOpen = !0;
|
|
21
|
+
},
|
|
22
|
+
// Errors are retained so rows don't blank during the ~300ms close animation.
|
|
23
|
+
close() {
|
|
24
|
+
this.isDrawerOpen = !1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
export {
|
|
29
|
+
o as useSaveValidationStore
|
|
30
|
+
};
|