@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.
Files changed (76) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/lib/components/Banner/AdSlotRender.js +23 -9
  3. package/lib/components/Banner/AdSlotRender.js.map +1 -1
  4. package/lib/components/Banner/Banner.js +24 -3
  5. package/lib/components/Banner/Banner.js.map +1 -1
  6. package/lib/components/Banner/BannerRender.js +7 -4
  7. package/lib/components/Banner/BannerRender.js.map +1 -1
  8. package/lib/components/Banner/helpers.js +66 -1
  9. package/lib/components/Banner/helpers.js.map +1 -1
  10. package/lib/components/BlazeLink.js +1 -0
  11. package/lib/components/BlazeLink.js.map +1 -1
  12. package/lib/components/Card/Card.js +1 -1
  13. package/lib/components/Card/Card.js.map +1 -1
  14. package/lib/components/Card/CardContainer.js +6 -2
  15. package/lib/components/Card/CardContainer.js.map +1 -1
  16. package/lib/components/Card/CardRender.js +27 -12
  17. package/lib/components/Card/CardRender.js.map +1 -1
  18. package/lib/components/Card/helpers/filter-query-setup.js +7 -3
  19. package/lib/components/Card/helpers/filter-query-setup.js.map +1 -1
  20. package/lib/components/Card/helpers/filters-setup.js +5 -16
  21. package/lib/components/Card/helpers/filters-setup.js.map +1 -1
  22. package/lib/components/List/ListBuilder.js +3 -3
  23. package/lib/components/List/ListBuilder.js.map +1 -1
  24. package/lib/helpers/build-props-query.js +15 -7
  25. package/lib/helpers/build-props-query.js.map +1 -1
  26. package/lib/helpers/get-entity-data.js +27 -5
  27. package/lib/helpers/get-entity-data.js.map +1 -1
  28. package/lib/helpers/get-generic-render-variables.js +29 -7
  29. package/lib/helpers/get-generic-render-variables.js.map +1 -1
  30. package/lib-es/components/Banner/AdSlotRender.js +23 -11
  31. package/lib-es/components/Banner/AdSlotRender.js.map +1 -1
  32. package/lib-es/components/Banner/Banner.js +22 -4
  33. package/lib-es/components/Banner/Banner.js.map +1 -1
  34. package/lib-es/components/Banner/BannerRender.js +8 -5
  35. package/lib-es/components/Banner/BannerRender.js.map +1 -1
  36. package/lib-es/components/Banner/helpers.js +52 -1
  37. package/lib-es/components/Banner/helpers.js.map +1 -1
  38. package/lib-es/components/BlazeLink.js +1 -0
  39. package/lib-es/components/BlazeLink.js.map +1 -1
  40. package/lib-es/components/Card/Card.js +1 -1
  41. package/lib-es/components/Card/Card.js.map +1 -1
  42. package/lib-es/components/Card/CardContainer.js +6 -2
  43. package/lib-es/components/Card/CardContainer.js.map +1 -1
  44. package/lib-es/components/Card/CardRender.js +19 -10
  45. package/lib-es/components/Card/CardRender.js.map +1 -1
  46. package/lib-es/components/Card/helpers/filter-query-setup.js +7 -3
  47. package/lib-es/components/Card/helpers/filter-query-setup.js.map +1 -1
  48. package/lib-es/components/Card/helpers/filters-setup.js +2 -7
  49. package/lib-es/components/Card/helpers/filters-setup.js.map +1 -1
  50. package/lib-es/components/List/ListBuilder.js +3 -3
  51. package/lib-es/components/List/ListBuilder.js.map +1 -1
  52. package/lib-es/helpers/build-props-query.js +11 -8
  53. package/lib-es/helpers/build-props-query.js.map +1 -1
  54. package/lib-es/helpers/get-entity-data.js +23 -5
  55. package/lib-es/helpers/get-entity-data.js.map +1 -1
  56. package/lib-es/helpers/get-generic-render-variables.js +28 -7
  57. package/lib-es/helpers/get-generic-render-variables.js.map +1 -1
  58. package/package.json +2 -2
  59. package/src/components/Banner/AdSlotRender.js +11 -7
  60. package/src/components/Banner/Banner.js +13 -4
  61. package/src/components/Banner/BannerRender.js +6 -4
  62. package/src/components/Banner/helpers.js +49 -1
  63. package/src/components/BlazeLink.js +1 -0
  64. package/src/components/Card/Card.js +3 -5
  65. package/src/components/Card/CardContainer.js +6 -2
  66. package/src/components/Card/CardRender.js +15 -9
  67. package/src/components/Card/helpers/filter-query-setup.js +9 -3
  68. package/src/components/Card/helpers/filters-setup.js +2 -5
  69. package/src/components/List/ListBuilder.js +3 -3
  70. package/src/helpers/build-props-query.js +7 -10
  71. package/src/helpers/get-entity-data.js +12 -4
  72. package/src/helpers/get-generic-render-variables.js +30 -6
  73. package/tests/unit/src/components/Banner/AdSlotRender.test.js +4 -3
  74. package/tests/unit/src/components/Banner/__snapshots__/AdSlotRender.test.js.snap +10 -4
  75. package/tests/unit/src/components/List/components/Cards/__snapshots__/CardsRender.test.js.snap +18 -6
  76. 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","rawQueryStringified","isTextSearchFilterApplied","limit","offset","raw","Number"],"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;AACzC,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,CAbD;;AAcA,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,mBAAmB,GAAG,EAJU,EAKhCC,yBAAyB,GAAG,KALI,KAM7B;AACH,QAAM;AAAEC,IAAAA,KAAK,GAAGxB,aAAV;AAAyByB,IAAAA;AAAzB,MAAoCR,WAA1C;AACA,QAAMV,IAAI,GAAGS,cAAc,CAACZ,SAAD,EAAYa,WAAZ,EAAyBZ,WAAzB,EAAsCkB,yBAAtC,CAA3B;AACA,QAAMG,GAAG,GAAGJ,mBAAmB,GAAG;AAAEA,IAAAA;AAAF,GAAH,GAA6B,EAA5D;AAEA;AACEE,IAAAA,KAAK,EAAEG,MAAM,CAACH,KAAK,IAAIxB,aAAV,CADf;AAEEyB,IAAAA,MAAM,EAAEE,MAAM,CAACF,MAAM,IAAIxB,cAAX;AAFhB,KAGKM,IAHL,GAIKmB,GAJL;AAMD,CAjBD;;AAmBA,eAAeL,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 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 rawQueryStringified = '',\n isTextSearchFilterApplied = false\n) => {\n const { limit = DEFAULT_LIMIT, offset } = filterProps;\n const sort = getCorrectSort(relations, filterProps, stringProps, isTextSearchFilterApplied);\n const raw = rawQueryStringified ? { rawQueryStringified } : {};\n\n return {\n limit: Number(limit || DEFAULT_LIMIT),\n offset: Number(offset || DEFAULT_OFFSET),\n ...sort,\n ...raw\n };\n};\n\nexport default getGenericRenderVariables;\n"],"file":"get-generic-render-variables.js"}
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.119.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": "2bbdbff965c620190bc67b5bae4b210041d44c0f"
86
+ "gitHead": "4100a7f4e48face4e0e60c66ac6d095720436ef9"
87
87
  }
