@useinsider/guido 3.18.1-beta.e9a6c91 → 3.18.1-beta.fefef3c
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 +21 -3
- package/dist/@types/config/schemas.js +59 -51
- package/dist/components/Guido.vue.js +4 -4
- package/dist/components/Guido.vue2.js +72 -70
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +7 -9
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +83 -72
- package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js +18 -0
- package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue2.js +25 -0
- package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +24 -22
- package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +28 -26
- package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.js +21 -0
- package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue2.js +46 -0
- package/dist/composables/useCustomInterfaceAppearance.js +46 -42
- package/dist/composables/useHtmlValidator.js +79 -84
- package/dist/composables/useLegacyStrategyConversion.js +61 -0
- package/dist/composables/useRecommendation.js +18 -21
- package/dist/enums/extensions/recommendationBlock.js +25 -29
- package/dist/extensions/Blocks/Recommendation/block.js +39 -43
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +72 -71
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +70 -40
- package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +45 -44
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +108 -138
- package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +72 -0
- package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +7 -7
- package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +12 -21
- package/dist/guido.css +1 -1
- package/dist/services/recommendationApi.js +93 -84
- package/dist/src/@types/config/schemas.d.ts +16 -0
- package/dist/src/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.d.ts +2 -0
- package/dist/src/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.d.ts +2 -0
- package/dist/src/composables/useConfig.d.ts +4 -0
- package/dist/src/composables/useLegacyStrategyConversion.d.ts +3 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +3 -2
- package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +4 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +54 -50
- package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +44 -0
- package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +0 -4
- package/dist/src/services/recommendationApi.d.ts +2 -1
- package/dist/src/stores/config.d.ts +322 -0
- package/dist/src/stores/onboarding.d.ts +421 -0
- package/dist/static/assets/icons/filled-arrow-rising.svg.js +5 -0
- package/dist/static/assets/icons/line-info.svg.js +5 -0
- package/dist/static/styles/components/recommendation-strategy.css.js +74 -43
- package/dist/stores/config.js +74 -60
- package/dist/stores/onboarding.js +6 -1
- package/dist/utils/templatePreparation.js +50 -50
- package/package.json +1 -1
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { getRecommendationFeedSourceMaps as
|
|
2
|
-
import { useRecommendationApi as
|
|
3
|
-
import { useConfigStore as
|
|
4
|
-
import { defineStore as
|
|
1
|
+
import { getRecommendationFeedSourceMaps as R, getOperatorOptions as D, PriceAttributes as F } from "../../../../enums/extensions/recommendationBlock.js";
|
|
2
|
+
import { useRecommendationApi as P } from "../../../../services/recommendationApi.js";
|
|
3
|
+
import { useConfigStore as k } from "../../../../stores/config.js";
|
|
4
|
+
import { defineStore as L } from "pinia";
|
|
5
5
|
import "../constants/selectors.js";
|
|
6
|
-
import { DEFAULT_MOBILE_CARDS_IN_ROW as U, DEFAULT_CARDS_IN_ROW as
|
|
7
|
-
import { DEFAULT_NODE_CONFIG as
|
|
6
|
+
import { DEFAULT_MOBILE_CARDS_IN_ROW as U, DEFAULT_CARDS_IN_ROW as _ } from "../constants/layout.js";
|
|
7
|
+
import { CURRENT_CONFIG_VERSION as y, DEFAULT_NODE_CONFIG as N, EXCLUDED_ALGORITHM_IDS as M } from "../constants/defaultConfig.js";
|
|
8
8
|
import { getDefaultProducts as C } from "../templates/utils.js";
|
|
9
9
|
import { generateCompleteFilterQuery as v } from "../utils/filterUtil.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
function
|
|
10
|
+
import { isLegacyStrategyConfig as x } from "../utils/legacyStrategyMigration.js";
|
|
11
|
+
import { getPartnerRecommendationParams as z } from "../utils/partnerCustomizations.js";
|
|
12
|
+
import { sanitizeProductIds as B } from "../utils/productIds.js";
|
|
13
|
+
import { isFilterValid as A } from "../validation/filterSchema.js";
|
|
14
|
+
import { isConfigValid as O } from "../validation/requiredFields.js";
|
|
15
|
+
const m = P();
|
|
16
|
+
let f = null, g = null, h = null, S = null;
|
|
17
|
+
const p = /* @__PURE__ */ new Map();
|
|
18
|
+
function G() {
|
|
19
19
|
return {
|
|
20
|
-
cardsInRow:
|
|
20
|
+
cardsInRow: _,
|
|
21
21
|
currencySettings: {
|
|
22
22
|
name: "USD",
|
|
23
23
|
value: "USD",
|
|
@@ -37,12 +37,9 @@ function F() {
|
|
|
37
37
|
recommendedProducts: [],
|
|
38
38
|
sendProductRequestFlag: !1,
|
|
39
39
|
shuffleProducts: !1,
|
|
40
|
-
|
|
41
|
-
// that default is what reached buildCampaignUrl and baked a most-popular feed URL
|
|
42
|
-
// for a block the user never configured (SD-149916). Legacy blocks still get their real
|
|
43
|
-
// algorithm from the node-config sync or the save-time seed.
|
|
44
|
-
strategy: P().isFeatureEnabled("reusableRecommendationStrategy") ? "" : "mostPopular",
|
|
40
|
+
strategy: "mostPopular",
|
|
45
41
|
strategyId: "",
|
|
42
|
+
nodeConfigVersion: y,
|
|
46
43
|
textTrimming: !0,
|
|
47
44
|
unresponsive: !1,
|
|
48
45
|
size: "6",
|
|
@@ -53,18 +50,20 @@ function F() {
|
|
|
53
50
|
}
|
|
54
51
|
function w() {
|
|
55
52
|
return {
|
|
56
|
-
recommendationConfigs:
|
|
53
|
+
recommendationConfigs: G(),
|
|
57
54
|
recommendationProducts: [],
|
|
58
55
|
filterStatus: !1,
|
|
59
56
|
filterSelectionDrawerStatus: !1,
|
|
60
57
|
assignStrategyDrawerStatus: !1,
|
|
61
58
|
removeStrategyModalStatus: !1,
|
|
59
|
+
legacyStrategyUpdatedModalStatus: !1,
|
|
62
60
|
filterGroup: 1,
|
|
63
61
|
isInitialized: !1,
|
|
64
|
-
filterSnapshot: null
|
|
62
|
+
filterSnapshot: null,
|
|
63
|
+
legacyConversionLoading: !1
|
|
65
64
|
};
|
|
66
65
|
}
|
|
67
|
-
const
|
|
66
|
+
const E = () => ({
|
|
68
67
|
recommendationCampaignUrls: {},
|
|
69
68
|
activePredictiveAlgorithms: [],
|
|
70
69
|
languages: {},
|
|
@@ -73,12 +72,11 @@ const j = () => ({
|
|
|
73
72
|
strategies: [],
|
|
74
73
|
strategiesLoading: !1,
|
|
75
74
|
strategyUrlTemplates: {},
|
|
76
|
-
strategiesFetched: !1,
|
|
77
75
|
blockStates: {},
|
|
78
76
|
currentRecommendationId: null,
|
|
79
77
|
configVersion: 0
|
|
80
|
-
}),
|
|
81
|
-
state: () =>
|
|
78
|
+
}), et = L("guidoRecommendationExtension", {
|
|
79
|
+
state: () => E(),
|
|
82
80
|
getters: {
|
|
83
81
|
// ====================================================================
|
|
84
82
|
// Proxy Getters — Backward Compatible Access to Current Block State
|
|
@@ -88,7 +86,7 @@ const j = () => ({
|
|
|
88
86
|
* This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
|
|
89
87
|
*/
|
|
90
88
|
recommendationConfigs(t) {
|
|
91
|
-
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs :
|
|
89
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : G();
|
|
92
90
|
},
|
|
93
91
|
/**
|
|
94
92
|
* Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
|
|
@@ -108,6 +106,15 @@ const j = () => ({
|
|
|
108
106
|
removeStrategyModalStatus(t) {
|
|
109
107
|
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].removeStrategyModalStatus : !1;
|
|
110
108
|
},
|
|
109
|
+
isLegacyStrategyBlock() {
|
|
110
|
+
return k().isFeatureEnabled("reusableRecommendationStrategy") && x(this.recommendationConfigs);
|
|
111
|
+
},
|
|
112
|
+
legacyConversionLoading(t) {
|
|
113
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].legacyConversionLoading : !1;
|
|
114
|
+
},
|
|
115
|
+
legacyStrategyUpdatedModalStatus(t) {
|
|
116
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].legacyStrategyUpdatedModalStatus : !1;
|
|
117
|
+
},
|
|
111
118
|
assignedStrategy(t) {
|
|
112
119
|
const { strategyId: e } = this.recommendationConfigs;
|
|
113
120
|
return e ? t.strategies.find((r) => String(r.strategy_id) === e) ?? null : null;
|
|
@@ -143,8 +150,8 @@ const j = () => ({
|
|
|
143
150
|
return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
|
|
144
151
|
},
|
|
145
152
|
getActivePredictiveAlgorithms: (t) => {
|
|
146
|
-
const e =
|
|
147
|
-
return t.activePredictiveAlgorithms.filter((n) => !
|
|
153
|
+
const e = R(), r = [];
|
|
154
|
+
return t.activePredictiveAlgorithms.filter((n) => !M.includes(n)).forEach((n) => {
|
|
148
155
|
r.push(...e.filter((s) => s.id === n));
|
|
149
156
|
}), r.map((n) => ({
|
|
150
157
|
text: n.name,
|
|
@@ -162,7 +169,7 @@ const j = () => ({
|
|
|
162
169
|
getFilterList() {
|
|
163
170
|
return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
|
|
164
171
|
let e;
|
|
165
|
-
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` :
|
|
172
|
+
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : F.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
|
|
166
173
|
text: t.displayName,
|
|
167
174
|
value: e,
|
|
168
175
|
type: t.attributeType
|
|
@@ -291,7 +298,7 @@ const j = () => ({
|
|
|
291
298
|
* Creates a filter with the first available attribute and operator pre-selected.
|
|
292
299
|
*/
|
|
293
300
|
createDefaultFilter(t, e) {
|
|
294
|
-
const [r] = this.getFilterList, [n] =
|
|
301
|
+
const [r] = this.getFilterList, [n] = D(r == null ? void 0 : r.type);
|
|
295
302
|
return {
|
|
296
303
|
type: "standardFilter",
|
|
297
304
|
attribute: (r == null ? void 0 : r.value) ?? "",
|
|
@@ -344,6 +351,12 @@ const j = () => ({
|
|
|
344
351
|
closeAssignStrategyDrawer() {
|
|
345
352
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !1);
|
|
346
353
|
},
|
|
354
|
+
openLegacyStrategyUpdatedModal() {
|
|
355
|
+
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].legacyStrategyUpdatedModalStatus = !0);
|
|
356
|
+
},
|
|
357
|
+
closeLegacyStrategyUpdatedModal() {
|
|
358
|
+
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].legacyStrategyUpdatedModalStatus = !1);
|
|
359
|
+
},
|
|
347
360
|
openRemoveStrategyModal() {
|
|
348
361
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !0);
|
|
349
362
|
},
|
|
@@ -351,87 +364,29 @@ const j = () => ({
|
|
|
351
364
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
|
|
352
365
|
},
|
|
353
366
|
async fetchStrategies() {
|
|
354
|
-
if (
|
|
367
|
+
if (S) {
|
|
368
|
+
await S;
|
|
355
369
|
return;
|
|
356
|
-
|
|
357
|
-
|
|
370
|
+
}
|
|
371
|
+
S = (async () => {
|
|
358
372
|
this.strategiesLoading = !0;
|
|
359
373
|
try {
|
|
360
|
-
|
|
361
|
-
if (t !== y)
|
|
362
|
-
return;
|
|
363
|
-
this.strategies = e, this.strategiesFetched = !0;
|
|
374
|
+
this.strategies = await m.fetchRecommendationStrategies();
|
|
364
375
|
} finally {
|
|
365
376
|
this.strategiesLoading = !1;
|
|
366
377
|
}
|
|
367
378
|
})();
|
|
368
379
|
try {
|
|
369
|
-
await
|
|
380
|
+
await S;
|
|
370
381
|
} finally {
|
|
371
|
-
|
|
382
|
+
S = null;
|
|
372
383
|
}
|
|
373
384
|
},
|
|
374
|
-
invalidateStrategies() {
|
|
375
|
-
this.strategiesFetched = !1, y += 1;
|
|
376
|
-
},
|
|
377
|
-
/**
|
|
378
|
-
* Opens a Smart Recommender strategy page in a new tab and refreshes the list every time
|
|
379
|
-
* the user comes back. `visibilitychange` covers the tab case; `focus` covers the page
|
|
380
|
-
* landing in a separate window, where this document never goes hidden.
|
|
381
|
-
*
|
|
382
|
-
* Deliberately NOT one-shot: the strategy tab stays open, so a user can create a second
|
|
383
|
-
* strategy in it and come back again — a listener that disarmed on the first return would
|
|
384
|
-
* leave that one missing from the list. Armed only once the user actually opens a strategy
|
|
385
|
-
* page, so anyone who never does pays nothing.
|
|
386
|
-
*/
|
|
387
|
-
_armStrategyPageReturn(t) {
|
|
388
|
-
window.open(t, "_blank", "noopener"), u == null || u();
|
|
389
|
-
let e = !1;
|
|
390
|
-
const r = () => {
|
|
391
|
-
document.hidden || e || (e = !0, this.invalidateStrategies(), this.fetchStrategies().then(() => this._refreshAssignedStrategyProducts()).catch(() => {
|
|
392
|
-
}).finally(() => {
|
|
393
|
-
e = !1;
|
|
394
|
-
}));
|
|
395
|
-
};
|
|
396
|
-
document.addEventListener("visibilitychange", r), window.addEventListener("focus", r), u = () => {
|
|
397
|
-
document.removeEventListener("visibilitychange", r), window.removeEventListener("focus", r), u = null;
|
|
398
|
-
};
|
|
399
|
-
},
|
|
400
|
-
/**
|
|
401
|
-
* Reloads the products of the block the user is on, so an edit made in the strategy tab
|
|
402
|
-
* lands on the canvas instead of waiting for the assign drawer to be reopened.
|
|
403
|
-
*
|
|
404
|
-
* Only the selected block: the canvas regeneration is driven off the active block's
|
|
405
|
-
* product array, so refreshing an unselected block would fetch without redrawing it.
|
|
406
|
-
*/
|
|
407
|
-
async _refreshAssignedStrategyProducts() {
|
|
408
|
-
var e;
|
|
409
|
-
const t = this.currentRecommendationId;
|
|
410
|
-
t === null || !((e = this.blockStates[t]) != null && e.recommendationConfigs.strategyId) || await this.fetchRecommendationProducts();
|
|
411
|
-
},
|
|
412
|
-
/** Lets the editor tear the return listeners down when it unmounts. */
|
|
413
|
-
disposeStrategyPageReturn() {
|
|
414
|
-
u == null || u();
|
|
415
|
-
},
|
|
416
|
-
/**
|
|
417
|
-
* Opens Smart Recommender's strategy creation page. Every return refreshes the list so the
|
|
418
|
-
* new strategy is offered; the user picks it themselves.
|
|
419
|
-
*/
|
|
420
|
-
openStrategyCreation() {
|
|
421
|
-
this._armStrategyPageReturn(D.RECOMMENDATION_STRATEGY_CREATE_PATH);
|
|
422
|
-
},
|
|
423
|
-
/**
|
|
424
|
-
* Opens the strategy's edit page. Every return refreshes the list so the block reflects the
|
|
425
|
-
* edited configuration.
|
|
426
|
-
*/
|
|
427
|
-
openStrategyEdit(t) {
|
|
428
|
-
this._armStrategyPageReturn(G(t));
|
|
429
|
-
},
|
|
430
385
|
async resolveStrategyUrlTemplate(t, e) {
|
|
431
386
|
const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
|
|
432
387
|
if (s)
|
|
433
388
|
return s;
|
|
434
|
-
const { full_path: i = "" } = await
|
|
389
|
+
const { full_path: i = "" } = await m.generateStrategyEndpoint(t, e) ?? {};
|
|
435
390
|
return n && i && (this.strategyUrlTemplates = {
|
|
436
391
|
...this.strategyUrlTemplates,
|
|
437
392
|
[n]: i
|
|
@@ -443,24 +398,51 @@ const j = () => ({
|
|
|
443
398
|
...t.size !== void 0 ? { size: String(t.size) } : {}
|
|
444
399
|
});
|
|
445
400
|
},
|
|
401
|
+
async convertLegacyStrategy(t, e = { scope: "campaign" }) {
|
|
402
|
+
const r = this.currentRecommendationId;
|
|
403
|
+
if (r === null || !this.blockStates[r])
|
|
404
|
+
throw new Error("[Guido] convertLegacyStrategy called without an active block");
|
|
405
|
+
this.blockStates[r].legacyConversionLoading = !0;
|
|
406
|
+
try {
|
|
407
|
+
const n = await m.migrateLegacyStrategy(t, e);
|
|
408
|
+
try {
|
|
409
|
+
await this.fetchStrategies();
|
|
410
|
+
} catch (o) {
|
|
411
|
+
console.error("[Guido] strategy listing refresh after conversion failed", o);
|
|
412
|
+
}
|
|
413
|
+
const s = this.strategies.find((o) => String(o.strategy_id) === n), i = this.blockStates[r];
|
|
414
|
+
return i && (i.recommendationConfigs = {
|
|
415
|
+
...i.recommendationConfigs,
|
|
416
|
+
strategyId: n,
|
|
417
|
+
nodeConfigVersion: y,
|
|
418
|
+
...(s == null ? void 0 : s.size) !== void 0 ? { size: String(s.size) } : {}
|
|
419
|
+
}), this.currentRecommendationId === r && this.configVersion++, n;
|
|
420
|
+
} finally {
|
|
421
|
+
this.blockStates[r] && (this.blockStates[r].legacyConversionLoading = !1);
|
|
422
|
+
}
|
|
423
|
+
},
|
|
446
424
|
removeStrategy() {
|
|
447
|
-
this.patchCurrentBlockConfig({
|
|
425
|
+
this.patchCurrentBlockConfig({
|
|
426
|
+
strategyId: "",
|
|
427
|
+
size: N.size,
|
|
428
|
+
nodeConfigVersion: y
|
|
429
|
+
});
|
|
448
430
|
},
|
|
449
431
|
// ====================================================================
|
|
450
432
|
// Shared Data Fetching (fetched once, used by all blocks)
|
|
451
433
|
// ====================================================================
|
|
452
434
|
async fetchRecommendationCreateData() {
|
|
453
435
|
if (!this.activePredictiveAlgorithms.length) {
|
|
454
|
-
if (
|
|
455
|
-
await
|
|
436
|
+
if (f) {
|
|
437
|
+
await f;
|
|
456
438
|
return;
|
|
457
439
|
}
|
|
458
|
-
|
|
440
|
+
f = (async () => {
|
|
459
441
|
const {
|
|
460
442
|
activePredictiveAlgorithms: t,
|
|
461
443
|
languages: e,
|
|
462
444
|
currencies: r
|
|
463
|
-
} = await
|
|
445
|
+
} = await m.fetchRecommendationCreateData();
|
|
464
446
|
if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
|
|
465
447
|
const n = this.blockStates[this.currentRecommendationId];
|
|
466
448
|
n.filterStatus = !!n.recommendationConfigs.filters.length;
|
|
@@ -468,9 +450,9 @@ const j = () => ({
|
|
|
468
450
|
this.currencyList = r;
|
|
469
451
|
})();
|
|
470
452
|
try {
|
|
471
|
-
await
|
|
453
|
+
await f;
|
|
472
454
|
} finally {
|
|
473
|
-
|
|
455
|
+
f = null;
|
|
474
456
|
}
|
|
475
457
|
}
|
|
476
458
|
},
|
|
@@ -481,7 +463,7 @@ const j = () => ({
|
|
|
481
463
|
return;
|
|
482
464
|
}
|
|
483
465
|
g = (async () => {
|
|
484
|
-
const t = await
|
|
466
|
+
const t = await m.fetchRecommendationFilters();
|
|
485
467
|
this.filterList = t;
|
|
486
468
|
})();
|
|
487
469
|
try {
|
|
@@ -516,7 +498,7 @@ const j = () => ({
|
|
|
516
498
|
const n = [...e.recommendationConfigs.filters];
|
|
517
499
|
n[r] = {
|
|
518
500
|
...t,
|
|
519
|
-
isValid:
|
|
501
|
+
isValid: A(t)
|
|
520
502
|
}, e.recommendationConfigs.filters = n;
|
|
521
503
|
}
|
|
522
504
|
},
|
|
@@ -562,45 +544,33 @@ const j = () => ({
|
|
|
562
544
|
* every block's recommendationConfigs across user edits.
|
|
563
545
|
*/
|
|
564
546
|
hasInvalidBlock() {
|
|
565
|
-
return Object.values(this.blockStates).some((t) => !
|
|
566
|
-
},
|
|
567
|
-
/**
|
|
568
|
-
* Which required fields are missing across the design's blocks, so the save
|
|
569
|
-
* toaster can name the cause instead of always showing the generic message.
|
|
570
|
-
*/
|
|
571
|
-
invalidBlockFields() {
|
|
572
|
-
return Object.values(this.blockStates).flatMap((t) => z(t.recommendationConfigs, this));
|
|
547
|
+
return Object.values(this.blockStates).some((t) => !O(t.recommendationConfigs, this));
|
|
573
548
|
},
|
|
574
549
|
// ====================================================================
|
|
575
550
|
// Per-Block Product Fetching
|
|
576
551
|
// ====================================================================
|
|
577
552
|
async fetchRecommendationProducts() {
|
|
578
553
|
if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
|
|
579
|
-
if (
|
|
580
|
-
await
|
|
554
|
+
if (h) {
|
|
555
|
+
await h;
|
|
581
556
|
return;
|
|
582
557
|
}
|
|
583
|
-
|
|
558
|
+
h = this._doFetchProducts();
|
|
584
559
|
try {
|
|
585
|
-
await
|
|
560
|
+
await h;
|
|
586
561
|
} finally {
|
|
587
|
-
|
|
562
|
+
h = null;
|
|
588
563
|
}
|
|
589
564
|
}
|
|
590
565
|
},
|
|
591
566
|
async _doFetchProducts() {
|
|
592
|
-
var
|
|
593
|
-
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n =
|
|
567
|
+
var d;
|
|
568
|
+
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = k();
|
|
594
569
|
if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
|
|
595
570
|
await this._doFetchStrategyProducts(t);
|
|
596
571
|
return;
|
|
597
572
|
}
|
|
598
|
-
const s = parseInt(r.size) || 6
|
|
599
|
-
if (!r.strategy) {
|
|
600
|
-
this._setBlockProducts(t, [], s);
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
const i = r.filters.filter((m) => m.isValid), o = v(i), c = ((f = k().find((m) => m.key === r.strategy)) == null ? void 0 : f.path) || "", a = {
|
|
573
|
+
const s = r.filters.filter((u) => u.isValid), i = v(s), o = ((d = R().find((u) => u.key === r.strategy)) == null ? void 0 : d.path) || "", c = parseInt(r.size) || 6, a = {
|
|
604
574
|
locale: r.language,
|
|
605
575
|
currency: r.currencySettings.value,
|
|
606
576
|
partnerName: n.partnerName,
|
|
@@ -608,21 +578,21 @@ const j = () => ({
|
|
|
608
578
|
details: !0,
|
|
609
579
|
campaignId: n.variationId
|
|
610
580
|
};
|
|
611
|
-
r.strategy === "manualMerchandising" ? a.productId =
|
|
581
|
+
r.strategy === "manualMerchandising" ? a.productId = B(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), i && (a.filter = i), r.shuffleProducts && (a.shuffle = !0), Object.assign(
|
|
612
582
|
a,
|
|
613
|
-
|
|
583
|
+
z(n.partnerName, r.strategy)
|
|
614
584
|
);
|
|
615
585
|
let l;
|
|
616
586
|
try {
|
|
617
|
-
l = await
|
|
587
|
+
l = await m.fetchRecommendationProducts(o, a);
|
|
618
588
|
} catch {
|
|
619
589
|
l = [];
|
|
620
590
|
}
|
|
621
|
-
this._setBlockProducts(t, l,
|
|
591
|
+
this._setBlockProducts(t, l, c);
|
|
622
592
|
},
|
|
623
593
|
async _doFetchStrategyProducts(t) {
|
|
624
|
-
const e = (
|
|
625
|
-
|
|
594
|
+
const e = (p.get(t) ?? 0) + 1;
|
|
595
|
+
p.set(t, e);
|
|
626
596
|
const { recommendationConfigs: r } = this.blockStates[t];
|
|
627
597
|
let n = [], s = parseInt(r.size) || 6;
|
|
628
598
|
try {
|
|
@@ -632,13 +602,13 @@ const j = () => ({
|
|
|
632
602
|
);
|
|
633
603
|
if (i) {
|
|
634
604
|
s = parseInt(String(i.size ?? "")) || s;
|
|
635
|
-
const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"),
|
|
636
|
-
I && (n = await
|
|
605
|
+
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), u = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((b) => b && !b.startsWith("user_id=")), I = u.length ? `${d}?${u.join("&")}` : d;
|
|
606
|
+
I && (n = await m.fetchRecommendationProductsByUrl(I));
|
|
637
607
|
}
|
|
638
608
|
} catch {
|
|
639
609
|
n = [];
|
|
640
610
|
}
|
|
641
|
-
|
|
611
|
+
p.get(t) === e && this._setBlockProducts(t, n, s);
|
|
642
612
|
},
|
|
643
613
|
_setBlockProducts(t, e, r) {
|
|
644
614
|
if (!this.blockStates[t])
|
|
@@ -652,5 +622,5 @@ const j = () => ({
|
|
|
652
622
|
}
|
|
653
623
|
});
|
|
654
624
|
export {
|
|
655
|
-
|
|
625
|
+
et as useRecommendationExtensionStore
|
|
656
626
|
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { OP_ANY_OF as p } from "../../../../enums/extensions/recommendationBlock.js";
|
|
2
|
+
import "../constants/selectors.js";
|
|
3
|
+
import { CURRENT_CONFIG_VERSION as l } from "../constants/defaultConfig.js";
|
|
4
|
+
import { parseTagList as I } from "./filterUtil.js";
|
|
5
|
+
import { sanitizeProductIds as N } from "./productIds.js";
|
|
6
|
+
const b = "String", f = "manualMerchandising";
|
|
7
|
+
function A({ strategyId: t, nodeConfigVersion: o }) {
|
|
8
|
+
return !t && o < l;
|
|
9
|
+
}
|
|
10
|
+
const m = (t) => {
|
|
11
|
+
const o = String(t ?? "").trim();
|
|
12
|
+
return /^[1-9]\d*$/.test(o) ? o : null;
|
|
13
|
+
};
|
|
14
|
+
function O({ campaignId: t, templateLibraryId: o }) {
|
|
15
|
+
if (m(t))
|
|
16
|
+
return { scope: "campaign" };
|
|
17
|
+
const e = m(o);
|
|
18
|
+
return e ? { scope: "template", templateId: e } : { scope: "campaign" };
|
|
19
|
+
}
|
|
20
|
+
const d = (t) => t === "|" ? "or" : "and", y = (t, o) => {
|
|
21
|
+
var e;
|
|
22
|
+
return {
|
|
23
|
+
conditionLogic: d(t.innerGroupOperator),
|
|
24
|
+
attribute: {
|
|
25
|
+
attributeName: t.attribute,
|
|
26
|
+
attributeType: ((e = o.find((r) => r.value === t.attribute)) == null ? void 0 : e.type) || b
|
|
27
|
+
},
|
|
28
|
+
operator: { operator: t.operator === p ? "=" : t.operator },
|
|
29
|
+
value: t.operator === p ? I(t.value).join(p) : t.value
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
function L(t, o) {
|
|
33
|
+
const e = /* @__PURE__ */ new Map();
|
|
34
|
+
return t.filter((r) => r.isValid).forEach((r) => {
|
|
35
|
+
e.set(r.filterGroup, [...e.get(r.filterGroup) ?? [], r]);
|
|
36
|
+
}), [...e.keys()].sort((r, n) => r - n).map((r) => {
|
|
37
|
+
const n = [...e.get(r) ?? []].sort((i, a) => i.filterNumber - a.filterNumber);
|
|
38
|
+
return {
|
|
39
|
+
groupLogic: d(n[0].outerGroupOperator),
|
|
40
|
+
conditionList: n.map((i) => y(i, o))
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function S({
|
|
45
|
+
blockId: t,
|
|
46
|
+
url: o,
|
|
47
|
+
campaignId: e,
|
|
48
|
+
variationId: r,
|
|
49
|
+
strategy: n,
|
|
50
|
+
productIds: i,
|
|
51
|
+
filters: a,
|
|
52
|
+
attributes: g,
|
|
53
|
+
target: u
|
|
54
|
+
}) {
|
|
55
|
+
const s = L(a, g), c = n === f ? N(i).split(",").filter(Boolean) : [];
|
|
56
|
+
return {
|
|
57
|
+
...u.scope === "template" ? { templateId: Number.parseInt(u.templateId) } : {
|
|
58
|
+
campaignId: Number.parseInt(e) || 0,
|
|
59
|
+
variationId: Number.parseInt(r) || 0
|
|
60
|
+
},
|
|
61
|
+
blockId: String(t),
|
|
62
|
+
url: o,
|
|
63
|
+
...s.length ? { filters: s } : {},
|
|
64
|
+
...c.length ? { productIds: c } : {}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
S as buildLegacyMigrationPayload,
|
|
69
|
+
A as isLegacyStrategyConfig,
|
|
70
|
+
O as resolveMigrationTarget,
|
|
71
|
+
L as toMigrationFilterGroups
|
|
72
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ModificationDescription as f } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
2
|
import { RECOMMENDATION_ID_ATTR as m } from "../constants/selectors.js";
|
|
3
|
-
import { isPartnerManagedBlock as
|
|
4
|
-
import { RecommendationConfigService as
|
|
3
|
+
import { isPartnerManagedBlock as l, updateProductContentInPlace as a, regenerateProductRowsWithStyles as d } from "../controls/main/utils.js";
|
|
4
|
+
import { RecommendationConfigService as p } from "../services/configService.js";
|
|
5
5
|
let e = null;
|
|
6
|
-
function
|
|
6
|
+
function M(r) {
|
|
7
7
|
e = r;
|
|
8
8
|
}
|
|
9
|
-
function
|
|
9
|
+
function N(r, c, i, u) {
|
|
10
10
|
const n = e == null ? void 0 : e.getDocumentRootHtmlNode();
|
|
11
11
|
if (!e || !n || !("querySelector" in n))
|
|
12
12
|
return !1;
|
|
@@ -14,9 +14,9 @@ function D(r, c, i, u) {
|
|
|
14
14
|
if (!t)
|
|
15
15
|
return !1;
|
|
16
16
|
const o = e.getDocumentModifier();
|
|
17
|
-
return
|
|
17
|
+
return p.stageConfig(o, t, c), l(t) ? (o.apply(new f(u)), !0) : (a({ currentNode: t, documentModifier: o, products: i, forceApply: !0 }) || d({ currentNode: t, documentModifier: o, products: i, forceApply: !0 }), !0);
|
|
18
18
|
}
|
|
19
19
|
export {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
N as commitBlockChangeOutsidePanel,
|
|
21
|
+
M as registerNodeConfigWriter
|
|
22
22
|
};
|
|
@@ -1,43 +1,34 @@
|
|
|
1
|
-
const
|
|
1
|
+
const l = [
|
|
2
2
|
{
|
|
3
3
|
key: "locale",
|
|
4
4
|
getValue: (e) => e.language,
|
|
5
5
|
getAvailableOptions: (e) => Object.keys(e.languages)
|
|
6
6
|
},
|
|
7
|
-
{
|
|
8
|
-
// A block feeds from either an assigned strategy (RRS) or an algorithm (legacy).
|
|
9
|
-
// Only a fresh RRS block has neither, and its feed URL would otherwise be built
|
|
10
|
-
// from an empty algorithm path.
|
|
11
|
-
key: o,
|
|
12
|
-
getValue: (e) => e.strategyId || e.strategy
|
|
13
|
-
},
|
|
14
7
|
{
|
|
15
8
|
key: "currency",
|
|
16
9
|
getValue: (e) => e.currencySettings.value,
|
|
17
10
|
getAvailableOptions: (e) => e.currencyList.map((n) => n.text),
|
|
18
11
|
canBeEmpty: !0
|
|
19
12
|
}
|
|
20
|
-
],
|
|
21
|
-
function c(e, n, i =
|
|
13
|
+
], o = "newsletter.recommendation-fill-required-fields";
|
|
14
|
+
function c(e, n, i = l) {
|
|
22
15
|
return i.filter((t) => {
|
|
23
|
-
var
|
|
16
|
+
var u;
|
|
24
17
|
if (t.condition && !t.condition(e))
|
|
25
18
|
return !1;
|
|
26
|
-
const
|
|
27
|
-
if (t.canBeEmpty && (
|
|
19
|
+
const r = (u = t.getAvailableOptions) == null ? void 0 : u.call(t, n);
|
|
20
|
+
if (t.canBeEmpty && (r == null ? void 0 : r.length) === 0)
|
|
28
21
|
return !1;
|
|
29
|
-
const
|
|
30
|
-
return
|
|
22
|
+
const a = t.getValue(e);
|
|
23
|
+
return a ? r !== void 0 && !r.includes(a) : !0;
|
|
31
24
|
}).map((t) => t.key);
|
|
32
25
|
}
|
|
33
|
-
function
|
|
26
|
+
function s(e, n) {
|
|
34
27
|
return c(e, n).length === 0;
|
|
35
28
|
}
|
|
36
29
|
export {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
l as RecommendationRequiredFieldsKey,
|
|
40
|
-
o as STRATEGY_FIELD_KEY,
|
|
30
|
+
l as REQUIRED_RECOMMENDATION_FIELDS,
|
|
31
|
+
o as RecommendationRequiredFieldsKey,
|
|
41
32
|
c as getInvalidFields,
|
|
42
|
-
|
|
33
|
+
s as isConfigValid
|
|
43
34
|
};
|
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-1ca6baf0]{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-1ca6baf0]{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-17b3c665]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-17b3c665]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-17b3c665]{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-19d8cb42] .vueperslides__bullets,[data-v-1f4a4044] .vueperslides__bullets,[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-4019dc4d]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-4019dc4d] .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}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
|