@blaze-cms/react-page-builder 0.119.0 → 0.120.0-alpha.2
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/CHANGELOG.md +44 -0
- package/lib/components/Banner/AdSlotRender.js +23 -9
- package/lib/components/Banner/AdSlotRender.js.map +1 -1
- package/lib/components/Banner/Banner.js +24 -3
- package/lib/components/Banner/Banner.js.map +1 -1
- package/lib/components/Banner/BannerRender.js +7 -4
- package/lib/components/Banner/BannerRender.js.map +1 -1
- package/lib/components/Banner/helpers.js +66 -1
- package/lib/components/Banner/helpers.js.map +1 -1
- package/lib/components/BlazeLink.js +1 -0
- package/lib/components/BlazeLink.js.map +1 -1
- package/lib/components/Card/Card.js +1 -1
- package/lib/components/Card/Card.js.map +1 -1
- package/lib/components/Card/CardContainer.js +6 -2
- package/lib/components/Card/CardContainer.js.map +1 -1
- package/lib/components/Card/CardRender.js +27 -12
- package/lib/components/Card/CardRender.js.map +1 -1
- package/lib/components/Card/helpers/filter-query-setup.js +7 -3
- package/lib/components/Card/helpers/filter-query-setup.js.map +1 -1
- package/lib/components/Card/helpers/filters-setup.js +5 -16
- package/lib/components/Card/helpers/filters-setup.js.map +1 -1
- package/lib/components/List/ListBuilder.js +3 -3
- package/lib/components/List/ListBuilder.js.map +1 -1
- package/lib/helpers/build-props-query.js +15 -7
- package/lib/helpers/build-props-query.js.map +1 -1
- package/lib/helpers/get-entity-data.js +27 -5
- package/lib/helpers/get-entity-data.js.map +1 -1
- package/lib/helpers/get-generic-render-variables.js +29 -7
- package/lib/helpers/get-generic-render-variables.js.map +1 -1
- package/lib-es/components/Banner/AdSlotRender.js +23 -11
- package/lib-es/components/Banner/AdSlotRender.js.map +1 -1
- package/lib-es/components/Banner/Banner.js +22 -4
- package/lib-es/components/Banner/Banner.js.map +1 -1
- package/lib-es/components/Banner/BannerRender.js +8 -5
- package/lib-es/components/Banner/BannerRender.js.map +1 -1
- package/lib-es/components/Banner/helpers.js +52 -1
- package/lib-es/components/Banner/helpers.js.map +1 -1
- package/lib-es/components/BlazeLink.js +1 -0
- package/lib-es/components/BlazeLink.js.map +1 -1
- package/lib-es/components/Card/Card.js +1 -1
- package/lib-es/components/Card/Card.js.map +1 -1
- package/lib-es/components/Card/CardContainer.js +6 -2
- package/lib-es/components/Card/CardContainer.js.map +1 -1
- package/lib-es/components/Card/CardRender.js +19 -10
- package/lib-es/components/Card/CardRender.js.map +1 -1
- package/lib-es/components/Card/helpers/filter-query-setup.js +7 -3
- package/lib-es/components/Card/helpers/filter-query-setup.js.map +1 -1
- package/lib-es/components/Card/helpers/filters-setup.js +2 -7
- package/lib-es/components/Card/helpers/filters-setup.js.map +1 -1
- package/lib-es/components/List/ListBuilder.js +3 -3
- package/lib-es/components/List/ListBuilder.js.map +1 -1
- package/lib-es/helpers/build-props-query.js +11 -8
- package/lib-es/helpers/build-props-query.js.map +1 -1
- package/lib-es/helpers/get-entity-data.js +23 -5
- package/lib-es/helpers/get-entity-data.js.map +1 -1
- package/lib-es/helpers/get-generic-render-variables.js +28 -7
- package/lib-es/helpers/get-generic-render-variables.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Banner/AdSlotRender.js +11 -7
- package/src/components/Banner/Banner.js +13 -4
- package/src/components/Banner/BannerRender.js +6 -4
- package/src/components/Banner/helpers.js +49 -1
- package/src/components/BlazeLink.js +1 -0
- package/src/components/Card/Card.js +3 -5
- package/src/components/Card/CardContainer.js +6 -2
- package/src/components/Card/CardRender.js +15 -9
- package/src/components/Card/helpers/filter-query-setup.js +9 -3
- package/src/components/Card/helpers/filters-setup.js +2 -5
- package/src/components/List/ListBuilder.js +3 -3
- package/src/helpers/build-props-query.js +7 -10
- package/src/helpers/get-entity-data.js +12 -4
- package/src/helpers/get-generic-render-variables.js +30 -6
- package/tests/unit/src/components/Banner/AdSlotRender.test.js +4 -3
- package/tests/unit/src/components/Banner/__snapshots__/AdSlotRender.test.js.snap +10 -4
- package/tests/unit/src/components/List/components/Cards/__snapshots__/CardsRender.test.js.snap +18 -6
- package/tests/unit/src/helpers/build-props-query.test.js +28 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/helpers/get-generic-render-variables.js"],"names":["getSortbyFieldName","DEFAULT_LIMIT","DEFAULT_OFFSET","buildSortValues","sortFilters","relations","stringProps","length","sort","sortValues","map","propsToDisplay","sortFieldName","toLowerCase","filter","Boolean","join","getCorrectSort","filterProps","isTextSearchApplied","sortby","sortProperties","getGenericRenderVariables","
|
|
1
|
+
{"version":3,"sources":["../../src/helpers/get-generic-render-variables.js"],"names":["getSortbyFieldName","DEFAULT_LIMIT","DEFAULT_OFFSET","buildSortValues","sortFilters","relations","stringProps","length","sort","sortValues","map","propsToDisplay","sortFieldName","toLowerCase","filter","Boolean","join","getCorrectSort","filterProps","isTextSearchApplied","sortby","sortProperties","getGenericRenderVariables","rawQuery","isTextSearchFilterApplied","useRandomSort","limit","offset","limitToUse","Number","offsetToUse","rawQueryStringified","JSON","stringify","query","function_score","random_score","boost_mode"],"mappings":";;;;;;AAAA,OAAOA,kBAAP,MAA+B,0BAA/B;AACA,SAASC,aAAT,EAAwBC,cAAxB,QAA8C,cAA9C;;AAEA,MAAMC,eAAe,GAAG,CAACC,WAAD,EAAcC,SAAd,EAAyBC,WAAzB,KAAyC;AAC/D,MAAI,CAACF,WAAD,IAAgB,CAACA,WAAW,CAACG,MAAjC,EAAyC,OAAO;AAAEC,IAAAA,IAAI,EAAE;AAAR,GAAP;AAEzC,QAAMC,UAAU,GAAGL,WAAW,CAC3BM,GADgB,CACZ,CAAC;AAAEF,IAAAA,IAAF;AAAQG,IAAAA;AAAR,GAAD,KAA8B;AACjC,QAAI,CAACH,IAAL,EAAW,OAAO,IAAP;AAEX,UAAMI,aAAa,GAAGZ,kBAAkB,CAACK,SAAD,EAAYM,cAAZ,EAA4BL,WAA5B,CAAxC;AACA,WAAOM,aAAa,GAAI,GAAEA,aAAc,IAAGJ,IAAI,CAACK,WAAL,EAAmB,EAA1C,GAA8C,IAAlE;AACD,GANgB,EAOhBC,MAPgB,CAOTC,OAPS,EAQhBC,IARgB,CAQX,GARW,CAAnB;AAUA,SAAO;AAAER,IAAAA,IAAI,EAAEC;AAAR,GAAP;AACD,CAdD;;AAeA,MAAMQ,cAAc,GAAG,CAACZ,SAAD,EAAYa,WAAZ,EAAyBZ,WAAzB,EAAsCa,mBAAtC,KAA8D;AACnF,MAAIA,mBAAJ,EAAyB;AACvB,WAAO,EAAP;AACD;;AACD,QAAM;AAAEX,IAAAA,IAAF;AAAQY,IAAAA,MAAR;AAAgBC,IAAAA,cAAc,GAAG;AAAjC,MAAwCH,WAA9C;AAEA,SAAOf,eAAe,CACpB,CAAC;AAAEK,IAAAA,IAAF;AAAQG,IAAAA,cAAc,EAAES;AAAxB,GAAD,EAAmC,GAAGC,cAAtC,CADoB,EAEpBhB,SAFoB,EAGpBC,WAHoB,CAAtB;AAKD,CAXD;;AAaA,MAAMgB,yBAAyB,GAAG,CAChCjB,SADgC,EAEhCa,WAAW,GAAG,EAFkB,EAGhCZ,WAAW,GAAG,EAHkB,EAIhCiB,QAAQ,GAAG,EAJqB,EAKhCC,yBAAyB,GAAG,KALI,EAMhCC,aAAa,GAAG,KANgB,KAO7B;AACH,QAAM;AAAEC,IAAAA,KAAK,GAAGzB,aAAV;AAAyB0B,IAAAA;AAAzB,MAAoCT,WAA1C;AACA,QAAMU,UAAU,GAAGC,MAAM,CAACH,KAAK,IAAIzB,aAAV,CAAzB;AACA,QAAM6B,WAAW,GAAGD,MAAM,CAACF,MAAM,IAAIzB,cAAX,CAA1B;;AAEA,MAAIuB,aAAJ,EAAmB;AACjB,UAAMM,mBAAmB,GAAGC,IAAI,CAACC,SAAL,CAAe;AACzCC,MAAAA,KAAK,EAAE;AACLC,QAAAA,cAAc,EAAE;AACdD,UAAAA,KAAK,EAAEX,QADO;AAEda,UAAAA,YAAY,EAAE,EAFA;AAGdC,UAAAA,UAAU,EAAE;AAHE;AADX;AADkC,KAAf,CAA5B;AAUA,WAAO;AACLX,MAAAA,KAAK,EAAEE,UADF;AAELD,MAAAA,MAAM,EAAEG,WAFH;AAGLC,MAAAA;AAHK,KAAP;AAKD;;AAED,QAAMvB,IAAI,GAAGS,cAAc,CAACZ,SAAD,EAAYa,WAAZ,EAAyBZ,WAAzB,EAAsCkB,yBAAtC,CAA3B;AAEA;AACEE,IAAAA,KAAK,EAAEE,UADT;AAEED,IAAAA,MAAM,EAAEG;AAFV,KAGKtB,IAHL;AAIEuB,IAAAA,mBAAmB,EAAEC,IAAI,CAACC,SAAL,CAAe;AAClCC,MAAAA,KAAK,EAAEX;AAD2B,KAAf;AAJvB;AAQD,CAxCD;;AA0CA,eAAeD,yBAAf","sourcesContent":["import getSortbyFieldName from './get-sort-by-field-name';\nimport { DEFAULT_LIMIT, DEFAULT_OFFSET } from '../constants';\n\nconst buildSortValues = (sortFilters, relations, stringProps) => {\n if (!sortFilters || !sortFilters.length) return { sort: [] };\n\n const sortValues = sortFilters\n .map(({ sort, propsToDisplay }) => {\n if (!sort) return null;\n\n const sortFieldName = getSortbyFieldName(relations, propsToDisplay, stringProps);\n return sortFieldName ? `${sortFieldName}:${sort.toLowerCase()}` : null;\n })\n .filter(Boolean)\n .join(',');\n\n return { sort: sortValues };\n};\nconst getCorrectSort = (relations, filterProps, stringProps, isTextSearchApplied) => {\n if (isTextSearchApplied) {\n return {};\n }\n const { sort, sortby, sortProperties = [] } = filterProps;\n\n return buildSortValues(\n [{ sort, propsToDisplay: sortby }, ...sortProperties],\n relations,\n stringProps\n );\n};\n\nconst getGenericRenderVariables = (\n relations,\n filterProps = {},\n stringProps = [],\n rawQuery = {},\n isTextSearchFilterApplied = false,\n useRandomSort = false\n) => {\n const { limit = DEFAULT_LIMIT, offset } = filterProps;\n const limitToUse = Number(limit || DEFAULT_LIMIT);\n const offsetToUse = Number(offset || DEFAULT_OFFSET);\n\n if (useRandomSort) {\n const rawQueryStringified = JSON.stringify({\n query: {\n function_score: {\n query: rawQuery,\n random_score: {},\n boost_mode: 'replace'\n }\n }\n });\n\n return {\n limit: limitToUse,\n offset: offsetToUse,\n rawQueryStringified\n };\n }\n\n const sort = getCorrectSort(relations, filterProps, stringProps, isTextSearchFilterApplied);\n\n return {\n limit: limitToUse,\n offset: offsetToUse,\n ...sort,\n rawQueryStringified: JSON.stringify({\n query: rawQuery\n })\n };\n};\n\nexport default getGenericRenderVariables;\n"],"file":"get-generic-render-variables.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blaze-cms/react-page-builder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.120.0-alpha.2",
|
|
4
4
|
"description": "Blaze react page builder",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib-es/index.js",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"lib/*",
|
|
84
84
|
"lib-es/*"
|
|
85
85
|
],
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "4100a7f4e48face4e0e60c66ac6d095720436ef9"
|
|
87
87
|
}
|
|
@@ -11,7 +11,7 @@ const AdSlotRender = ({
|
|
|
11
11
|
parsedSizes,
|
|
12
12
|
targetingArguments
|
|
13
13
|
}) => {
|
|
14
|
-
const [loadingStatus, setLoadingStatus] = useState(
|
|
14
|
+
const [{ loadingStatus = BANNER_LOADING, minHeight }, setLoadingStatus] = useState({});
|
|
15
15
|
|
|
16
16
|
const bannerClass = `banner-${sizeId}`;
|
|
17
17
|
|
|
@@ -19,25 +19,29 @@ const AdSlotRender = ({
|
|
|
19
19
|
loadingStatus === BANNER_LOADING &&
|
|
20
20
|
sizeMapping
|
|
21
21
|
.map(({ sizes: styleSizes, viewport: [minWidth] }) => {
|
|
22
|
-
const
|
|
23
|
-
return `@media(min-width:${minWidth}px){.${bannerClass}{min-height:${
|
|
22
|
+
const minimumHeight = Math.min(...styleSizes.map(([, height]) => height));
|
|
23
|
+
return `@media(min-width:${minWidth}px){.${bannerClass}{min-height:${minimumHeight}px;}`;
|
|
24
24
|
})
|
|
25
25
|
.sort();
|
|
26
26
|
const className = `ad-slot ad-slot-${loadingStatus} ${bannerClass}`;
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
29
|
<>
|
|
30
|
-
{styles && <style>{styles}</style>}
|
|
31
|
-
<div className={className}>
|
|
30
|
+
{styles && <style>{styles.join('\n')}</style>}
|
|
31
|
+
<div className={className} style={{ minHeight }}>
|
|
32
32
|
{shouldShowBanner && (
|
|
33
33
|
<AdSlot
|
|
34
34
|
adUnit={parsedAdunit}
|
|
35
35
|
sizes={parsedSizes}
|
|
36
36
|
targetingArguments={targetingArguments}
|
|
37
37
|
sizeMapping={sizeMapping}
|
|
38
|
-
onSlotRender={
|
|
38
|
+
onSlotRender={slotData => {
|
|
39
|
+
const {
|
|
40
|
+
event: { isEmpty, size }
|
|
41
|
+
} = slotData;
|
|
42
|
+
const slotHeight = size && size.length ? size[1] : undefined;
|
|
39
43
|
const newLoadingStatus = isEmpty ? BANNER_EMPTY : BANNER_LOADED;
|
|
40
|
-
setLoadingStatus(newLoadingStatus);
|
|
44
|
+
setLoadingStatus({ loadingStatus: newLoadingStatus, minHeight: slotHeight });
|
|
41
45
|
}}
|
|
42
46
|
/>
|
|
43
47
|
)}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import { MainContext } from '@blaze-cms/nextjs-components';
|
|
3
|
+
import { checkIfLoggedIn } from '@blaze-cms/core-auth-ui';
|
|
3
4
|
import PropTypes from 'prop-types';
|
|
4
5
|
import flatten from 'lodash.flatten';
|
|
5
6
|
import { useQuery } from '@apollo/client';
|
|
6
7
|
import { useRouter } from 'next/router';
|
|
7
|
-
import {
|
|
8
|
+
import { buildUserQuery, buildUserPropsData } from './helpers';
|
|
9
|
+
import { getSingleEntitySchema, getUser } from '../../application/query';
|
|
8
10
|
import Wrapper from '../Wrapper';
|
|
9
11
|
import BannerRender from './BannerRender';
|
|
10
12
|
import buildPropsQuery from '../../helpers/build-props-query';
|
|
@@ -14,15 +16,20 @@ import getEntityRenderProps from '../../helpers/get-entity-render-props';
|
|
|
14
16
|
const Banner = ({ type, ...otherProps }) => {
|
|
15
17
|
const router = useRouter();
|
|
16
18
|
const { isPreview } = useContext(MainContext);
|
|
19
|
+
const { id: userId } = checkIfLoggedIn();
|
|
17
20
|
const { asPath } = router;
|
|
18
|
-
const { parent, entity, sizeId, propsToDisplay = [] } = otherProps;
|
|
19
|
-
|
|
21
|
+
const { parent, entity, sizeId, propsToDisplay = [], userPropsToDisplay = [] } = otherProps;
|
|
22
|
+
const userQuery = buildUserQuery(userPropsToDisplay);
|
|
20
23
|
const { itemEntity } = parent;
|
|
21
24
|
const { data, error, loading } = useQuery(getSingleEntitySchema, {
|
|
22
25
|
variables: { id: entity || itemEntity }
|
|
23
26
|
});
|
|
27
|
+
const { data: userData, loading: userLoading } = useQuery(getUser(userQuery), {
|
|
28
|
+
variables: { id: userId },
|
|
29
|
+
skip: !userPropsToDisplay.length || !userId
|
|
30
|
+
});
|
|
24
31
|
|
|
25
|
-
if (loading) return '';
|
|
32
|
+
if (loading || userLoading) return '';
|
|
26
33
|
if (error) return error.message;
|
|
27
34
|
if (!data) return null;
|
|
28
35
|
if (!sizeId) return null;
|
|
@@ -35,6 +42,7 @@ const Banner = ({ type, ...otherProps }) => {
|
|
|
35
42
|
: []
|
|
36
43
|
);
|
|
37
44
|
|
|
45
|
+
const userPropsData = buildUserPropsData(userData, userPropsToDisplay);
|
|
38
46
|
const { actionKey, action } = getEntityRenderProps(queryProps, data, isPreview);
|
|
39
47
|
const bannerKey = `${sizeId}${asPath}`;
|
|
40
48
|
|
|
@@ -46,6 +54,7 @@ const Banner = ({ type, ...otherProps }) => {
|
|
|
46
54
|
action={action}
|
|
47
55
|
actionKey={actionKey}
|
|
48
56
|
asPath={asPath}
|
|
57
|
+
userPropsData={userPropsData}
|
|
49
58
|
/>
|
|
50
59
|
</Wrapper>
|
|
51
60
|
);
|
|
@@ -33,6 +33,7 @@ const BannerRender = ({
|
|
|
33
33
|
action,
|
|
34
34
|
actionKey,
|
|
35
35
|
cardBannerIndex,
|
|
36
|
+
userPropsData,
|
|
36
37
|
...otherProps
|
|
37
38
|
}) => {
|
|
38
39
|
const { id } = otherProps;
|
|
@@ -63,7 +64,6 @@ const BannerRender = ({
|
|
|
63
64
|
});
|
|
64
65
|
|
|
65
66
|
const parsedTargetings = buildContextualTargeting(actionKey, entityRecordData, propsToDisplay);
|
|
66
|
-
|
|
67
67
|
const { entityData } = bannerData;
|
|
68
68
|
const { sizes: bannerSizes } = entityData || {};
|
|
69
69
|
|
|
@@ -81,7 +81,7 @@ const BannerRender = ({
|
|
|
81
81
|
|
|
82
82
|
const customTargetings = setCustomTargetings(targetings, cardBannerIndex);
|
|
83
83
|
|
|
84
|
-
const targetingArguments = { ...parsedTargetings, ...customTargetings };
|
|
84
|
+
const targetingArguments = { ...parsedTargetings, ...customTargetings, ...userPropsData };
|
|
85
85
|
|
|
86
86
|
return (
|
|
87
87
|
<AdSlotRender
|
|
@@ -107,7 +107,8 @@ BannerRender.propTypes = {
|
|
|
107
107
|
entity: PropTypes.string,
|
|
108
108
|
targetings: PropTypes.string,
|
|
109
109
|
sizes: PropTypes.string,
|
|
110
|
-
cardBannerIndex: PropTypes.number
|
|
110
|
+
cardBannerIndex: PropTypes.number,
|
|
111
|
+
userPropsData: PropTypes.object
|
|
111
112
|
};
|
|
112
113
|
|
|
113
114
|
BannerRender.defaultProps = {
|
|
@@ -118,7 +119,8 @@ BannerRender.defaultProps = {
|
|
|
118
119
|
entity: '',
|
|
119
120
|
targetings: '',
|
|
120
121
|
sizes: '',
|
|
121
|
-
cardBannerIndex: null
|
|
122
|
+
cardBannerIndex: null,
|
|
123
|
+
userPropsData: {}
|
|
122
124
|
};
|
|
123
125
|
|
|
124
126
|
export default withTitle(BannerRender);
|
|
@@ -135,6 +135,52 @@ const getMinBannerHeight = bannerSizes => {
|
|
|
135
135
|
return MIN_BANNER_HEIGHT;
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
+
const buildUserQuery = userProps => {
|
|
139
|
+
if (!userProps || !userProps.length) return '';
|
|
140
|
+
const basicProps = [];
|
|
141
|
+
const nestedProps = {};
|
|
142
|
+
userProps.forEach(({ propertiesToDisplay }) => {
|
|
143
|
+
const [propKey] = propertiesToDisplay;
|
|
144
|
+
if (!propKey || propKey === 'id') return;
|
|
145
|
+
if (propKey.indexOf('.') !== -1) {
|
|
146
|
+
const [baseProp, nestedProp] = propKey.split('.');
|
|
147
|
+
if (nestedProps[baseProp]) nestedProps[baseProp].push(nestedProp);
|
|
148
|
+
else nestedProps[baseProp] = [nestedProp];
|
|
149
|
+
} else basicProps.push(propKey);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
Object.keys(nestedProps).forEach(nestedKey => {
|
|
153
|
+
const nested = nestedProps[nestedKey];
|
|
154
|
+
basicProps.push(nestedKey);
|
|
155
|
+
basicProps.push('{');
|
|
156
|
+
nested.forEach(prop => basicProps.push(prop));
|
|
157
|
+
basicProps.push('}');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return basicProps.join(' ');
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const buildUserPropsData = (userData, userProps) => {
|
|
164
|
+
if (!userData || !userProps.length) return {};
|
|
165
|
+
const { getUser: user } = userData;
|
|
166
|
+
const propsWithData = {};
|
|
167
|
+
userProps.forEach(({ propertiesToDisplay, label }) => {
|
|
168
|
+
const [key] = propertiesToDisplay;
|
|
169
|
+
const parsedKey = key.split('.');
|
|
170
|
+
const value = getNestedValue(parsedKey, user);
|
|
171
|
+
const labelToUse = label || key;
|
|
172
|
+
if (value) propsWithData[labelToUse] = value;
|
|
173
|
+
});
|
|
174
|
+
return propsWithData;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const getNestedValue = (keys, object) => {
|
|
178
|
+
const key = keys.shift();
|
|
179
|
+
const nestedValue = object[key];
|
|
180
|
+
if (!nestedValue) return null;
|
|
181
|
+
return keys.length ? getNestedValue(keys, nestedValue) : nestedValue;
|
|
182
|
+
};
|
|
183
|
+
|
|
138
184
|
export {
|
|
139
185
|
getParsedSizes,
|
|
140
186
|
setCustomTargetings,
|
|
@@ -143,5 +189,7 @@ export {
|
|
|
143
189
|
buildContextualTargeting,
|
|
144
190
|
buildSizeMapping,
|
|
145
191
|
getMaxBannerHeight,
|
|
146
|
-
getMinBannerHeight
|
|
192
|
+
getMinBannerHeight,
|
|
193
|
+
buildUserPropsData,
|
|
194
|
+
buildUserQuery
|
|
147
195
|
};
|
|
@@ -7,6 +7,7 @@ const BlazeLink = ({ children, className, name, href, as, shallow, scroll, gtmId
|
|
|
7
7
|
const { hasGTM } = useContext(MainContext);
|
|
8
8
|
const gtmProps = hasGTM && !!gtmId ? { gtmId } : {};
|
|
9
9
|
const linkExtraProps = buildLinkExtraProps({ className, name, as, ...gtmProps });
|
|
10
|
+
if (!href) return children;
|
|
10
11
|
|
|
11
12
|
return (
|
|
12
13
|
<Link href={href} shallow={shallow} scroll={scroll} onClick={onClick} {...linkExtraProps}>
|
|
@@ -93,11 +93,9 @@ const Card = ({
|
|
|
93
93
|
))}
|
|
94
94
|
{displayTitle && (
|
|
95
95
|
<h2 className={getModifiers('card__title', modifiers)}>
|
|
96
|
-
{url
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</BlazeLink>
|
|
100
|
-
)}
|
|
96
|
+
<BlazeLink title={linkTitle} gtmId={gtmId} href={url} scroll>
|
|
97
|
+
{headline}
|
|
98
|
+
</BlazeLink>
|
|
101
99
|
</h2>
|
|
102
100
|
)}
|
|
103
101
|
{!!propsToDisplay.length && (
|
|
@@ -109,7 +109,9 @@ CardContainer.propTypes = {
|
|
|
109
109
|
itemsPerRow: PropTypes.number,
|
|
110
110
|
enableCarousel: PropTypes.bool,
|
|
111
111
|
bannerModifier: PropTypes.string,
|
|
112
|
-
priorityLimit: PropTypes.number
|
|
112
|
+
priorityLimit: PropTypes.number,
|
|
113
|
+
enableAutoScroll: PropTypes.bool,
|
|
114
|
+
autoScrollTimer: PropTypes.number
|
|
113
115
|
};
|
|
114
116
|
|
|
115
117
|
CardContainer.defaultProps = {
|
|
@@ -127,7 +129,9 @@ CardContainer.defaultProps = {
|
|
|
127
129
|
itemsPerRow: 1,
|
|
128
130
|
enableCarousel: false,
|
|
129
131
|
bannerModifier: '',
|
|
130
|
-
priorityLimit: 0
|
|
132
|
+
priorityLimit: 0,
|
|
133
|
+
enableAutoScroll: false,
|
|
134
|
+
autoScrollTimer: 0
|
|
131
135
|
};
|
|
132
136
|
|
|
133
137
|
export default withTitle(CardContainer);
|
|
@@ -22,6 +22,7 @@ import { filtersSetup, filterQuerySetup, shouldSkipSingleQuery, shouldReturn } f
|
|
|
22
22
|
const CardContainer = dynamic(() => import('./CardContainer'));
|
|
23
23
|
|
|
24
24
|
const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...otherProps }) => {
|
|
25
|
+
const { isPreview } = useContext(MainContext);
|
|
25
26
|
const {
|
|
26
27
|
parent: { itemId, itemEntity },
|
|
27
28
|
filterBy = [],
|
|
@@ -29,7 +30,8 @@ const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...otherPr
|
|
|
29
30
|
sortby,
|
|
30
31
|
sort,
|
|
31
32
|
sortProperties = [],
|
|
32
|
-
operator: filterOperator = AND
|
|
33
|
+
operator: filterOperator = AND,
|
|
34
|
+
useRandomSort
|
|
33
35
|
} = otherProps;
|
|
34
36
|
|
|
35
37
|
const updatedSortProperties = [...sortProperties];
|
|
@@ -55,14 +57,15 @@ const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...otherPr
|
|
|
55
57
|
entity
|
|
56
58
|
]);
|
|
57
59
|
|
|
58
|
-
const
|
|
59
|
-
const {
|
|
60
|
+
const schemas = Object.values(mainSchemas);
|
|
61
|
+
const currentSchema = schemas.find(({ identifier }) => identifier === itemEntityUpdated) || {};
|
|
62
|
+
const filterEntitySchema = schemas.find(({ id }) => entity === id) || {};
|
|
63
|
+
const { entityType, docType } = getEntityData(entity, filterEntitySchema);
|
|
64
|
+
|
|
60
65
|
const {
|
|
61
66
|
getAction,
|
|
62
67
|
queryProps,
|
|
63
68
|
inheritedFilters,
|
|
64
|
-
currentSchema,
|
|
65
|
-
filterEntitySchema,
|
|
66
69
|
entitySameAsCurrentItemEntity,
|
|
67
70
|
action,
|
|
68
71
|
filterEntityRelations
|
|
@@ -72,7 +75,8 @@ const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...otherPr
|
|
|
72
75
|
filterBy,
|
|
73
76
|
filterByProperty,
|
|
74
77
|
entity,
|
|
75
|
-
|
|
78
|
+
currentSchema,
|
|
79
|
+
filterEntitySchema,
|
|
76
80
|
isPreview,
|
|
77
81
|
itemEntityUpdated
|
|
78
82
|
});
|
|
@@ -111,12 +115,15 @@ const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...otherPr
|
|
|
111
115
|
filterOperator,
|
|
112
116
|
filterEntityRelations,
|
|
113
117
|
itemsToDisplay,
|
|
114
|
-
entitySameAsCurrentItemEntity
|
|
118
|
+
entitySameAsCurrentItemEntity,
|
|
119
|
+
useRandomSort
|
|
115
120
|
});
|
|
116
121
|
const { data, error: cardsError, loading: cardsLoading } = useQuery(action, {
|
|
117
122
|
variables,
|
|
123
|
+
fetchPolicy: useRandomSort ? 'cache-and-network' : 'cache-first',
|
|
118
124
|
skip: shouldReturn(!updatedFilterBy, _loading, _load, schemaLoading, _error, _err, schemaError)
|
|
119
125
|
});
|
|
126
|
+
|
|
120
127
|
const imageIds = itemsToDisplay.map(({ imageId }) => imageId).filter(Boolean);
|
|
121
128
|
const { data: imagesData, loading: imagesLoading } = useGetImages(imageIds, true);
|
|
122
129
|
const isLoading = shouldReturn(_loading, _load, schemaLoading, cardsLoading, imagesLoading);
|
|
@@ -126,11 +133,10 @@ const CardRender = ({ entity, entityFields, itemsToDisplay, children, ...otherPr
|
|
|
126
133
|
if (isLoading) return '';
|
|
127
134
|
if (hasError) return null;
|
|
128
135
|
if (cardsError) return cardsError.message;
|
|
129
|
-
|
|
130
136
|
let { results: cardData } = data[SEARCH_PUBLISHED_CONTENT];
|
|
131
137
|
if (!cardData || !cardData.length) return null;
|
|
132
138
|
cardData = entitySameAsCurrentItemEntity ? removeExtraItems(cardData, limit, itemId) : cardData;
|
|
133
|
-
const orderedData = sortResponseData(cardData, itemsToDisplay);
|
|
139
|
+
const orderedData = useRandomSort ? cardData : sortResponseData(cardData, itemsToDisplay);
|
|
134
140
|
const { regularChildren, gtmChildren } = splitChildren(children, cardData, entity, {
|
|
135
141
|
name: variableProps.name
|
|
136
142
|
});
|
|
@@ -11,7 +11,9 @@ const filterQuerySetup = ({
|
|
|
11
11
|
filterOperator,
|
|
12
12
|
filterEntityRelations,
|
|
13
13
|
itemsToDisplay,
|
|
14
|
-
entitySameAsCurrentItemEntity
|
|
14
|
+
entitySameAsCurrentItemEntity,
|
|
15
|
+
entitySchema,
|
|
16
|
+
useRandomSort
|
|
15
17
|
}) => {
|
|
16
18
|
const stringProps = getStringTypeProps(entity, filterEntityRelations, getEntitySchemas);
|
|
17
19
|
const filterValues =
|
|
@@ -27,7 +29,9 @@ const filterQuerySetup = ({
|
|
|
27
29
|
relations: filterEntityRelations,
|
|
28
30
|
stringProps,
|
|
29
31
|
itemsToDisplay,
|
|
30
|
-
addListFiltersToQuery: true
|
|
32
|
+
addListFiltersToQuery: true,
|
|
33
|
+
entity,
|
|
34
|
+
entitySchema
|
|
31
35
|
})
|
|
32
36
|
};
|
|
33
37
|
|
|
@@ -39,7 +43,9 @@ const filterQuerySetup = ({
|
|
|
39
43
|
filterEntityRelations,
|
|
40
44
|
{ ...variableProps, limit: requestLimit },
|
|
41
45
|
stringProps,
|
|
42
|
-
|
|
46
|
+
rawQuery,
|
|
47
|
+
false,
|
|
48
|
+
useRandomSort
|
|
43
49
|
);
|
|
44
50
|
|
|
45
51
|
return { variables, limit };
|
|
@@ -7,18 +7,15 @@ const filtersSetup = ({
|
|
|
7
7
|
filterBy,
|
|
8
8
|
filterByProperty,
|
|
9
9
|
entity,
|
|
10
|
-
|
|
10
|
+
currentSchema,
|
|
11
|
+
filterEntitySchema,
|
|
11
12
|
isPreview,
|
|
12
13
|
itemEntityUpdated
|
|
13
14
|
}) => {
|
|
14
15
|
const fields = buildQueryFields(entityFields, entityType);
|
|
15
16
|
const action = getSearchPublishedContent(fields);
|
|
16
17
|
const inheritedFilters = getInheritedFilters(filterBy, filterByProperty);
|
|
17
|
-
|
|
18
18
|
const entitySameAsCurrentItemEntity = itemEntityUpdated === entity;
|
|
19
|
-
const currentSchema =
|
|
20
|
-
getEntitySchemas.find(({ identifier }) => identifier === itemEntityUpdated) || {};
|
|
21
|
-
const filterEntitySchema = getEntitySchemas.find(({ id }) => entity === id) || {};
|
|
22
19
|
const { relations: filterEntityRelations = [] } = filterEntitySchema;
|
|
23
20
|
const queryProps = getQueryProps(inheritedFilters, currentSchema, filterEntitySchema);
|
|
24
21
|
const { actions = {} } = currentSchema || {};
|
|
@@ -62,7 +62,7 @@ const ListBuilder = props => {
|
|
|
62
62
|
const shouldApplyDefaultSort = !sortProperties || !sortProperties.length;
|
|
63
63
|
const itemsPerPageToUse = getItemsPerPageToUse(itemsPerPage, limitToUse);
|
|
64
64
|
const initialOffset = getCurrentOffset(offset, itemsPerPageToUse, paginationIndex, limitToUse);
|
|
65
|
-
const { entityType, docType } = getEntityData(entity);
|
|
65
|
+
const { entityType, docType } = getEntityData(entity, requiredSchema);
|
|
66
66
|
const fields = buildQueryFields(entityFields, entityType, !isCard);
|
|
67
67
|
const action = getSearchPublishedContent(fields);
|
|
68
68
|
const actionKey = SEARCH_PUBLISHED_CONTENT;
|
|
@@ -110,7 +110,7 @@ const ListBuilder = props => {
|
|
|
110
110
|
sortProperties
|
|
111
111
|
},
|
|
112
112
|
stringProps,
|
|
113
|
-
|
|
113
|
+
azRawQuery,
|
|
114
114
|
isTextSearchFilterApplied
|
|
115
115
|
);
|
|
116
116
|
|
|
@@ -153,7 +153,7 @@ const ListBuilder = props => {
|
|
|
153
153
|
sortProperties
|
|
154
154
|
},
|
|
155
155
|
stringProps,
|
|
156
|
-
|
|
156
|
+
rawQuery,
|
|
157
157
|
isTextSearchFilterApplied
|
|
158
158
|
);
|
|
159
159
|
|
|
@@ -59,7 +59,7 @@ const getTypeBaseProps = (data, cardOptions, extraPropsHaveCategory) => {
|
|
|
59
59
|
if (!isCard) return { typeBasedProps: [ID], shouldAddCategoryProps };
|
|
60
60
|
|
|
61
61
|
const { getEntitySchema } = data;
|
|
62
|
-
const { interfaces, properties, dynamicProperties } = getEntitySchema;
|
|
62
|
+
const { interfaces, properties, dynamicProperties, relations } = getEntitySchema;
|
|
63
63
|
|
|
64
64
|
const isContent = !!interfaces.includes('content/content');
|
|
65
65
|
const hasCategory = checkProps(properties) || checkProps(dynamicProperties);
|
|
@@ -68,19 +68,16 @@ const getTypeBaseProps = (data, cardOptions, extraPropsHaveCategory) => {
|
|
|
68
68
|
const typeBasedProps = [...defaultProps];
|
|
69
69
|
|
|
70
70
|
typeBasedProps.push(...getCategoyProps(shouldAddCategoryProps, hasCategory, hasPreheader));
|
|
71
|
-
typeBasedProps.push(...getContentProps(isContent
|
|
71
|
+
typeBasedProps.push(...getContentProps(isContent));
|
|
72
|
+
|
|
73
|
+
if (displayThumbnail && relations.find(({ localField }) => localField === 'image')) {
|
|
74
|
+
typeBasedProps.push('image.id', 'image.url', 'image.data');
|
|
75
|
+
}
|
|
72
76
|
|
|
73
77
|
return { typeBasedProps, shouldAddCategoryProps };
|
|
74
78
|
};
|
|
75
79
|
|
|
76
|
-
const getContentProps = (isContent,
|
|
77
|
-
if (!isContent) return [];
|
|
78
|
-
|
|
79
|
-
const props = ['url', 'sponsored', 'featured'];
|
|
80
|
-
if (displayThumbnail) props.push('image.id', 'image.url', 'image.data');
|
|
81
|
-
|
|
82
|
-
return props;
|
|
83
|
-
};
|
|
80
|
+
const getContentProps = isContent => (isContent ? ['url', 'sponsored', 'featured'] : []);
|
|
84
81
|
|
|
85
82
|
const getCategoyProps = (shouldAddCategoryProps, hasCategory, hasPreheader) => {
|
|
86
83
|
if (!shouldAddCategoryProps) return [];
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import upperFirst from 'lodash.upperfirst';
|
|
2
2
|
import camelcase from 'lodash.camelcase';
|
|
3
3
|
|
|
4
|
-
const getEntityData = entity => {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
4
|
+
const getEntityData = (entity, schema) => {
|
|
5
|
+
const publishedDocType = `published_${entity}`;
|
|
6
|
+
const publishedEntityType = `Published${upperFirst(camelcase(entity))}`;
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
if (schema) {
|
|
9
|
+
const { interfaces, [entity]: { interfaces: nestedInterfaces } = {} } = schema || {};
|
|
10
|
+
const interfacesToCheck = interfaces || nestedInterfaces;
|
|
11
|
+
if (interfacesToCheck && !interfacesToCheck.includes('publish/publishable')) {
|
|
12
|
+
return { docType: entity, entityType: upperFirst(camelcase(entity)) };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return { docType: publishedDocType, entityType: publishedEntityType };
|
|
9
17
|
};
|
|
10
18
|
|
|
11
19
|
export default getEntityData;
|
|
@@ -3,6 +3,7 @@ import { DEFAULT_LIMIT, DEFAULT_OFFSET } from '../constants';
|
|
|
3
3
|
|
|
4
4
|
const buildSortValues = (sortFilters, relations, stringProps) => {
|
|
5
5
|
if (!sortFilters || !sortFilters.length) return { sort: [] };
|
|
6
|
+
|
|
6
7
|
const sortValues = sortFilters
|
|
7
8
|
.map(({ sort, propsToDisplay }) => {
|
|
8
9
|
if (!sort) return null;
|
|
@@ -32,18 +33,41 @@ const getGenericRenderVariables = (
|
|
|
32
33
|
relations,
|
|
33
34
|
filterProps = {},
|
|
34
35
|
stringProps = [],
|
|
35
|
-
|
|
36
|
-
isTextSearchFilterApplied = false
|
|
36
|
+
rawQuery = {},
|
|
37
|
+
isTextSearchFilterApplied = false,
|
|
38
|
+
useRandomSort = false
|
|
37
39
|
) => {
|
|
38
40
|
const { limit = DEFAULT_LIMIT, offset } = filterProps;
|
|
41
|
+
const limitToUse = Number(limit || DEFAULT_LIMIT);
|
|
42
|
+
const offsetToUse = Number(offset || DEFAULT_OFFSET);
|
|
43
|
+
|
|
44
|
+
if (useRandomSort) {
|
|
45
|
+
const rawQueryStringified = JSON.stringify({
|
|
46
|
+
query: {
|
|
47
|
+
function_score: {
|
|
48
|
+
query: rawQuery,
|
|
49
|
+
random_score: {},
|
|
50
|
+
boost_mode: 'replace'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
limit: limitToUse,
|
|
57
|
+
offset: offsetToUse,
|
|
58
|
+
rawQueryStringified
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
39
62
|
const sort = getCorrectSort(relations, filterProps, stringProps, isTextSearchFilterApplied);
|
|
40
|
-
const raw = rawQueryStringified ? { rawQueryStringified } : {};
|
|
41
63
|
|
|
42
64
|
return {
|
|
43
|
-
limit:
|
|
44
|
-
offset:
|
|
65
|
+
limit: limitToUse,
|
|
66
|
+
offset: offsetToUse,
|
|
45
67
|
...sort,
|
|
46
|
-
|
|
68
|
+
rawQueryStringified: JSON.stringify({
|
|
69
|
+
query: rawQuery
|
|
70
|
+
})
|
|
47
71
|
};
|
|
48
72
|
};
|
|
49
73
|
|
|
@@ -9,8 +9,8 @@ jest.mock('react-dfp', () => {
|
|
|
9
9
|
<div
|
|
10
10
|
data-testid="adslot-test"
|
|
11
11
|
role="button"
|
|
12
|
-
onMouseLeave={() => onSlotRender({ event: { isEmpty: true } })}
|
|
13
|
-
onMouseOver={() => onSlotRender({ event: { isEmpty: false } })}
|
|
12
|
+
onMouseLeave={() => onSlotRender({ event: { isEmpty: true, size: null } })}
|
|
13
|
+
onMouseOver={() => onSlotRender({ event: { isEmpty: false, size: [970, 250] } })}
|
|
14
14
|
/>
|
|
15
15
|
);
|
|
16
16
|
return { AdSlot };
|
|
@@ -61,7 +61,7 @@ describe('Banner render component', () => {
|
|
|
61
61
|
expect(asFragment()).toMatchSnapshot();
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
it('should change class and remove styles after loaded events', async () => {
|
|
64
|
+
it('should change class and remove responsive styles after loaded events', async () => {
|
|
65
65
|
const { asFragment, container, getByTestId } = render(<AdSlotRender {...defaultProps} />);
|
|
66
66
|
const adSlot = getByTestId(slotTestId);
|
|
67
67
|
|
|
@@ -69,6 +69,7 @@ describe('Banner render component', () => {
|
|
|
69
69
|
await waitFor(() =>
|
|
70
70
|
expect(container.childNodes[0]).toHaveClass('ad-slot ad-slot-loaded banner-sizeId')
|
|
71
71
|
);
|
|
72
|
+
expect(container.childNodes[0]).toHaveStyle('min-height: 250px');
|
|
72
73
|
expect(asFragment()).toMatchSnapshot();
|
|
73
74
|
|
|
74
75
|
fireEvent.mouseLeave(adSlot);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
-
exports[`Banner render component AdSlot loading should change class and remove styles after loaded events 1`] = `
|
|
3
|
+
exports[`Banner render component AdSlot loading should change class and remove responsive styles after loaded events 1`] = `
|
|
4
4
|
<DocumentFragment>
|
|
5
5
|
<div
|
|
6
6
|
class="ad-slot ad-slot-loaded banner-sizeId"
|
|
7
|
+
style="min-height: 250px;"
|
|
7
8
|
>
|
|
8
9
|
<div
|
|
9
10
|
data-testid="adslot-test"
|
|
@@ -13,10 +14,11 @@ exports[`Banner render component AdSlot loading should change class and remove s
|
|
|
13
14
|
</DocumentFragment>
|
|
14
15
|
`;
|
|
15
16
|
|
|
16
|
-
exports[`Banner render component AdSlot loading should change class and remove styles after loaded events 2`] = `
|
|
17
|
+
exports[`Banner render component AdSlot loading should change class and remove responsive styles after loaded events 2`] = `
|
|
17
18
|
<DocumentFragment>
|
|
18
19
|
<div
|
|
19
20
|
class="ad-slot ad-slot-empty banner-sizeId"
|
|
21
|
+
style=""
|
|
20
22
|
>
|
|
21
23
|
<div
|
|
22
24
|
data-testid="adslot-test"
|
|
@@ -29,7 +31,9 @@ exports[`Banner render component AdSlot loading should change class and remove s
|
|
|
29
31
|
exports[`Banner render component AdSlot loading should render AdSlot 1`] = `
|
|
30
32
|
<DocumentFragment>
|
|
31
33
|
<style>
|
|
32
|
-
@media(min-width:320px){.banner-sizeId{min-height:100px;}
|
|
34
|
+
@media(min-width:320px){.banner-sizeId{min-height:100px;}
|
|
35
|
+
@media(min-width:728px){.banner-sizeId{min-height:100px;}
|
|
36
|
+
@media(min-width:970px){.banner-sizeId{min-height:250px;}
|
|
33
37
|
</style>
|
|
34
38
|
<div
|
|
35
39
|
class="ad-slot ad-slot-loading banner-sizeId"
|
|
@@ -45,7 +49,9 @@ exports[`Banner render component AdSlot loading should render AdSlot 1`] = `
|
|
|
45
49
|
exports[`Banner render component should not render AdSlot if shouldShowBanner=false but should render styles and wrapper 1`] = `
|
|
46
50
|
<DocumentFragment>
|
|
47
51
|
<style>
|
|
48
|
-
@media(min-width:320px){.banner-sizeId{min-height:100px;}
|
|
52
|
+
@media(min-width:320px){.banner-sizeId{min-height:100px;}
|
|
53
|
+
@media(min-width:728px){.banner-sizeId{min-height:100px;}
|
|
54
|
+
@media(min-width:970px){.banner-sizeId{min-height:250px;}
|
|
49
55
|
</style>
|
|
50
56
|
<div
|
|
51
57
|
class="ad-slot ad-slot-loading banner-sizeId"
|