@builder.io/react 5.0.2-5 → 5.0.2-8
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/dist/builder-react-lite.cjs.js +1 -1
- package/dist/builder-react-lite.esm.js +1 -1
- package/dist/builder-react.browser.js +2 -2
- package/dist/builder-react.browser.js.map +1 -1
- package/dist/builder-react.cjs.js +1 -1
- package/dist/builder-react.cjs.js.map +1 -1
- package/dist/builder-react.es5.js +1 -1
- package/dist/builder-react.es5.js.map +1 -1
- package/dist/builder-react.unpkg.js +2 -2
- package/dist/builder-react.unpkg.js.map +1 -1
- package/dist/lib/package.json +1 -1
- package/dist/lib/src/blocks/PersonalizationContainer.js +10 -85
- package/dist/lib/src/blocks/PersonalizationContainer.js.map +1 -1
- package/dist/lib/src/functions/filter-with-custom-targeting.js +86 -0
- package/dist/lib/src/functions/filter-with-custom-targeting.js.map +1 -0
- package/dist/types/src/blocks/PersonalizationContainer.d.ts +2 -4
- package/dist/types/src/functions/filter-with-custom-targeting.d.ts +14 -0
- package/package.json +2 -2
- package/src/blocks/PersonalizationContainer.tsx +9 -104
- package/src/functions/filter-with-custom-targeting.ts +127 -0
package/dist/lib/package.json
CHANGED
|
@@ -14,14 +14,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
17
|
+
exports.PersonalizationContainer = void 0;
|
|
18
18
|
var react_1 = __importDefault(require("react"));
|
|
19
19
|
var sdk_1 = require("@builder.io/sdk");
|
|
20
20
|
var react_2 = require("react");
|
|
21
21
|
var builder_blocks_component_1 = require("../components/builder-blocks.component");
|
|
22
|
+
var filter_with_custom_targeting_1 = require("../functions/filter-with-custom-targeting");
|
|
22
23
|
function PersonalizationContainer(props) {
|
|
23
24
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
24
|
-
var _l = (0, react_2.useState)(
|
|
25
|
+
var _l = (0, react_2.useState)(!props.clientSideOnly), isClient = _l[0], setIsClient = _l[1];
|
|
25
26
|
var _m = (0, react_2.useState)(0), update = _m[0], setUpdate = _m[1];
|
|
26
27
|
(0, react_2.useEffect)(function () {
|
|
27
28
|
setIsClient(true);
|
|
@@ -35,7 +36,7 @@ function PersonalizationContainer(props) {
|
|
|
35
36
|
};
|
|
36
37
|
}, []);
|
|
37
38
|
var filteredVariants = (props.variants || []).filter(function (variant) {
|
|
38
|
-
return filterWithCustomTargeting(sdk_1.builder.getUserAttributes(), variant.query, variant.startDate, variant.endDate);
|
|
39
|
+
return (0, filter_with_custom_targeting_1.filterWithCustomTargeting)(sdk_1.builder.getUserAttributes(), variant.query, variant.startDate, variant.endDate);
|
|
39
40
|
});
|
|
40
41
|
return (react_1.default.createElement("div", __assign({}, props.attributes, { style: __assign({ opacity: isClient ? 1 : 0, transition: 'opacity 0.2s ease-in-out' }, (_a = props.attributes) === null || _a === void 0 ? void 0 : _a.style), className: "builder-personalization-container ".concat(props.attributes.className, " ").concat(isClient ? '' : 'builder-personalization-container-loading') }), sdk_1.Builder.isEditing &&
|
|
41
42
|
typeof props.previewingIndex === 'number' &&
|
|
@@ -47,88 +48,6 @@ function PersonalizationContainer(props) {
|
|
|
47
48
|
react_1.default.createElement(builder_blocks_component_1.BuilderBlocks, { blocks: (_h = filteredVariants[0]) === null || _h === void 0 ? void 0 : _h.blocks, parentElementId: (_j = props.builderBlock) === null || _j === void 0 ? void 0 : _j.id, dataPath: "component.options.variants.".concat((_k = props.variants) === null || _k === void 0 ? void 0 : _k.indexOf(filteredVariants[0]), ".blocks"), child: true }))));
|
|
48
49
|
}
|
|
49
50
|
exports.PersonalizationContainer = PersonalizationContainer;
|
|
50
|
-
function filterWithCustomTargeting(userAttributes, query, startDate, endDate) {
|
|
51
|
-
var item = {
|
|
52
|
-
query: query,
|
|
53
|
-
startDate: startDate,
|
|
54
|
-
endDate: endDate,
|
|
55
|
-
};
|
|
56
|
-
var now = (userAttributes.date && new Date(userAttributes.date)) || new Date();
|
|
57
|
-
if (item.startDate && new Date(item.startDate) > now) {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
else if (item.endDate && new Date(item.endDate) < now) {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
if (!item.query || !item.query.length) {
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
return item.query.every(function (filter) {
|
|
67
|
-
if (filter &&
|
|
68
|
-
filter.property === 'urlPath' &&
|
|
69
|
-
filter.value &&
|
|
70
|
-
typeof filter.value === 'string' &&
|
|
71
|
-
filter.value !== '/' &&
|
|
72
|
-
filter.value.endsWith('/')) {
|
|
73
|
-
filter.value = filter.value.slice(0, -1);
|
|
74
|
-
}
|
|
75
|
-
return objectMatchesQuery(userAttributes, filter);
|
|
76
|
-
});
|
|
77
|
-
function isNumber(val) {
|
|
78
|
-
return typeof val === 'number';
|
|
79
|
-
}
|
|
80
|
-
function isString(val) {
|
|
81
|
-
return typeof val === 'string';
|
|
82
|
-
}
|
|
83
|
-
function objectMatchesQuery(userattr, query) {
|
|
84
|
-
var result = (function () {
|
|
85
|
-
var property = query.property;
|
|
86
|
-
var operator = query.operator;
|
|
87
|
-
var testValue = query.value;
|
|
88
|
-
// Check is query property is present in userAttributes. Proceed only if it is present.
|
|
89
|
-
if (!(property && operator)) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
if (Array.isArray(testValue)) {
|
|
93
|
-
if (operator === 'isNot') {
|
|
94
|
-
return testValue.every(function (val) {
|
|
95
|
-
return objectMatchesQuery(userattr, { property: property, operator: operator, value: val });
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
return !!testValue.find(function (val) {
|
|
99
|
-
return objectMatchesQuery(userattr, { property: property, operator: operator, value: val });
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
var value = userattr[property];
|
|
103
|
-
if (Array.isArray(value)) {
|
|
104
|
-
return value.includes(testValue);
|
|
105
|
-
}
|
|
106
|
-
switch (operator) {
|
|
107
|
-
case 'is':
|
|
108
|
-
return value === testValue;
|
|
109
|
-
case 'isNot':
|
|
110
|
-
return value !== testValue;
|
|
111
|
-
case 'contains':
|
|
112
|
-
return (isString(value) || Array.isArray(value)) && value.includes(testValue);
|
|
113
|
-
case 'startsWith':
|
|
114
|
-
return isString(value) && value.startsWith(testValue);
|
|
115
|
-
case 'endsWith':
|
|
116
|
-
return isString(value) && value.endsWith(testValue);
|
|
117
|
-
case 'greaterThan':
|
|
118
|
-
return isNumber(value) && isNumber(testValue) && value > testValue;
|
|
119
|
-
case 'lessThan':
|
|
120
|
-
return isNumber(value) && isNumber(testValue) && value < testValue;
|
|
121
|
-
case 'greaterThanOrEqualTo':
|
|
122
|
-
return isNumber(value) && isNumber(testValue) && value >= testValue;
|
|
123
|
-
case 'lessThanOrEqualTo':
|
|
124
|
-
return isNumber(value) && isNumber(testValue) && value <= testValue;
|
|
125
|
-
}
|
|
126
|
-
return false;
|
|
127
|
-
})();
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
exports.filterWithCustomTargeting = filterWithCustomTargeting;
|
|
132
51
|
sdk_1.Builder.registerComponent(PersonalizationContainer, {
|
|
133
52
|
name: 'PersonalizationContainer',
|
|
134
53
|
noWrap: true,
|
|
@@ -147,6 +66,7 @@ sdk_1.Builder.registerComponent(PersonalizationContainer, {
|
|
|
147
66
|
},
|
|
148
67
|
{
|
|
149
68
|
name: 'query',
|
|
69
|
+
friendlyName: 'Targeting rules',
|
|
150
70
|
type: 'BuilderQuery',
|
|
151
71
|
defaultValue: [],
|
|
152
72
|
},
|
|
@@ -166,6 +86,11 @@ sdk_1.Builder.registerComponent(PersonalizationContainer, {
|
|
|
166
86
|
},
|
|
167
87
|
],
|
|
168
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: 'clientSideOnly',
|
|
91
|
+
type: 'boolean',
|
|
92
|
+
advanced: true,
|
|
93
|
+
}
|
|
169
94
|
],
|
|
170
95
|
});
|
|
171
96
|
//# sourceMappingURL=PersonalizationContainer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersonalizationContainer.js","sourceRoot":"","sources":["../../../../src/blocks/PersonalizationContainer.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,gDAA0B;AAC1B,uCAAmE;AACnE,+BAA4C;AAC5C,mFAAuE;
|
|
1
|
+
{"version":3,"file":"PersonalizationContainer.js","sourceRoot":"","sources":["../../../../src/blocks/PersonalizationContainer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.filterWithCustomTargeting = void 0;
|
|
4
|
+
function filterWithCustomTargeting(userAttributes, query, startDate, endDate) {
|
|
5
|
+
var item = {
|
|
6
|
+
query: query,
|
|
7
|
+
startDate: startDate,
|
|
8
|
+
endDate: endDate,
|
|
9
|
+
};
|
|
10
|
+
var now = (userAttributes.date && new Date(userAttributes.date)) || new Date();
|
|
11
|
+
if (item.startDate && new Date(item.startDate) > now) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
else if (item.endDate && new Date(item.endDate) < now) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (!item.query || !item.query.length) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return item.query.every(function (filter) {
|
|
21
|
+
return objectMatchesQuery(userAttributes, filter);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
exports.filterWithCustomTargeting = filterWithCustomTargeting;
|
|
25
|
+
function isString(val) {
|
|
26
|
+
return typeof val === 'string';
|
|
27
|
+
}
|
|
28
|
+
function isNumber(val) {
|
|
29
|
+
return typeof val === 'number';
|
|
30
|
+
}
|
|
31
|
+
function objectMatchesQuery(userattr, query) {
|
|
32
|
+
var result = (function () {
|
|
33
|
+
var property = query.property;
|
|
34
|
+
var operator = query.operator;
|
|
35
|
+
var testValue = query.value;
|
|
36
|
+
if (query &&
|
|
37
|
+
query.property === 'urlPath' &&
|
|
38
|
+
query.value &&
|
|
39
|
+
typeof query.value === 'string' &&
|
|
40
|
+
query.value !== '/' &&
|
|
41
|
+
query.value.endsWith('/')) {
|
|
42
|
+
testValue = query.value.slice(0, -1);
|
|
43
|
+
}
|
|
44
|
+
// Check is query property is present in userAttributes. Proceed only if it is present.
|
|
45
|
+
if (!(property && operator)) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(testValue)) {
|
|
49
|
+
if (operator === 'isNot') {
|
|
50
|
+
return testValue.every(function (val) {
|
|
51
|
+
return objectMatchesQuery(userattr, { property: property, operator: operator, value: val });
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return !!testValue.find(function (val) {
|
|
55
|
+
return objectMatchesQuery(userattr, { property: property, operator: operator, value: val });
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
var value = userattr[property];
|
|
59
|
+
if (Array.isArray(value)) {
|
|
60
|
+
return value.includes(testValue);
|
|
61
|
+
}
|
|
62
|
+
switch (operator) {
|
|
63
|
+
case 'is':
|
|
64
|
+
return value === testValue;
|
|
65
|
+
case 'isNot':
|
|
66
|
+
return value !== testValue;
|
|
67
|
+
case 'contains':
|
|
68
|
+
return (isString(value) || Array.isArray(value)) && value.includes(String(testValue));
|
|
69
|
+
case 'startsWith':
|
|
70
|
+
return isString(value) && value.startsWith(String(testValue));
|
|
71
|
+
case 'endsWith':
|
|
72
|
+
return isString(value) && value.endsWith(String(testValue));
|
|
73
|
+
case 'greaterThan':
|
|
74
|
+
return isNumber(value) && isNumber(testValue) && value > testValue;
|
|
75
|
+
case 'lessThan':
|
|
76
|
+
return isNumber(value) && isNumber(testValue) && value < testValue;
|
|
77
|
+
case 'greaterThanOrEqualTo':
|
|
78
|
+
return isNumber(value) && isNumber(testValue) && value >= testValue;
|
|
79
|
+
case 'lessThanOrEqualTo':
|
|
80
|
+
return isNumber(value) && isNumber(testValue) && value <= testValue;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
})();
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=filter-with-custom-targeting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-with-custom-targeting.js","sourceRoot":"","sources":["../../../../src/functions/filter-with-custom-targeting.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { BuilderElement } from '@builder.io/sdk';
|
|
3
|
-
|
|
4
|
-
type Query = any;
|
|
3
|
+
import { Query } from '../functions/filter-with-custom-targeting';
|
|
5
4
|
export type PersonalizationContainerProps = {
|
|
6
5
|
children: React.ReactNode;
|
|
7
6
|
previewingIndex: number | null;
|
|
@@ -15,7 +14,6 @@ export type PersonalizationContainerProps = {
|
|
|
15
14
|
}
|
|
16
15
|
];
|
|
17
16
|
attributes: any;
|
|
17
|
+
clientSideOnly?: boolean;
|
|
18
18
|
};
|
|
19
19
|
export declare function PersonalizationContainer(props: PersonalizationContainerProps): React.JSX.Element;
|
|
20
|
-
export declare function filterWithCustomTargeting(userAttributes: UserAttributes, query: Query[], startDate?: string, endDate?: string): boolean;
|
|
21
|
-
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type UserAttributes = {
|
|
2
|
+
date?: string | Date;
|
|
3
|
+
urlPath?: string;
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
};
|
|
6
|
+
type QueryOperator = 'is' | 'isNot' | 'contains' | 'startsWith' | 'endsWith' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqualTo' | 'lessThanOrEqualTo';
|
|
7
|
+
type QueryValue = string | number | boolean | Array<string | number | boolean>;
|
|
8
|
+
export type Query = {
|
|
9
|
+
property: string;
|
|
10
|
+
operator: QueryOperator;
|
|
11
|
+
value: QueryValue;
|
|
12
|
+
};
|
|
13
|
+
export declare function filterWithCustomTargeting(userAttributes: UserAttributes, query: Query[], startDate?: string, endDate?: string): boolean;
|
|
14
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builder.io/react",
|
|
3
|
-
"version": "5.0.2-
|
|
3
|
+
"version": "5.0.2-8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"main": "dist/builder-react.cjs.js",
|
|
@@ -107,5 +107,5 @@
|
|
|
107
107
|
"installConfig": {
|
|
108
108
|
"hoistingLimits": "workspaces"
|
|
109
109
|
},
|
|
110
|
-
"stableVersion": "5.0.2-
|
|
110
|
+
"stableVersion": "5.0.2-7"
|
|
111
111
|
}
|
|
@@ -2,9 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { Builder, builder, BuilderElement } from '@builder.io/sdk';
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
4
|
import { BuilderBlocks } from '../components/builder-blocks.component';
|
|
5
|
-
|
|
6
|
-
type UserAttributes = any;
|
|
7
|
-
type Query = any;
|
|
5
|
+
import { filterWithCustomTargeting, Query } from '../functions/filter-with-custom-targeting';
|
|
8
6
|
|
|
9
7
|
export type PersonalizationContainerProps = {
|
|
10
8
|
children: React.ReactNode;
|
|
@@ -19,10 +17,11 @@ export type PersonalizationContainerProps = {
|
|
|
19
17
|
},
|
|
20
18
|
];
|
|
21
19
|
attributes: any;
|
|
20
|
+
clientSideOnly?: boolean;
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
export function PersonalizationContainer(props: PersonalizationContainerProps) {
|
|
25
|
-
const [isClient, setIsClient] = useState(
|
|
24
|
+
const [isClient, setIsClient] = useState(!props.clientSideOnly);
|
|
26
25
|
const [update, setUpdate] = useState(0);
|
|
27
26
|
|
|
28
27
|
useEffect(() => {
|
|
@@ -94,106 +93,6 @@ export function PersonalizationContainer(props: PersonalizationContainerProps) {
|
|
|
94
93
|
);
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
export function filterWithCustomTargeting(
|
|
98
|
-
userAttributes: UserAttributes,
|
|
99
|
-
query: Query[],
|
|
100
|
-
startDate?: string,
|
|
101
|
-
endDate?: string
|
|
102
|
-
) {
|
|
103
|
-
const item = {
|
|
104
|
-
query,
|
|
105
|
-
startDate,
|
|
106
|
-
endDate,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const now = (userAttributes.date && new Date(userAttributes.date)) || new Date();
|
|
110
|
-
|
|
111
|
-
if (item.startDate && new Date(item.startDate) > now) {
|
|
112
|
-
return false;
|
|
113
|
-
} else if (item.endDate && new Date(item.endDate) < now) {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (!item.query || !item.query.length) {
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return item.query.every((filter: Query) => {
|
|
122
|
-
if (
|
|
123
|
-
filter &&
|
|
124
|
-
filter.property === 'urlPath' &&
|
|
125
|
-
filter.value &&
|
|
126
|
-
typeof filter.value === 'string' &&
|
|
127
|
-
filter.value !== '/' &&
|
|
128
|
-
filter.value.endsWith('/')
|
|
129
|
-
) {
|
|
130
|
-
filter.value = filter.value.slice(0, -1);
|
|
131
|
-
}
|
|
132
|
-
return objectMatchesQuery(userAttributes, filter);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
function isNumber(val: unknown) {
|
|
136
|
-
return typeof val === 'number';
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function isString(val: unknown) {
|
|
140
|
-
return typeof val === 'string';
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function objectMatchesQuery(userattr: UserAttributes, query: Query): boolean {
|
|
144
|
-
const result = (() => {
|
|
145
|
-
const property = query.property;
|
|
146
|
-
const operator = query.operator;
|
|
147
|
-
const testValue = query.value;
|
|
148
|
-
|
|
149
|
-
// Check is query property is present in userAttributes. Proceed only if it is present.
|
|
150
|
-
if (!(property && operator)) {
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (Array.isArray(testValue)) {
|
|
155
|
-
if (operator === 'isNot') {
|
|
156
|
-
return testValue.every(val =>
|
|
157
|
-
objectMatchesQuery(userattr, { property, operator, value: val })
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
return !!testValue.find(val =>
|
|
161
|
-
objectMatchesQuery(userattr, { property, operator, value: val })
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
const value = userattr[property];
|
|
165
|
-
|
|
166
|
-
if (Array.isArray(value)) {
|
|
167
|
-
return value.includes(testValue);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
switch (operator) {
|
|
171
|
-
case 'is':
|
|
172
|
-
return value === testValue;
|
|
173
|
-
case 'isNot':
|
|
174
|
-
return value !== testValue;
|
|
175
|
-
case 'contains':
|
|
176
|
-
return (isString(value) || Array.isArray(value)) && value.includes(testValue);
|
|
177
|
-
case 'startsWith':
|
|
178
|
-
return isString(value) && value.startsWith(testValue);
|
|
179
|
-
case 'endsWith':
|
|
180
|
-
return isString(value) && value.endsWith(testValue);
|
|
181
|
-
case 'greaterThan':
|
|
182
|
-
return isNumber(value) && isNumber(testValue) && value > testValue;
|
|
183
|
-
case 'lessThan':
|
|
184
|
-
return isNumber(value) && isNumber(testValue) && value < testValue;
|
|
185
|
-
case 'greaterThanOrEqualTo':
|
|
186
|
-
return isNumber(value) && isNumber(testValue) && value >= testValue;
|
|
187
|
-
case 'lessThanOrEqualTo':
|
|
188
|
-
return isNumber(value) && isNumber(testValue) && value <= testValue;
|
|
189
|
-
}
|
|
190
|
-
return false;
|
|
191
|
-
})();
|
|
192
|
-
|
|
193
|
-
return result;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
96
|
Builder.registerComponent(PersonalizationContainer, {
|
|
198
97
|
name: 'PersonalizationContainer',
|
|
199
98
|
noWrap: true,
|
|
@@ -213,6 +112,7 @@ Builder.registerComponent(PersonalizationContainer, {
|
|
|
213
112
|
},
|
|
214
113
|
{
|
|
215
114
|
name: 'query',
|
|
115
|
+
friendlyName: 'Targeting rules',
|
|
216
116
|
type: 'BuilderQuery',
|
|
217
117
|
defaultValue: [],
|
|
218
118
|
},
|
|
@@ -232,5 +132,10 @@ Builder.registerComponent(PersonalizationContainer, {
|
|
|
232
132
|
},
|
|
233
133
|
],
|
|
234
134
|
},
|
|
135
|
+
{
|
|
136
|
+
name: 'clientSideOnly',
|
|
137
|
+
type: 'boolean',
|
|
138
|
+
advanced: true,
|
|
139
|
+
}
|
|
235
140
|
],
|
|
236
141
|
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
type UserAttributes = {
|
|
2
|
+
date?: string | Date;
|
|
3
|
+
urlPath?: string;
|
|
4
|
+
[key: string]: any; // Allow any other properties
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// Query type
|
|
8
|
+
type QueryOperator =
|
|
9
|
+
| 'is'
|
|
10
|
+
| 'isNot'
|
|
11
|
+
| 'contains'
|
|
12
|
+
| 'startsWith'
|
|
13
|
+
| 'endsWith'
|
|
14
|
+
| 'greaterThan'
|
|
15
|
+
| 'lessThan'
|
|
16
|
+
| 'greaterThanOrEqualTo'
|
|
17
|
+
| 'lessThanOrEqualTo';
|
|
18
|
+
|
|
19
|
+
type QueryValue = string | number | boolean | Array<string | number | boolean>;
|
|
20
|
+
|
|
21
|
+
export type Query = {
|
|
22
|
+
property: string;
|
|
23
|
+
operator: QueryOperator;
|
|
24
|
+
value: QueryValue;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function filterWithCustomTargeting(
|
|
28
|
+
userAttributes: UserAttributes,
|
|
29
|
+
query: Query[],
|
|
30
|
+
startDate?: string,
|
|
31
|
+
endDate?: string
|
|
32
|
+
) {
|
|
33
|
+
const item = {
|
|
34
|
+
query,
|
|
35
|
+
startDate,
|
|
36
|
+
endDate,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const now = (userAttributes.date && new Date(userAttributes.date)) || new Date();
|
|
40
|
+
|
|
41
|
+
if (item.startDate && new Date(item.startDate) > now) {
|
|
42
|
+
return false;
|
|
43
|
+
} else if (item.endDate && new Date(item.endDate) < now) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!item.query || !item.query.length) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return item.query.every((filter: Query) => {
|
|
52
|
+
return objectMatchesQuery(userAttributes, filter);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isString(val: unknown): val is string {
|
|
57
|
+
return typeof val === 'string';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isNumber(val: unknown): val is number {
|
|
61
|
+
return typeof val === 'number';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function objectMatchesQuery(userattr: UserAttributes, query: Query): boolean {
|
|
65
|
+
const result = (() => {
|
|
66
|
+
const property = query.property;
|
|
67
|
+
const operator = query.operator;
|
|
68
|
+
let testValue = query.value;
|
|
69
|
+
|
|
70
|
+
if (
|
|
71
|
+
query &&
|
|
72
|
+
query.property === 'urlPath' &&
|
|
73
|
+
query.value &&
|
|
74
|
+
typeof query.value === 'string' &&
|
|
75
|
+
query.value !== '/' &&
|
|
76
|
+
query.value.endsWith('/')
|
|
77
|
+
) {
|
|
78
|
+
testValue = query.value.slice(0, -1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
// Check is query property is present in userAttributes. Proceed only if it is present.
|
|
83
|
+
if (!(property && operator)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (Array.isArray(testValue)) {
|
|
88
|
+
if (operator === 'isNot') {
|
|
89
|
+
return testValue.every(val =>
|
|
90
|
+
objectMatchesQuery(userattr, { property, operator, value: val })
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
return !!testValue.find(val =>
|
|
94
|
+
objectMatchesQuery(userattr, { property, operator, value: val })
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const value = userattr[property];
|
|
98
|
+
|
|
99
|
+
if (Array.isArray(value)) {
|
|
100
|
+
return value.includes(testValue);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
switch (operator) {
|
|
104
|
+
case 'is':
|
|
105
|
+
return value === testValue;
|
|
106
|
+
case 'isNot':
|
|
107
|
+
return value !== testValue;
|
|
108
|
+
case 'contains':
|
|
109
|
+
return (isString(value) || Array.isArray(value)) && value.includes(String(testValue));
|
|
110
|
+
case 'startsWith':
|
|
111
|
+
return isString(value) && value.startsWith(String(testValue));
|
|
112
|
+
case 'endsWith':
|
|
113
|
+
return isString(value) && value.endsWith(String(testValue));
|
|
114
|
+
case 'greaterThan':
|
|
115
|
+
return isNumber(value) && isNumber(testValue) && value > testValue;
|
|
116
|
+
case 'lessThan':
|
|
117
|
+
return isNumber(value) && isNumber(testValue) && value < testValue;
|
|
118
|
+
case 'greaterThanOrEqualTo':
|
|
119
|
+
return isNumber(value) && isNumber(testValue) && value >= testValue;
|
|
120
|
+
case 'lessThanOrEqualTo':
|
|
121
|
+
return isNumber(value) && isNumber(testValue) && value <= testValue;
|
|
122
|
+
}
|
|
123
|
+
return false;
|
|
124
|
+
})();
|
|
125
|
+
|
|
126
|
+
return result;
|
|
127
|
+
}
|