@@ -11,7 +11,7 @@ const AdSlotRender = ({
11
11
  parsedSizes,
12
12
  targetingArguments
13
13
  }) => {
14
- const [loadingStatus, setLoadingStatus] = useState(BANNER_LOADING);
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 minHeight = Math.min(...styleSizes.map(([, height]) => height));
23
- return `@media(min-width:${minWidth}px){.${bannerClass}{min-height:${minHeight}px;}`;
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={({ event: { isEmpty } }) => {
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 { getSingleEntitySchema } from '../../application/query';
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
- <BlazeLink title={linkTitle} gtmId={gtmId} href={url} scroll>
98
- {headline}
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 { isPreview } = useContext(MainContext);
59
- const { entityType, docType } = getEntityData(entity);
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
- getEntitySchemas: Object.values(mainSchemas),
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
- JSON.stringify(rawQuery)
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
- getEntitySchemas,
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
- JSON.stringify(azRawQuery),
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
- JSON.stringify(rawQuery),
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, displayThumbnail));
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, displayThumbnail) => {
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 docType = `published_${entity}`;
6
- const entityType = `Published${upperFirst(camelcase(entity))}`;
4
+ const getEntityData = (entity, schema) => {
5
+ const publishedDocType = `published_${entity}`;
6
+ const publishedEntityType = `Published${upperFirst(camelcase(entity))}`;
7
7
 
8
- return { docType, entityType };
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
- rawQueryStringified = '',
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: Number(limit || DEFAULT_LIMIT),
44
- offset: Number(offset || DEFAULT_OFFSET),
65
+ limit: limitToUse,
66
+ offset: offsetToUse,
45
67
  ...sort,
46
- ...raw
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;}@media(min-width:728px){.banner-sizeId{min-height:100px;}@media(min-width:970px){.banner-sizeId{min-height:250px;}
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;}@media(min-width:728px){.banner-sizeId{min-height:100px;}@media(min-width:970px){.banner-sizeId{min-height:250px;}
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"