@useinsider/guido 3.17.0-beta.668ca65 → 3.17.0-beta.6cedc6c
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 +5 -5
- package/dist/components/Guido.vue.js +7 -7
- package/dist/components/Guido.vue2.js +59 -57
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +5 -5
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +31 -30
- package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue.js +17 -0
- package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +52 -0
- package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue2.js +36 -35
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +198 -135
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +1 -1
- package/dist/extensions/Blocks/Recommendation/services/configService.js +34 -16
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +47 -37
- package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +22 -0
- package/dist/guido.css +1 -1
- package/dist/services/recommendationApi.js +1 -1
- package/dist/src/components/organisms/extensions/recommendation/RemoveStrategyModal.vue.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +38 -8
- package/dist/src/extensions/Blocks/Recommendation/services/configService.d.ts +12 -1
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +26 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +31 -0
- package/dist/src/utils/genericUtil.d.ts +5 -0
- package/dist/utils/genericUtil.js +28 -27
- package/package.json +2 -2
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { getRecommendationFeedSourceMaps as
|
|
2
|
-
import { useRecommendationApi as
|
|
3
|
-
import { useConfigStore as
|
|
4
|
-
import { defineStore as
|
|
1
|
+
import { getRecommendationFeedSourceMaps as b, getOperatorOptions as G, PriceAttributes as v } from "../../../../enums/extensions/recommendationBlock.js";
|
|
2
|
+
import { useRecommendationApi as D } from "../../../../services/recommendationApi.js";
|
|
3
|
+
import { useConfigStore as P } from "../../../../stores/config.js";
|
|
4
|
+
import { defineStore as F } from "pinia";
|
|
5
5
|
import "../constants/selectors.js";
|
|
6
6
|
import { DEFAULT_MOBILE_CARDS_IN_ROW as _, DEFAULT_CARDS_IN_ROW as U } from "../constants/layout.js";
|
|
7
7
|
import { DEFAULT_NODE_CONFIG as N, EXCLUDED_ALGORITHM_IDS as L } from "../constants/defaultConfig.js";
|
|
8
|
-
import { getDefaultProducts as
|
|
9
|
-
import { generateCompleteFilterQuery as
|
|
8
|
+
import { getDefaultProducts as R } from "../templates/utils.js";
|
|
9
|
+
import { generateCompleteFilterQuery as k } from "../utils/filterUtil.js";
|
|
10
10
|
import { getPartnerRecommendationParams as x } from "../utils/partnerCustomizations.js";
|
|
11
11
|
import { sanitizeProductIds as A } from "../utils/productIds.js";
|
|
12
12
|
import { isFilterValid as B } from "../validation/filterSchema.js";
|
|
13
|
-
import { isConfigValid as
|
|
14
|
-
const
|
|
15
|
-
let f = null,
|
|
13
|
+
import { isConfigValid as M } from "../validation/requiredFields.js";
|
|
14
|
+
const u = D();
|
|
15
|
+
let f = null, h = null, g = null, S = null;
|
|
16
16
|
const p = /* @__PURE__ */ new Map();
|
|
17
17
|
function w() {
|
|
18
18
|
return {
|
|
@@ -53,12 +53,13 @@ function C() {
|
|
|
53
53
|
filterStatus: !1,
|
|
54
54
|
filterSelectionDrawerStatus: !1,
|
|
55
55
|
assignStrategyDrawerStatus: !1,
|
|
56
|
+
removeStrategyModalStatus: !1,
|
|
56
57
|
filterGroup: 1,
|
|
57
58
|
isInitialized: !1,
|
|
58
59
|
filterSnapshot: null
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
|
-
const
|
|
62
|
+
const z = () => ({
|
|
62
63
|
recommendationCampaignUrls: {},
|
|
63
64
|
activePredictiveAlgorithms: [],
|
|
64
65
|
languages: {},
|
|
@@ -70,8 +71,8 @@ const O = () => ({
|
|
|
70
71
|
blockStates: {},
|
|
71
72
|
currentRecommendationId: null,
|
|
72
73
|
configVersion: 0
|
|
73
|
-
}), Y =
|
|
74
|
-
state: () =>
|
|
74
|
+
}), Y = F("guidoRecommendationExtension", {
|
|
75
|
+
state: () => z(),
|
|
75
76
|
getters: {
|
|
76
77
|
// ====================================================================
|
|
77
78
|
// Proxy Getters — Backward Compatible Access to Current Block State
|
|
@@ -98,6 +99,9 @@ const O = () => ({
|
|
|
98
99
|
assignStrategyDrawerStatus(t) {
|
|
99
100
|
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].assignStrategyDrawerStatus : !1;
|
|
100
101
|
},
|
|
102
|
+
removeStrategyModalStatus(t) {
|
|
103
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].removeStrategyModalStatus : !1;
|
|
104
|
+
},
|
|
101
105
|
assignedStrategy(t) {
|
|
102
106
|
const { strategyId: e } = this.recommendationConfigs;
|
|
103
107
|
return e ? t.strategies.find((r) => String(r.strategy_id) === e) ?? null : null;
|
|
@@ -133,7 +137,7 @@ const O = () => ({
|
|
|
133
137
|
return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
|
|
134
138
|
},
|
|
135
139
|
getActivePredictiveAlgorithms: (t) => {
|
|
136
|
-
const e =
|
|
140
|
+
const e = b(), r = [];
|
|
137
141
|
return t.activePredictiveAlgorithms.filter((n) => !L.includes(n)).forEach((n) => {
|
|
138
142
|
r.push(...e.filter((s) => s.id === n));
|
|
139
143
|
}), r.map((n) => ({
|
|
@@ -152,7 +156,7 @@ const O = () => ({
|
|
|
152
156
|
getFilterList() {
|
|
153
157
|
return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
|
|
154
158
|
let e;
|
|
155
|
-
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` :
|
|
159
|
+
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : v.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
|
|
156
160
|
text: t.displayName,
|
|
157
161
|
value: e,
|
|
158
162
|
type: t.attributeType
|
|
@@ -334,6 +338,12 @@ const O = () => ({
|
|
|
334
338
|
closeAssignStrategyDrawer() {
|
|
335
339
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !1);
|
|
336
340
|
},
|
|
341
|
+
openRemoveStrategyModal() {
|
|
342
|
+
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !0);
|
|
343
|
+
},
|
|
344
|
+
closeRemoveStrategyModal() {
|
|
345
|
+
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
|
|
346
|
+
},
|
|
337
347
|
async fetchStrategies() {
|
|
338
348
|
if (S) {
|
|
339
349
|
await S;
|
|
@@ -342,7 +352,7 @@ const O = () => ({
|
|
|
342
352
|
S = (async () => {
|
|
343
353
|
this.strategiesLoading = !0;
|
|
344
354
|
try {
|
|
345
|
-
this.strategies = await
|
|
355
|
+
this.strategies = await u.fetchRecommendationStrategies();
|
|
346
356
|
} finally {
|
|
347
357
|
this.strategiesLoading = !1;
|
|
348
358
|
}
|
|
@@ -357,7 +367,7 @@ const O = () => ({
|
|
|
357
367
|
const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
|
|
358
368
|
if (s)
|
|
359
369
|
return s;
|
|
360
|
-
const { full_path: i = "" } = await
|
|
370
|
+
const { full_path: i = "" } = await u.generateStrategyEndpoint(t, e) ?? {};
|
|
361
371
|
return n && i && (this.strategyUrlTemplates = {
|
|
362
372
|
...this.strategyUrlTemplates,
|
|
363
373
|
[n]: i
|
|
@@ -386,7 +396,7 @@ const O = () => ({
|
|
|
386
396
|
activePredictiveAlgorithms: t,
|
|
387
397
|
languages: e,
|
|
388
398
|
currencies: r
|
|
389
|
-
} = await
|
|
399
|
+
} = await u.fetchRecommendationCreateData();
|
|
390
400
|
if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
|
|
391
401
|
const n = this.blockStates[this.currentRecommendationId];
|
|
392
402
|
n.filterStatus = !!n.recommendationConfigs.filters.length;
|
|
@@ -402,18 +412,18 @@ const O = () => ({
|
|
|
402
412
|
},
|
|
403
413
|
async fetchRecommendationFilters() {
|
|
404
414
|
if (!Object.keys(this.filterList).length) {
|
|
405
|
-
if (
|
|
406
|
-
await
|
|
415
|
+
if (h) {
|
|
416
|
+
await h;
|
|
407
417
|
return;
|
|
408
418
|
}
|
|
409
|
-
|
|
410
|
-
const t = await
|
|
419
|
+
h = (async () => {
|
|
420
|
+
const t = await u.fetchRecommendationFilters();
|
|
411
421
|
this.filterList = t;
|
|
412
422
|
})();
|
|
413
423
|
try {
|
|
414
|
-
await
|
|
424
|
+
await h;
|
|
415
425
|
} finally {
|
|
416
|
-
|
|
426
|
+
h = null;
|
|
417
427
|
}
|
|
418
428
|
}
|
|
419
429
|
},
|
|
@@ -480,7 +490,7 @@ const O = () => ({
|
|
|
480
490
|
}), e.recommendationConfigs.filters = r;
|
|
481
491
|
},
|
|
482
492
|
generateFilterQuery() {
|
|
483
|
-
return
|
|
493
|
+
return k(this.recommendationConfigs.filters);
|
|
484
494
|
},
|
|
485
495
|
/**
|
|
486
496
|
* Validation-only check invoked at save-CTA time. Defined as an action
|
|
@@ -488,33 +498,33 @@ const O = () => ({
|
|
|
488
498
|
* every block's recommendationConfigs across user edits.
|
|
489
499
|
*/
|
|
490
500
|
hasInvalidBlock() {
|
|
491
|
-
return Object.values(this.blockStates).some((t) => !
|
|
501
|
+
return Object.values(this.blockStates).some((t) => !M(t.recommendationConfigs, this));
|
|
492
502
|
},
|
|
493
503
|
// ====================================================================
|
|
494
504
|
// Per-Block Product Fetching
|
|
495
505
|
// ====================================================================
|
|
496
506
|
async fetchRecommendationProducts() {
|
|
497
507
|
if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
|
|
498
|
-
if (
|
|
499
|
-
await
|
|
508
|
+
if (g) {
|
|
509
|
+
await g;
|
|
500
510
|
return;
|
|
501
511
|
}
|
|
502
|
-
|
|
512
|
+
g = this._doFetchProducts();
|
|
503
513
|
try {
|
|
504
|
-
await
|
|
514
|
+
await g;
|
|
505
515
|
} finally {
|
|
506
|
-
|
|
516
|
+
g = null;
|
|
507
517
|
}
|
|
508
518
|
}
|
|
509
519
|
},
|
|
510
520
|
async _doFetchProducts() {
|
|
511
521
|
var d;
|
|
512
|
-
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n =
|
|
522
|
+
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = P();
|
|
513
523
|
if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
|
|
514
524
|
await this._doFetchStrategyProducts(t);
|
|
515
525
|
return;
|
|
516
526
|
}
|
|
517
|
-
const s = r.filters.filter((
|
|
527
|
+
const s = r.filters.filter((m) => m.isValid), i = k(s), o = ((d = b().find((m) => m.key === r.strategy)) == null ? void 0 : d.path) || "", c = parseInt(r.size) || 6, a = {
|
|
518
528
|
locale: r.language,
|
|
519
529
|
currency: r.currencySettings.value,
|
|
520
530
|
partnerName: n.partnerName,
|
|
@@ -528,7 +538,7 @@ const O = () => ({
|
|
|
528
538
|
);
|
|
529
539
|
let l;
|
|
530
540
|
try {
|
|
531
|
-
l = await
|
|
541
|
+
l = await u.fetchRecommendationProducts(o, a);
|
|
532
542
|
} catch {
|
|
533
543
|
l = [];
|
|
534
544
|
}
|
|
@@ -546,8 +556,8 @@ const O = () => ({
|
|
|
546
556
|
);
|
|
547
557
|
if (i) {
|
|
548
558
|
s = parseInt(String(i.size ?? "")) || s;
|
|
549
|
-
const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), d = l === -1 ? a : a.slice(0, l),
|
|
550
|
-
y && (n = await
|
|
559
|
+
const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), d = l === -1 ? a : a.slice(0, l), m = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((I) => I && !I.startsWith("user_id=")), y = m.length ? `${d}?${m.join("&")}` : d;
|
|
560
|
+
y && (n = await u.fetchRecommendationProductsByUrl(y));
|
|
551
561
|
}
|
|
552
562
|
} catch {
|
|
553
563
|
n = [];
|
|
@@ -557,10 +567,10 @@ const O = () => ({
|
|
|
557
567
|
_setBlockProducts(t, e, r) {
|
|
558
568
|
if (!this.blockStates[t])
|
|
559
569
|
return;
|
|
560
|
-
const n = e.length > 0 ? e :
|
|
570
|
+
const n = e.length > 0 ? e : R(r);
|
|
561
571
|
this.blockStates[t].recommendationProducts = [
|
|
562
572
|
...n.slice(0, r),
|
|
563
|
-
...
|
|
573
|
+
...R(Math.max(0, r - n.length))
|
|
564
574
|
];
|
|
565
575
|
}
|
|
566
576
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ModificationDescription as f } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
|
+
import { isPartnerManagedBlock as d, updateProductContentInPlace as m, regenerateProductRowsWithStyles as a } from "../controls/main/utils.js";
|
|
3
|
+
import { RecommendationConfigService as l } from "../services/configService.js";
|
|
4
|
+
const s = "recommendation-id";
|
|
5
|
+
let e = null;
|
|
6
|
+
function M(r) {
|
|
7
|
+
e = r;
|
|
8
|
+
}
|
|
9
|
+
function N(r, c, i, u) {
|
|
10
|
+
const n = e == null ? void 0 : e.getDocumentRootHtmlNode();
|
|
11
|
+
if (!e || !n || !("querySelector" in n))
|
|
12
|
+
return !1;
|
|
13
|
+
const t = n.querySelector(`[${s}="${r}"]`);
|
|
14
|
+
if (!t)
|
|
15
|
+
return !1;
|
|
16
|
+
const o = e.getDocumentModifier();
|
|
17
|
+
return l.stageConfig(o, t, c), d(t) ? (o.apply(new f(u)), !0) : (m({ currentNode: t, documentModifier: o, products: i }) || a({ currentNode: t, documentModifier: o, products: i }), !0);
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
N as commitBlockChangeOutsidePanel,
|
|
21
|
+
M as registerNodeConfigWriter
|
|
22
|
+
};
|
package/dist/guido.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-6e711fd7]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-
|
|
1
|
+
@charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-6e711fd7]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-5c588dc5]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-5c588dc5]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-5c588dc5]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}
|
|
@@ -63,7 +63,7 @@ const y = "[sr_strategies.status][=][active]*[sr_strategies.suitable_channels][~
|
|
|
63
63
|
);
|
|
64
64
|
return Array.isArray(e) ? e : (e == null ? void 0 : e.data) ?? [];
|
|
65
65
|
} catch (e) {
|
|
66
|
-
|
|
66
|
+
throw console.error("fetchRecommendationStrategies error:", e), e;
|
|
67
67
|
}
|
|
68
68
|
},
|
|
69
69
|
generateStrategyEndpoint: async (e, o) => {
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
|
2
|
+
export default _default;
|
|
@@ -20,7 +20,9 @@ export * from './utils';
|
|
|
20
20
|
export declare class RecommendationBlockControl extends CommonControl {
|
|
21
21
|
private store;
|
|
22
22
|
private storeUnsubscription;
|
|
23
|
-
private
|
|
23
|
+
private syncedConfigs;
|
|
24
|
+
private pendingNodeConfigWrite;
|
|
25
|
+
private pendingConfigFlushTimer;
|
|
24
26
|
private algorithmControl;
|
|
25
27
|
private localeControl;
|
|
26
28
|
private currencyControl;
|
|
@@ -54,6 +56,41 @@ export declare class RecommendationBlockControl extends CommonControl {
|
|
|
54
56
|
* Uses triggerRefetch: false because the fetch hasn't happened yet —
|
|
55
57
|
* values are being prepared for the upcoming initial fetch.
|
|
56
58
|
*/
|
|
59
|
+
/**
|
|
60
|
+
* Re-syncs the store when the node config moved since we last read it.
|
|
61
|
+
*
|
|
62
|
+
* Undo/redo, the code editor and version-history restore rewrite the node
|
|
63
|
+
* config behind the store's back — Stripo exposes no undo signal, so a
|
|
64
|
+
* fingerprint diff on this hook is the only way to notice (SD-149105).
|
|
65
|
+
* An unchanged fingerprint means the move came from us, so runtime store
|
|
66
|
+
* edits are never clobbered (SD-141049).
|
|
67
|
+
*/
|
|
68
|
+
private _syncNodeConfigIfChanged;
|
|
69
|
+
private _capturePendingNodeConfigWrite;
|
|
70
|
+
/**
|
|
71
|
+
* Accumulates the pending write into `documentModifier` without applying, so the
|
|
72
|
+
* caller's apply() commits config and re-render as ONE undo entry.
|
|
73
|
+
*
|
|
74
|
+
* Deliberately does not consume the pending record: the product helpers call
|
|
75
|
+
* apply() only when they actually changed something, so this batch may never be
|
|
76
|
+
* committed and the flush has to stay able to write it standalone.
|
|
77
|
+
* @param documentModifier - The batch to accumulate into
|
|
78
|
+
* @returns Whether anything was staged
|
|
79
|
+
*/
|
|
80
|
+
private _stagePendingNodeConfig;
|
|
81
|
+
/**
|
|
82
|
+
* Arms the guaranteed fallback write, once the product fetch has settled. The
|
|
83
|
+
* delay only has to outlast the re-render debounce that fetch triggers — firing
|
|
84
|
+
* earlier writes the config on its own and the undo entry splits in two again.
|
|
85
|
+
*/
|
|
86
|
+
private _scheduleConfigFlush;
|
|
87
|
+
private _clearConfigFlush;
|
|
88
|
+
/**
|
|
89
|
+
* Writes the deferred change standalone when the batch it was staged into never
|
|
90
|
+
* committed. Always targets the LIVE node — the captured one is an immutable
|
|
91
|
+
* snapshot the intervening re-render staled, and saveConfig swallows that failure.
|
|
92
|
+
*/
|
|
93
|
+
private _flushPendingNodeConfig;
|
|
57
94
|
private _syncNodeConfigToStore;
|
|
58
95
|
/**
|
|
59
96
|
* Fetches initial data for a block in three phases:
|
|
@@ -110,11 +147,4 @@ export declare class RecommendationBlockControl extends CommonControl {
|
|
|
110
147
|
* We skip that tick and update tracking references instead.
|
|
111
148
|
*/
|
|
112
149
|
private _listenStateUpdates;
|
|
113
|
-
/**
|
|
114
|
-
* Persists filter + strategy state to the Stripo node config so it survives
|
|
115
|
-
* save/reload (strategyId must reach esd-ext-config before any save).
|
|
116
|
-
* `size` rides along: assigning a strategy writes it to the store only, and a
|
|
117
|
-
* stale node config would rebuild the block against the old slot count.
|
|
118
|
-
*/
|
|
119
|
-
private _persistFiltersToNodeConfig;
|
|
120
150
|
}
|
|
@@ -25,7 +25,7 @@ import { ModificationDescription } from '@stripoinc/ui-editor-extensions';
|
|
|
25
25
|
* Stripo Extension API interface for document modifications
|
|
26
26
|
* Extracted to allow type-safe usage without importing full Stripo types
|
|
27
27
|
*/
|
|
28
|
-
interface DocumentModifier {
|
|
28
|
+
export interface DocumentModifier {
|
|
29
29
|
modifyHtml: (node: ImmutableHtmlNode) => {
|
|
30
30
|
setNodeConfig: (config: Record<string, unknown>) => DocumentModifier;
|
|
31
31
|
setAttribute: (name: string, value: string) => DocumentModifier;
|
|
@@ -90,6 +90,17 @@ export declare class RecommendationConfigService {
|
|
|
90
90
|
* @returns The new complete configuration
|
|
91
91
|
*/
|
|
92
92
|
static updateConfig(api: DocumentModifierApi, node: ImmutableHtmlNode, updates: PartialNodeConfig, description: string): RecommendationNodeConfig;
|
|
93
|
+
/**
|
|
94
|
+
* Accumulate a config update into an existing modifier batch, WITHOUT applying.
|
|
95
|
+
*
|
|
96
|
+
* The caller owns the apply(), so the write shares one undo entry with the rest
|
|
97
|
+
* of that batch — a change whose visible result only lands after an async product
|
|
98
|
+
* fetch would otherwise cost the user two undo presses (SD-149105).
|
|
99
|
+
* @param documentModifier - The batch to accumulate into (caller applies)
|
|
100
|
+
* @param node - The immutable HTML node to write to
|
|
101
|
+
* @param updates - Partial config with values to update
|
|
102
|
+
*/
|
|
103
|
+
static stageConfig(documentModifier: DocumentModifier, node: ImmutableHtmlNode, updates: PartialNodeConfig): void;
|
|
93
104
|
/**
|
|
94
105
|
* Initialize configuration for a new block
|
|
95
106
|
*
|
|
@@ -35,6 +35,7 @@ interface PerBlockState {
|
|
|
35
35
|
filterStatus: boolean;
|
|
36
36
|
filterSelectionDrawerStatus: boolean;
|
|
37
37
|
assignStrategyDrawerStatus: boolean;
|
|
38
|
+
removeStrategyModalStatus: boolean;
|
|
38
39
|
filterGroup: number;
|
|
39
40
|
/** Whether initial API data (filters, algorithms, products) has been fetched for this block */
|
|
40
41
|
isInitialized: boolean;
|
|
@@ -177,6 +178,29 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
|
|
|
177
178
|
currentRecommendationId: number | null;
|
|
178
179
|
configVersion: number;
|
|
179
180
|
} & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
|
|
181
|
+
removeStrategyModalStatus(state: {
|
|
182
|
+
recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
|
|
183
|
+
activePredictiveAlgorithms: number[];
|
|
184
|
+
languages: Languages;
|
|
185
|
+
currencyList: {
|
|
186
|
+
text: string;
|
|
187
|
+
value: string;
|
|
188
|
+
}[];
|
|
189
|
+
filterList: FiltersResponse;
|
|
190
|
+
strategies: {
|
|
191
|
+
[x: string]: unknown;
|
|
192
|
+
strategy_id: number;
|
|
193
|
+
name: string;
|
|
194
|
+
status: string;
|
|
195
|
+
suitable_channels: string;
|
|
196
|
+
size?: (number | string) | undefined;
|
|
197
|
+
}[];
|
|
198
|
+
strategiesLoading: boolean;
|
|
199
|
+
strategyUrlTemplates: Record<string, string>;
|
|
200
|
+
blockStates: Record<number, PerBlockState>;
|
|
201
|
+
currentRecommendationId: number | null;
|
|
202
|
+
configVersion: number;
|
|
203
|
+
} & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
|
|
180
204
|
assignedStrategy(state: {
|
|
181
205
|
recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
|
|
182
206
|
activePredictiveAlgorithms: number[];
|
|
@@ -406,6 +430,8 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
|
|
|
406
430
|
cancelFilterDrawer(): void;
|
|
407
431
|
openAssignStrategyDrawer(): void;
|
|
408
432
|
closeAssignStrategyDrawer(): void;
|
|
433
|
+
openRemoveStrategyModal(): void;
|
|
434
|
+
closeRemoveStrategyModal(): void;
|
|
409
435
|
fetchStrategies(): Promise<void>;
|
|
410
436
|
resolveStrategyUrlTemplate(strategy: RrsStrategy, currency: string): Promise<string>;
|
|
411
437
|
assignStrategy(strategy: RrsStrategy): void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DocumentModifier } from '../services/configService';
|
|
2
|
+
import type { PartialNodeConfig } from '../types/nodeConfig';
|
|
3
|
+
import type { RecommendationProduct } from '@@/Types/recommendation';
|
|
4
|
+
import { ImmutableHtmlNode } from '@stripoinc/ui-editor-extensions';
|
|
5
|
+
interface ConfigWriterApi {
|
|
6
|
+
getDocumentModifier: () => DocumentModifier;
|
|
7
|
+
getDocumentRootHtmlNode: () => ImmutableHtmlNode;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Keeps a document handle alive for writes the settings panel can no longer make.
|
|
11
|
+
* Deliberately not cleared on deselect — that is the exact moment the handle is
|
|
12
|
+
* needed. It is replaced on the next render, and goes stale only if the editor
|
|
13
|
+
* itself is torn down.
|
|
14
|
+
*/
|
|
15
|
+
export declare function registerNodeConfigWriter(api: ConfigWriterApi): void;
|
|
16
|
+
/**
|
|
17
|
+
* Commits a config change and its product re-render straight to the document,
|
|
18
|
+
* bypassing the settings panel.
|
|
19
|
+
*
|
|
20
|
+
* Host-rendered UI (the remove-strategy modal) lives outside `ui-editor`, and
|
|
21
|
+
* Stripo deselects the block on the first click that lands there — destroying the
|
|
22
|
+
* control that normally does both, before the store change even happens.
|
|
23
|
+
*
|
|
24
|
+
* Mirrors the control's regenerate routine so config and cards land in ONE undo
|
|
25
|
+
* entry, and so partner-managed blocks keep their hand-authored cells.
|
|
26
|
+
* @param description - labels the undo entry only when there are no cards to
|
|
27
|
+
* re-render; the product helpers label their own batch.
|
|
28
|
+
* @returns whether the write reached a node
|
|
29
|
+
*/
|
|
30
|
+
export declare function commitBlockChangeOutsidePanel(blockId: number, updates: PartialNodeConfig, products: RecommendationProduct[], description: string): boolean;
|
|
31
|
+
export {};
|
|
@@ -25,3 +25,8 @@ export declare const getCsrfToken: () => string;
|
|
|
25
25
|
export declare const getUrlParams: () => URLSearchParams;
|
|
26
26
|
export declare const getUrlParam: (paramName: string, defaultValue?: string) => string;
|
|
27
27
|
export declare const replaceString: (string?: string, values?: Record<string, string | number>, isRemoveEmptyValues?: boolean) => string;
|
|
28
|
+
/**
|
|
29
|
+
* Narrows an unknown API value to a printable string; anything that is neither
|
|
30
|
+
* a string nor a number becomes ''.
|
|
31
|
+
*/
|
|
32
|
+
export declare const asText: (value: unknown) => string;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
const o = (
|
|
2
|
-
const a =
|
|
3
|
-
text:
|
|
4
|
-
value:
|
|
1
|
+
const o = (t) => {
|
|
2
|
+
const a = t.value.match(/\{\{([^}]+)\}\}/)[1].split("|").map((l) => l.trim()), [s] = a, r = {
|
|
3
|
+
text: t.label,
|
|
4
|
+
value: s || ""
|
|
5
5
|
};
|
|
6
6
|
if (a.length >= 2) {
|
|
7
|
-
const [,
|
|
8
|
-
if (
|
|
9
|
-
let n =
|
|
7
|
+
const [, l, e] = a;
|
|
8
|
+
if (l.startsWith("default:")) {
|
|
9
|
+
let n = l.slice(8).trim();
|
|
10
10
|
n.startsWith('"') && n.endsWith('"') && (n = n.slice(1, -1)), r.fallback = n;
|
|
11
11
|
} else {
|
|
12
|
-
const n =
|
|
13
|
-
n ? r.format = n : e || (r.fallback =
|
|
12
|
+
const n = l.includes("=") ? { key: l.split("=")[0].trim(), value: l.split("=")[1].trim() } : null;
|
|
13
|
+
n ? r.format = n : e || (r.fallback = l), e && (r.fallback = e);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
return r;
|
|
17
|
-
}, f = (
|
|
17
|
+
}, f = (t, c = !1) => t.map((a) => {
|
|
18
18
|
if (a.format)
|
|
19
19
|
return {
|
|
20
20
|
label: `${a.text} | ${a.format.key}=${a.format.value}`,
|
|
21
21
|
value: `{{${a.value}|${a.format.key}=${a.format.value}}}`
|
|
22
22
|
};
|
|
23
|
-
if (
|
|
23
|
+
if (c) {
|
|
24
24
|
if (!a.fallback)
|
|
25
25
|
return {
|
|
26
26
|
label: a.text,
|
|
@@ -36,33 +36,34 @@ const o = (l) => {
|
|
|
36
36
|
label: a.fallback ? `${a.text} | ${a.fallback}` : a.text,
|
|
37
37
|
value: a.fallback ? `{{${a.value}|${a.fallback}}}` : `{{${a.value}}}`
|
|
38
38
|
};
|
|
39
|
-
}), b = (
|
|
40
|
-
const
|
|
41
|
-
Array.isArray(
|
|
39
|
+
}), b = (t) => {
|
|
40
|
+
const c = [], a = /* @__PURE__ */ new Set(), s = (l) => {
|
|
41
|
+
Array.isArray(l) && l.forEach((e) => {
|
|
42
42
|
const n = [...e.children ?? [], ...e.select_items ?? []];
|
|
43
43
|
if (n.length > 0) {
|
|
44
|
-
|
|
44
|
+
s(n);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
const u = e.text || e.tag_text;
|
|
48
|
-
u && e.value && !a.has(e.value) && (a.add(e.value),
|
|
48
|
+
u && e.value && !a.has(e.value) && (a.add(e.value), c.push({ text: u, value: e.value }));
|
|
49
49
|
});
|
|
50
|
-
}, [r] = Object.values(
|
|
51
|
-
return
|
|
52
|
-
},
|
|
53
|
-
const
|
|
50
|
+
}, [r] = Object.values(t ?? {});
|
|
51
|
+
return s(r), c;
|
|
52
|
+
}, i = (t, c, a = !1) => {
|
|
53
|
+
const s = new Set(t.map((l) => l.value)), r = c.filter((l) => s.has(l.value) ? !1 : (s.add(l.value), !0));
|
|
54
54
|
return [
|
|
55
|
-
...f(
|
|
55
|
+
...f(t, a),
|
|
56
56
|
...f(r, a)
|
|
57
57
|
];
|
|
58
|
-
},
|
|
59
|
-
var
|
|
60
|
-
return ((
|
|
61
|
-
};
|
|
58
|
+
}, v = () => {
|
|
59
|
+
var t;
|
|
60
|
+
return ((t = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : t.getAttribute("content")) ?? "";
|
|
61
|
+
}, k = (t) => typeof t == "string" ? t : typeof t == "number" ? String(t) : "";
|
|
62
62
|
export {
|
|
63
|
-
|
|
63
|
+
k as asText,
|
|
64
|
+
i as buildMergeTagEntries,
|
|
64
65
|
f as dynamicContentToMergeTags,
|
|
65
66
|
b as flattenDynamicContentList,
|
|
66
|
-
|
|
67
|
+
v as getCsrfToken,
|
|
67
68
|
o as mergeTagToDynamicContent
|
|
68
69
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.17.0-beta.
|
|
3
|
+
"version": "3.17.0-beta.6cedc6c",
|
|
4
4
|
"description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
|
|
5
5
|
"main": "./dist/guido.umd.cjs",
|
|
6
6
|
"module": "./dist/library.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"start": "vite",
|
|
26
26
|
"build": "vite build && vue-tsc --declaration --emitDeclarationOnly --project tsconfig.app.json",
|
|
27
27
|
"preview": "vite preview",
|
|
28
|
-
"lint": "NODE_OPTIONS=--max-old-space-size=2048 eslint ./ &&
|
|
28
|
+
"lint": "NODE_OPTIONS=--max-old-space-size=2048 eslint ./ && npm run type-check",
|
|
29
29
|
"lint:fix": "NODE_OPTIONS=--max-old-space-size=2048 eslint --fix ./",
|
|
30
30
|
"lint:e2e-quality": "node scripts/lint-e2e-quality.mjs",
|
|
31
31
|
"lint:e2e-quality:ci": "node scripts/lint-e2e-quality.mjs --ci",
|