@blaze-cms/react-page-builder 0.118.0 → 0.119.1

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 (180) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +22 -0
  3. package/lib/application/query/index.js +12 -12
  4. package/lib/application/query/index.js.map +1 -1
  5. package/lib/components/Banner/AdSlotRender.js +118 -0
  6. package/lib/components/Banner/AdSlotRender.js.map +1 -0
  7. package/lib/components/Banner/Banner.js +2 -2
  8. package/lib/components/Banner/Banner.js.map +1 -1
  9. package/lib/components/Banner/BannerRender.js +23 -33
  10. package/lib/components/Banner/BannerRender.js.map +1 -1
  11. package/lib/components/Button.js +2 -2
  12. package/lib/components/Button.js.map +1 -1
  13. package/lib/components/Card/CardContainer.js +6 -2
  14. package/lib/components/Card/CardContainer.js.map +1 -1
  15. package/lib/components/Card/CardFactory.js +2 -2
  16. package/lib/components/Card/CardFactory.js.map +1 -1
  17. package/lib/components/Card/CardRender.js +3 -3
  18. package/lib/components/Card/CardRender.js.map +1 -1
  19. package/lib/components/Card/helpers/filter-query-setup.js +7 -7
  20. package/lib/components/Card/helpers/filter-query-setup.js.map +1 -1
  21. package/lib/components/CarouselWrapper.js +54 -14
  22. package/lib/components/CarouselWrapper.js.map +1 -1
  23. package/lib/components/DataSummary/DataSummaryFactory.js +2 -2
  24. package/lib/components/DataSummary/DataSummaryFactory.js.map +1 -1
  25. package/lib/components/DataSummary/DataSummaryRender.js +2 -2
  26. package/lib/components/DataSummary/DataSummaryRender.js.map +1 -1
  27. package/lib/components/EmailConfirm/EmailConfirm.js +2 -2
  28. package/lib/components/EmailConfirm/EmailConfirm.js.map +1 -1
  29. package/lib/components/EmailConfirm/mutation.js +2 -2
  30. package/lib/components/EmailConfirm/mutation.js.map +1 -1
  31. package/lib/components/Image/ImageFactory.js +9 -5
  32. package/lib/components/Image/ImageFactory.js.map +1 -1
  33. package/lib/components/List/ListBuilder.js +21 -21
  34. package/lib/components/List/ListBuilder.js.map +1 -1
  35. package/lib/components/List/ListFactory.js +3 -3
  36. package/lib/components/List/ListFactory.js.map +1 -1
  37. package/lib/components/List/ListRender.js +2 -2
  38. package/lib/components/List/ListRender.js.map +1 -1
  39. package/lib/components/Login/LoggedInMessage.js +1 -1
  40. package/lib/components/Login/LoggedInMessage.js.map +1 -1
  41. package/lib/components/Login/Login.js +2 -2
  42. package/lib/components/Login/Login.js.map +1 -1
  43. package/lib/components/PasswordReset/PasswordReset.js +2 -2
  44. package/lib/components/PasswordReset/PasswordReset.js.map +1 -1
  45. package/lib/components/PasswordResetRequest/PasswordResetRequest.js +2 -2
  46. package/lib/components/PasswordResetRequest/PasswordResetRequest.js.map +1 -1
  47. package/lib/components/SearchFilter/SearchFilterContainer.js +2 -2
  48. package/lib/components/SearchFilter/SearchFilterContainer.js.map +1 -1
  49. package/lib/constants/index.js +8 -2
  50. package/lib/constants/index.js.map +1 -1
  51. package/lib/helpers/build-props-query.js +2 -2
  52. package/lib/helpers/build-props-query.js.map +1 -1
  53. package/lib/hooks/use-get-entity-schema.js +3 -3
  54. package/lib/hooks/use-get-entity-schema.js.map +1 -1
  55. package/lib/hooks/use-get-entity-schemas-as-obj.js +2 -2
  56. package/lib/hooks/use-get-entity-schemas-as-obj.js.map +1 -1
  57. package/lib/hooks/use-get-image-id-from-relation.js +2 -2
  58. package/lib/hooks/use-get-image-id-from-relation.js.map +1 -1
  59. package/lib/hooks/use-get-images.js +2 -2
  60. package/lib/hooks/use-get-images.js.map +1 -1
  61. package/lib/hooks/use-get-single-entity-schema.js +2 -2
  62. package/lib/hooks/use-get-single-entity-schema.js.map +1 -1
  63. package/lib-es/application/query/index.js +1 -5
  64. package/lib-es/application/query/index.js.map +1 -1
  65. package/lib-es/components/Banner/AdSlotRender.js +66 -0
  66. package/lib-es/components/Banner/AdSlotRender.js.map +1 -0
  67. package/lib-es/components/Banner/Banner.js +1 -1
  68. package/lib-es/components/Banner/Banner.js.map +1 -1
  69. package/lib-es/components/Banner/BannerRender.js +21 -29
  70. package/lib-es/components/Banner/BannerRender.js.map +1 -1
  71. package/lib-es/components/Button.js +1 -1
  72. package/lib-es/components/Button.js.map +1 -1
  73. package/lib-es/components/Card/CardContainer.js +7 -3
  74. package/lib-es/components/Card/CardContainer.js.map +1 -1
  75. package/lib-es/components/Card/CardFactory.js +1 -1
  76. package/lib-es/components/Card/CardFactory.js.map +1 -1
  77. package/lib-es/components/Card/CardRender.js +1 -1
  78. package/lib-es/components/Card/CardRender.js.map +1 -1
  79. package/lib-es/components/Card/helpers/filter-query-setup.js +1 -1
  80. package/lib-es/components/Card/helpers/filter-query-setup.js.map +1 -1
  81. package/lib-es/components/CarouselWrapper.js +50 -14
  82. package/lib-es/components/CarouselWrapper.js.map +1 -1
  83. package/lib-es/components/DataSummary/DataSummaryFactory.js +1 -1
  84. package/lib-es/components/DataSummary/DataSummaryFactory.js.map +1 -1
  85. package/lib-es/components/DataSummary/DataSummaryRender.js +1 -1
  86. package/lib-es/components/DataSummary/DataSummaryRender.js.map +1 -1
  87. package/lib-es/components/EmailConfirm/EmailConfirm.js +1 -1
  88. package/lib-es/components/EmailConfirm/EmailConfirm.js.map +1 -1
  89. package/lib-es/components/EmailConfirm/mutation.js +1 -1
  90. package/lib-es/components/EmailConfirm/mutation.js.map +1 -1
  91. package/lib-es/components/Image/ImageFactory.js +8 -4
  92. package/lib-es/components/Image/ImageFactory.js.map +1 -1
  93. package/lib-es/components/List/ListBuilder.js +2 -2
  94. package/lib-es/components/List/ListBuilder.js.map +1 -1
  95. package/lib-es/components/List/ListFactory.js +1 -1
  96. package/lib-es/components/List/ListFactory.js.map +1 -1
  97. package/lib-es/components/List/ListRender.js +1 -1
  98. package/lib-es/components/List/ListRender.js.map +1 -1
  99. package/lib-es/components/Login/LoggedInMessage.js +1 -1
  100. package/lib-es/components/Login/LoggedInMessage.js.map +1 -1
  101. package/lib-es/components/Login/Login.js +1 -1
  102. package/lib-es/components/Login/Login.js.map +1 -1
  103. package/lib-es/components/PasswordReset/PasswordReset.js +1 -1
  104. package/lib-es/components/PasswordReset/PasswordReset.js.map +1 -1
  105. package/lib-es/components/PasswordResetRequest/PasswordResetRequest.js +1 -1
  106. package/lib-es/components/PasswordResetRequest/PasswordResetRequest.js.map +1 -1
  107. package/lib-es/components/SearchFilter/SearchFilterContainer.js +1 -1
  108. package/lib-es/components/SearchFilter/SearchFilterContainer.js.map +1 -1
  109. package/lib-es/constants/index.js +4 -1
  110. package/lib-es/constants/index.js.map +1 -1
  111. package/lib-es/helpers/build-props-query.js +2 -2
  112. package/lib-es/helpers/build-props-query.js.map +1 -1
  113. package/lib-es/hooks/use-get-entity-schema.js +1 -1
  114. package/lib-es/hooks/use-get-entity-schema.js.map +1 -1
  115. package/lib-es/hooks/use-get-entity-schemas-as-obj.js +1 -1
  116. package/lib-es/hooks/use-get-entity-schemas-as-obj.js.map +1 -1
  117. package/lib-es/hooks/use-get-image-id-from-relation.js +1 -1
  118. package/lib-es/hooks/use-get-image-id-from-relation.js.map +1 -1
  119. package/lib-es/hooks/use-get-images.js +1 -1
  120. package/lib-es/hooks/use-get-images.js.map +1 -1
  121. package/lib-es/hooks/use-get-single-entity-schema.js +1 -1
  122. package/lib-es/hooks/use-get-single-entity-schema.js.map +1 -1
  123. package/package.json +7 -11
  124. package/src/application/query/index.js +1 -5
  125. package/src/components/Banner/AdSlotRender.js +66 -0
  126. package/src/components/Banner/Banner.js +1 -1
  127. package/src/components/Banner/BannerRender.js +22 -27
  128. package/src/components/Button.js +1 -1
  129. package/src/components/Card/CardContainer.js +5 -1
  130. package/src/components/Card/CardFactory.js +1 -1
  131. package/src/components/Card/CardRender.js +1 -1
  132. package/src/components/Card/helpers/filter-query-setup.js +1 -1
  133. package/src/components/CarouselWrapper.js +64 -19
  134. package/src/components/DataSummary/DataSummaryFactory.js +1 -1
  135. package/src/components/DataSummary/DataSummaryRender.js +1 -1
  136. package/src/components/EmailConfirm/EmailConfirm.js +1 -1
  137. package/src/components/EmailConfirm/mutation.js +1 -1
  138. package/src/components/Image/ImageFactory.js +10 -7
  139. package/src/components/List/ListBuilder.js +2 -2
  140. package/src/components/List/ListFactory.js +1 -1
  141. package/src/components/List/ListRender.js +1 -1
  142. package/src/components/Login/LoggedInMessage.js +1 -1
  143. package/src/components/Login/Login.js +1 -1
  144. package/src/components/PasswordReset/PasswordReset.js +1 -1
  145. package/src/components/PasswordResetRequest/PasswordResetRequest.js +1 -1
  146. package/src/components/SearchFilter/SearchFilterContainer.js +1 -1
  147. package/src/constants/index.js +6 -0
  148. package/src/helpers/build-props-query.js +2 -2
  149. package/src/hooks/use-get-entity-schema.js +1 -1
  150. package/src/hooks/use-get-entity-schemas-as-obj.js +1 -1
  151. package/src/hooks/use-get-image-id-from-relation.js +1 -1
  152. package/src/hooks/use-get-images.js +1 -1
  153. package/src/hooks/use-get-single-entity-schema.js +1 -1
  154. package/tests/unit/src/components/Banner/AdSlotRender.test.js +82 -0
  155. package/tests/unit/src/components/Banner/Banner.test.js +2 -1
  156. package/tests/unit/src/components/Banner/BannerRender.test.js +119 -0
  157. package/tests/unit/src/components/Banner/__snapshots__/AdSlotRender.test.js.snap +60 -0
  158. package/tests/unit/src/components/Banner/__snapshots__/BannerRender.test.js.snap +10 -0
  159. package/tests/unit/src/components/Button.test.js +2 -1
  160. package/tests/unit/src/components/Card/CardRender.test.js +1 -1
  161. package/tests/unit/src/components/Card/__snapshots__/CardContainer.test.js.snap +4 -4
  162. package/tests/unit/src/components/Carousel/Carousel.test.js +1 -1
  163. package/tests/unit/src/components/DataSummary/DataSummaryFactory.test.js +3 -2
  164. package/tests/unit/src/components/EmailConfirm/EmailConfirm.test.js +2 -1
  165. package/tests/unit/src/components/Image/GlobalLightbox/GlobalLightbox.test.js +10 -6
  166. package/tests/unit/src/components/Image/ImageFactory.test.js +11 -19
  167. package/tests/unit/src/components/Image/__snapshots__/ImageFactory.test.js.snap +34 -1
  168. package/tests/unit/src/components/Image/mocks.js +80 -24
  169. package/tests/unit/src/components/List/ListRender.test.js +2 -1
  170. package/tests/unit/src/components/Login/Login.test.js +2 -1
  171. package/tests/unit/src/components/PasswordReset/PasswordReset.test.js +2 -2
  172. package/tests/unit/src/components/PasswordResetRequest/PasswordResetRequest.test.js +2 -2
  173. package/tests/unit/src/components/SearchFilter/SearchFilterContainer.test.js +2 -1
  174. package/tests/unit/src/components/Video/providers/JWPlayer/JWPlayerProvider.test.js +1 -1
  175. package/tests/unit/src/components/__snapshots__/CarouselWrapper.test.js.snap +12 -12
  176. package/tests/unit/src/helpers/build-props-query.test.js +6 -6
  177. package/tests/unit/src/hooks/use-get-entity-schema-as-obj.test.js +2 -2
  178. package/tests/unit/src/hooks/use-get-image-id-from-relation.test.js +1 -1
  179. package/tests/unit/src/hooks/use-get-images.test.js +4 -14
  180. package/tests/unit/src/hooks/use-get-single-entity-schema.test.js +2 -4
@@ -1,4 +1,4 @@
1
- import { getStringTypeProps } from '@blaze-cms/utils';
1
+ import { getStringTypeProps } from '@blaze-cms/utils/src/helpers';
2
2
  import { getGenericRenderVariables, buildRawQueryBase, buildSetFilters } from '../../../helpers';
3
3
  import { DEFAULT_LIMIT } from '../../../constants';
4
4
 
@@ -2,17 +2,46 @@ import React, { useRef, useState, useEffect } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { FaAngleLeft, FaAngleRight } from 'react-icons/fa';
4
4
 
5
- const CarouselWrapper = ({ children, bannerModifier, itemsPerRow }) => {
5
+ const CarouselWrapper = ({
6
+ children,
7
+ bannerModifier,
8
+ itemsPerRow,
9
+ enableAutoScroll,
10
+ autoScrollTimer
11
+ }) => {
6
12
  const ref = useRef();
7
13
  const [buttonDisplay, setButtonDisplays] = useState({ displayLeft: false, displayRight: true });
14
+ const [shouldAutoScroll, setShouldAutoScroll] = useState(false);
15
+ const autoScrollRef = useRef();
8
16
 
9
- useEffect(() => {
10
- const {
11
- current: { offsetWidth, scrollWidth }
12
- } = ref;
17
+ useEffect(
18
+ () => {
19
+ autoScrollRef.current = shouldAutoScroll;
20
+ const id = setInterval(scrollCheck, autoScrollTimer);
21
+ function scrollCheck() {
22
+ if (!autoScrollRef.current) {
23
+ clearInterval(id);
24
+ } else {
25
+ handleButtonNavigation(true);
26
+ }
27
+ }
13
28
 
14
- if (scrollWidth <= offsetWidth) setButtonDisplays({ displayLeft: false, displayRight: false });
15
- }, []);
29
+ return () => clearInterval(id);
30
+ },
31
+ [autoScrollTimer, shouldAutoScroll]
32
+ );
33
+
34
+ useEffect(
35
+ () => {
36
+ const {
37
+ current: { offsetWidth, scrollWidth }
38
+ } = ref;
39
+ if (scrollWidth <= offsetWidth)
40
+ setButtonDisplays({ displayLeft: false, displayRight: false });
41
+ setShouldAutoScroll(enableAutoScroll);
42
+ },
43
+ [enableAutoScroll]
44
+ );
16
45
 
17
46
  const handleScroll = () => {
18
47
  const {
@@ -24,36 +53,48 @@ const CarouselWrapper = ({ children, bannerModifier, itemsPerRow }) => {
24
53
  };
25
54
 
26
55
  const handleButtonNavigation = direction => {
56
+ if (!ref || !ref.current) return;
27
57
  const {
28
- current: { offsetWidth, scrollLeft }
58
+ current: { offsetWidth, scrollLeft, scrollWidth }
29
59
  } = ref;
30
- ref.current.scrollLeft = direction ? scrollLeft + offsetWidth : scrollLeft - offsetWidth;
60
+
61
+ if (autoScrollRef.current && scrollLeft + offsetWidth >= scrollWidth) {
62
+ ref.current.scrollLeft = 0;
63
+ } else {
64
+ ref.current.scrollLeft = direction ? scrollLeft + offsetWidth : scrollLeft - offsetWidth;
65
+ }
31
66
  };
32
67
 
33
68
  const { displayLeft, displayRight } = buttonDisplay;
34
- const wrapperClassName = `card-carousel relative gap-2${bannerModifier}`;
35
- const contentClassName = `card-carousel__content card-carousel__content--items-per-row-${itemsPerRow} flex flex-nowrap p-4 gap-4 overflow-x-scroll`;
69
+ const wrapperClassName = `cards-carousel${bannerModifier}`;
70
+ const contentClassName = `cards-carousel--content items-per-row-${itemsPerRow}`;
36
71
 
37
72
  return (
38
73
  <div className={wrapperClassName}>
39
- <div className="card-carousel__button-wrapper absolute left-0 h-full flex justify-center items-center z-10">
74
+ <div className="cards-carousel--left-button-wrapper">
40
75
  {displayLeft && (
41
76
  <button
42
77
  type="button"
43
- className="card-carousel__button-back icon-button"
44
- onClick={() => handleButtonNavigation()}>
78
+ className="cards-carousel--button-back icon-button icon"
79
+ onClick={() => {
80
+ setShouldAutoScroll(false);
81
+ handleButtonNavigation();
82
+ }}>
45
83
  <i>
46
84
  <FaAngleLeft />
47
85
  </i>
48
86
  </button>
49
87
  )}
50
88
  </div>
51
- <div className="card-carousel__button-wrapper absolute right-0 h-full flex justify-center items-center z-10">
89
+ <div className="cards-carousel--right-button-wrapper">
52
90
  {displayRight && (
53
91
  <button
54
92
  type="button"
55
- className="card-carousel__button-forward icon-button icon"
56
- onClick={() => handleButtonNavigation(true)}>
93
+ className="cards-carousel--button-forward icon-button icon"
94
+ onClick={() => {
95
+ setShouldAutoScroll(false);
96
+ handleButtonNavigation(true);
97
+ }}>
57
98
  <i>
58
99
  <FaAngleRight />
59
100
  </i>
@@ -70,13 +111,17 @@ const CarouselWrapper = ({ children, bannerModifier, itemsPerRow }) => {
70
111
  CarouselWrapper.propTypes = {
71
112
  bannerModifier: PropTypes.string,
72
113
  itemsPerRow: PropTypes.number,
73
- children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
114
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
115
+ enableAutoScroll: PropTypes.bool,
116
+ autoScrollTimer: PropTypes.number
74
117
  };
75
118
 
76
119
  CarouselWrapper.defaultProps = {
77
120
  itemsPerRow: 0,
78
121
  bannerModifier: '',
79
- children: []
122
+ children: [],
123
+ enableAutoScroll: false,
124
+ autoScrollTimer: 0
80
125
  };
81
126
 
82
127
  export default CarouselWrapper;
@@ -1,5 +1,5 @@
1
1
  import React, { useContext } from 'react';
2
- import { useQuery } from '@apollo/react-hooks';
2
+ import { useQuery } from '@apollo/client';
3
3
  import PropTypes from 'prop-types';
4
4
  import { MainContext } from '@blaze-cms/nextjs-components';
5
5
  import { getSingleEntitySchema } from '../../application/query';
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { useQuery } from '@apollo/react-hooks';
2
+ import { useQuery } from '@apollo/client';
3
3
  import PropTypes from 'prop-types';
4
4
  import { summaryComponents } from './DataSummaryTypes';
5
5
  import { getClassModifiers } from '../../utils';
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { useMutation } from 'react-apollo';
3
+ import { useMutation } from '@apollo/client';
4
4
  import { useRouter } from 'next/router';
5
5
  import { parseUrl } from 'query-string';
6
6
  import EMAIL_CONFIRM_MUTATION from './mutation';
@@ -1,4 +1,4 @@
1
- import gql from 'graphql-tag';
1
+ import { gql } from '@apollo/client';
2
2
 
3
3
  const EMAIL_CONFIRM_MUTATION = gql`
4
4
  mutation confirmUserEmail($token: String!) {
@@ -17,7 +17,7 @@ const ImageFactory = props => {
17
17
  const isUsingRelationImage = checkIfUsingRelationImage(entity, fetchFromRelation, imageRelation);
18
18
  const { data: { getEntitySchema = {} } = {} } = useGetSingleEntitySchema(entity, !entity);
19
19
  const { actions = {} } = getEntitySchema;
20
- const { data: relationData } = useGetImageIdFromRelation(
20
+ const { data: relationData, loading: relationLoading } = useGetImageIdFromRelation(
21
21
  itemId,
22
22
  imageRelation,
23
23
  actions,
@@ -25,16 +25,19 @@ const ImageFactory = props => {
25
25
  isPreview
26
26
  );
27
27
 
28
- const updatedImageIds = getImageIds(imageRelation, relationData, imageId);
29
-
30
- const { data: { getFiles: files = [] } = {}, loading, error } = useGetImages(
31
- updatedImageIds,
32
- true
28
+ const updatedImageIds = relationLoading
29
+ ? null
30
+ : getImageIds(imageRelation, relationData, imageId);
31
+ const imageIds =
32
+ updatedImageIds && updatedImageIds.length === 1 ? updatedImageIds[0] : updatedImageIds;
33
+ const { data: { getFile, getFiles = [] } = {}, loading, error } = useGetImages(
34
+ imageIds,
35
+ updatedImageIds && updatedImageIds.length > 1
33
36
  );
34
-
35
37
  if (error) return error.message;
36
38
  if (loading) return '';
37
39
 
40
+ const files = getFile ? [getFile] : getFiles;
38
41
  return files.map(({ id, data: imageData = {}, url: imageUrl = '' }) => {
39
42
  if (!imageUrl) return null;
40
43
  return <Image key={id} {...props} imageData={imageData} imageUrl={imageUrl} />;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { useQuery } from '@apollo/react-hooks';
4
- import { getStringTypeProps } from '@blaze-cms/utils';
3
+ import { useQuery } from '@apollo/client';
4
+ import { getStringTypeProps } from '@blaze-cms/utils/src/helpers';
5
5
  import {
6
6
  CardRenderWithInfiniteScroll,
7
7
  CardsRender,
@@ -1,5 +1,5 @@
1
1
  import React, { useContext } from 'react';
2
- import { useQuery } from '@apollo/react-hooks';
2
+ import { useQuery } from '@apollo/client';
3
3
  import { parseUrl } from 'query-string';
4
4
  import PropTypes from 'prop-types';
5
5
  import { useRouter } from 'next/router';
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { useQuery } from '@apollo/react-hooks';
2
+ import { useQuery } from '@apollo/client';
3
3
  import PropTypes from 'prop-types';
4
4
  import ListPagination from './components/Pagination';
5
5
  import ListHeader from './components/Header';
@@ -17,7 +17,7 @@ const LoggedInMessage = ({ goToUrl, urlToUse }) => (
17
17
  );
18
18
 
19
19
  LoggedInMessage.propTypes = {
20
- goToUrl: PropTypes.string.isRequired,
20
+ goToUrl: PropTypes.func.isRequired,
21
21
  urlToUse: PropTypes.string.isRequired
22
22
  };
23
23
 
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from 'react';
2
2
  import { handleLogin, checkIfLoggedIn, LOGIN_MUTATION } from '@blaze-cms/core-auth-ui';
3
3
  import PropTypes from 'prop-types';
4
- import { useMutation } from 'react-apollo';
4
+ import { useMutation } from '@apollo/client';
5
5
  import { useRouter } from 'next/router';
6
6
  import { parseUrl } from 'query-string';
7
7
  import LoggedInMessage from './LoggedInMessage';
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import Input from '@blaze-react/input';
4
4
  import Button from '@blaze-react/button';
5
- import { useMutation } from 'react-apollo';
5
+ import { useMutation } from '@apollo/client';
6
6
  import { useRouter } from 'next/router';
7
7
  import { parseUrl } from 'query-string';
8
8
  import { RESET_USER_PASSWORD_MUTATION } from '@blaze-cms/core-auth-ui';
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import Input from '@blaze-react/input';
4
4
  import Button from '@blaze-react/button';
5
- import { useMutation } from 'react-apollo';
5
+ import { useMutation } from '@apollo/client';
6
6
  import { useRouter } from 'next/router';
7
7
  import { checkIfLoggedIn, REQUEST_USER_PASSWORD_RESET_MUTATION } from '@blaze-cms/core-auth-ui';
8
8
  import { GRAPH_QL_ERROR } from '../../constants';
@@ -1,6 +1,6 @@
1
1
  import React, { useState, useRef } from 'react';
2
2
  import { useRouter } from 'next/router';
3
- import { useQuery } from '@apollo/react-hooks';
3
+ import { useQuery } from '@apollo/client';
4
4
  import PropTypes from 'prop-types';
5
5
  import { parseUrl, stringify } from 'query-string';
6
6
  import SearchFilter from './SearchFilter';
@@ -194,10 +194,16 @@ const ALL_AZ_SORT = {
194
194
 
195
195
  const SCROLL_OFFSET = process.env.BLAZE_SCROLL_OFFSET || 50;
196
196
 
197
+ const BANNER_LOADING = 'loading';
198
+ const BANNER_EMPTY = 'empty';
199
+ const BANNER_LOADED = 'loaded';
197
200
  const ANCHOR_TAG = 'a';
198
201
  const TARGET_BLANK = '_blank';
199
202
 
200
203
  export {
204
+ BANNER_LOADING,
205
+ BANNER_EMPTY,
206
+ BANNER_LOADED,
201
207
  BLANK_SPACE_UNICODE_STRING,
202
208
  BOLD_TAG,
203
209
  BUTTON,
@@ -1,7 +1,7 @@
1
1
  import { CATEGORY_ID, ID, PREHEADER_PROP, HEADLINE_PROP } from '../constants';
2
2
 
3
3
  const defaultProps = [ID, 'name'];
4
- const categoryProps = 'publishedListingPage{url}';
4
+ const categoryProps = 'id publishedListingPage{id, url}';
5
5
 
6
6
  const checkProps = props =>
7
7
  !!(props && Object.keys(props).filter(prop => prop === CATEGORY_ID).length);
@@ -77,7 +77,7 @@ const getContentProps = (isContent, displayThumbnail) => {
77
77
  if (!isContent) return [];
78
78
 
79
79
  const props = ['url', 'sponsored', 'featured'];
80
- if (displayThumbnail) props.push('image.url', 'image.data');
80
+ if (displayThumbnail) props.push('image.id', 'image.url', 'image.data');
81
81
 
82
82
  return props;
83
83
  };
@@ -1,4 +1,4 @@
1
- import { useQuery, useApolloClient } from '@apollo/react-hooks';
1
+ import { useQuery, useApolloClient } from '@apollo/client';
2
2
  import { useState } from 'react';
3
3
  import { getEntitySchema } from '../application/query';
4
4
  import { ALL } from '../constants';
@@ -1,4 +1,4 @@
1
- import { useQuery } from '@apollo/react-hooks';
1
+ import { useQuery } from '@apollo/client';
2
2
  import { getMultipleSchema } from '../application/query';
3
3
 
4
4
  function useGetEntitySchemasAsObj(identifiers, shouldSkip = false) {
@@ -1,4 +1,4 @@
1
- import { useQuery } from '@apollo/react-hooks';
1
+ import { useQuery } from '@apollo/client';
2
2
  import { generateSingleItemQuery } from '../application/query';
3
3
 
4
4
  function useGetImageIdFromRelation(id, imageRelation, actions, isUsingRelationImage, isPreview) {
@@ -1,4 +1,4 @@
1
- import { useQuery } from '@apollo/react-hooks';
1
+ import { useQuery } from '@apollo/client';
2
2
  import { getFiles, getFileById } from '../application/query';
3
3
 
4
4
  function shouldSkip(id) {
@@ -1,4 +1,4 @@
1
- import { useQuery } from '@apollo/react-hooks';
1
+ import { useQuery } from '@apollo/client';
2
2
  import { getSingleEntitySchema } from '../application/query';
3
3
 
4
4
  const useGetSingleEntitySchema = (id, skip = false) => {
@@ -0,0 +1,82 @@
1
+ import React from 'react';
2
+ import '@testing-library/jest-dom/extend-expect';
3
+ import { render, fireEvent, waitFor } from '@testing-library/react';
4
+ import AdSlotRender from '../../../../../src/components/Banner/AdSlotRender';
5
+
6
+ jest.mock('react-dfp', () => {
7
+ const AdSlot = ({ onSlotRender }) => (
8
+ // eslint-disable-next-line jsx-a11y/mouse-events-have-key-events
9
+ <div
10
+ data-testid="adslot-test"
11
+ role="button"
12
+ onMouseLeave={() => onSlotRender({ event: { isEmpty: true, size: null } })}
13
+ onMouseOver={() => onSlotRender({ event: { isEmpty: false, size: [970, 250] } })}
14
+ />
15
+ );
16
+ return { AdSlot };
17
+ });
18
+
19
+ const slotTestId = 'adslot-test';
20
+ const sizeMapping = [
21
+ {
22
+ viewport: [970, 250],
23
+ sizes: [[970, 250], [970, 528]]
24
+ },
25
+ {
26
+ viewport: [320, 100],
27
+ sizes: [[320, 100]]
28
+ },
29
+ {
30
+ viewport: [728, 90],
31
+ sizes: [[320, 100]]
32
+ }
33
+ ];
34
+
35
+ const defaultProps = {
36
+ shouldShowBanner: true,
37
+ sizeMapping,
38
+ sizeId: 'sizeId',
39
+ parsedAdunit: 'unit-name',
40
+ parsedSizes: [],
41
+ targetingArguments: {}
42
+ };
43
+
44
+ describe('Banner render component', () => {
45
+ it('should not render AdSlot if shouldShowBanner=false but should render styles and wrapper', () => {
46
+ const { asFragment, container, getByTestId } = render(
47
+ <AdSlotRender {...defaultProps} shouldShowBanner={false} />
48
+ );
49
+
50
+ expect(container.childNodes[0].nodeName).toEqual('STYLE');
51
+ expect(container.childNodes[1]).toHaveClass('ad-slot ad-slot-loading banner-sizeId');
52
+ expect(() => getByTestId(slotTestId)).toThrow();
53
+ expect(asFragment()).toMatchSnapshot();
54
+ });
55
+
56
+ describe('AdSlot loading', () => {
57
+ it('should render AdSlot', () => {
58
+ const { asFragment, container, getByTestId } = render(<AdSlotRender {...defaultProps} />);
59
+ expect(getByTestId('adslot-test')).toBeDefined();
60
+ expect(container.childNodes[1]).toHaveClass('ad-slot ad-slot-loading banner-sizeId');
61
+ expect(asFragment()).toMatchSnapshot();
62
+ });
63
+
64
+ it('should change class and remove responsive styles after loaded events', async () => {
65
+ const { asFragment, container, getByTestId } = render(<AdSlotRender {...defaultProps} />);
66
+ const adSlot = getByTestId(slotTestId);
67
+
68
+ fireEvent.mouseOver(adSlot);
69
+ await waitFor(() =>
70
+ expect(container.childNodes[0]).toHaveClass('ad-slot ad-slot-loaded banner-sizeId')
71
+ );
72
+ expect(container.childNodes[0]).toHaveStyle('min-height: 250px');
73
+ expect(asFragment()).toMatchSnapshot();
74
+
75
+ fireEvent.mouseLeave(adSlot);
76
+ await waitFor(() =>
77
+ expect(container.childNodes[0]).toHaveClass('ad-slot ad-slot-empty banner-sizeId')
78
+ );
79
+ expect(asFragment()).toMatchSnapshot();
80
+ });
81
+ });
82
+ });
@@ -2,7 +2,8 @@ import '@testing-library/jest-dom/extend-expect';
2
2
  import { render } from '@blaze-cms/tools/test-helpers/test-functions';
3
3
  import Banner from '../../../../../src/components/Banner/Banner';
4
4
 
5
- jest.mock('@apollo/react-hooks', () => ({
5
+ jest.mock('@apollo/client', () => ({
6
+ ...jest.requireActual('@apollo/client'),
6
7
  useQuery: jest.fn(({ data, loading, error }) => ({ data, loading, error }))
7
8
  }));
8
9
  jest.mock('next/router', () => ({
@@ -0,0 +1,119 @@
1
+ import React from 'react';
2
+ import '@testing-library/jest-dom/extend-expect';
3
+ import { MockedProvider } from '@apollo/client/testing';
4
+ import { render } from '@testing-library/react';
5
+ import BannerRender from '../../../../../src/components/Banner/BannerRender';
6
+ import { getAction, generateSingleItemQuery, getCount } from '../../../../../src/application/query';
7
+ import {
8
+ BANNER_QUERY_PROPS,
9
+ COUNT_CONTENT_HIERARCHIES,
10
+ GET_BANNER,
11
+ PUBLISHED
12
+ } from '../../../../../src/constants';
13
+
14
+ const actionKey = 'getPublishedPage';
15
+ const id = 'record id';
16
+ const action = getAction(actionKey, 'id, name');
17
+ const getEntityDataMock = {
18
+ request: {
19
+ query: action,
20
+ variables: {
21
+ id
22
+ }
23
+ },
24
+ result: {
25
+ data: {
26
+ [actionKey]: {
27
+ id,
28
+ name: 'record name'
29
+ }
30
+ }
31
+ }
32
+ };
33
+
34
+ const sizeId = 'sizeId';
35
+ const sizes = [
36
+ {
37
+ width: 320,
38
+ height: 100,
39
+ viewports: [
40
+ {
41
+ width: 320,
42
+ height: 100
43
+ }
44
+ ]
45
+ }
46
+ ];
47
+ const getBannerMock = {
48
+ request: {
49
+ query: generateSingleItemQuery(GET_BANNER, BANNER_QUERY_PROPS),
50
+ variables: { id: sizeId },
51
+ skip: false
52
+ },
53
+ result: {
54
+ data: {
55
+ entityData: {
56
+ sizes,
57
+ id,
58
+ __typename: 'Banner'
59
+ }
60
+ }
61
+ }
62
+ };
63
+
64
+ const getCountMock = {
65
+ request: {
66
+ query: getCount(COUNT_CONTENT_HIERARCHIES),
67
+ variables: {
68
+ where: {
69
+ parentId: id,
70
+ childEntity: {
71
+ _ilike: `${PUBLISHED}_%`
72
+ }
73
+ }
74
+ }
75
+ },
76
+ result: {
77
+ data: {
78
+ entityData: {
79
+ sizes,
80
+ id,
81
+ __typename: 'Banner'
82
+ }
83
+ }
84
+ }
85
+ };
86
+
87
+ const mocks = [getEntityDataMock, getBannerMock, getCountMock];
88
+
89
+ const otherProps = { id };
90
+ const defaultProps = {
91
+ parent: {},
92
+ asPath: 'path',
93
+ action,
94
+ actionKey,
95
+ adunit: '',
96
+ baseAdunit: '',
97
+ sizeId,
98
+ propsToDisplay: [],
99
+ entity: '',
100
+ targetings: '',
101
+ sizes: '',
102
+ cardBannerIndex: null,
103
+ ...otherProps
104
+ };
105
+
106
+ const setup = (props = defaultProps) =>
107
+ render(
108
+ <MockedProvider mocks={mocks}>
109
+ <BannerRender {...props} />
110
+ </MockedProvider>
111
+ );
112
+
113
+ describe('Banner render component', () => {
114
+ it('should render', () => {
115
+ const { asFragment } = setup();
116
+
117
+ expect(asFragment()).toMatchSnapshot();
118
+ });
119
+ });
@@ -0,0 +1,60 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Banner render component AdSlot loading should change class and remove responsive styles after loaded events 1`] = `
4
+ <DocumentFragment>
5
+ <div
6
+ class="ad-slot ad-slot-loaded banner-sizeId"
7
+ style="min-height: 250px;"
8
+ >
9
+ <div
10
+ data-testid="adslot-test"
11
+ role="button"
12
+ />
13
+ </div>
14
+ </DocumentFragment>
15
+ `;
16
+
17
+ exports[`Banner render component AdSlot loading should change class and remove responsive styles after loaded events 2`] = `
18
+ <DocumentFragment>
19
+ <div
20
+ class="ad-slot ad-slot-empty banner-sizeId"
21
+ style=""
22
+ >
23
+ <div
24
+ data-testid="adslot-test"
25
+ role="button"
26
+ />
27
+ </div>
28
+ </DocumentFragment>
29
+ `;
30
+
31
+ exports[`Banner render component AdSlot loading should render AdSlot 1`] = `
32
+ <DocumentFragment>
33
+ <style>
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;}
37
+ </style>
38
+ <div
39
+ class="ad-slot ad-slot-loading banner-sizeId"
40
+ >
41
+ <div
42
+ data-testid="adslot-test"
43
+ role="button"
44
+ />
45
+ </div>
46
+ </DocumentFragment>
47
+ `;
48
+
49
+ exports[`Banner render component should not render AdSlot if shouldShowBanner=false but should render styles and wrapper 1`] = `
50
+ <DocumentFragment>
51
+ <style>
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;}
55
+ </style>
56
+ <div
57
+ class="ad-slot ad-slot-loading banner-sizeId"
58
+ />
59
+ </DocumentFragment>
60
+ `;
@@ -0,0 +1,10 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Banner render component should render 1`] = `
4
+ <DocumentFragment>
5
+ <style />
6
+ <div
7
+ class="ad-slot ad-slot-loading banner-sizeId"
8
+ />
9
+ </DocumentFragment>
10
+ `;
@@ -3,7 +3,8 @@ import { act, render } from '@testing-library/react';
3
3
  import '@testing-library/jest-dom/extend-expect';
4
4
  import Button from '../../../../src/components/Button';
5
5
 
6
- jest.mock('react-apollo', () => ({
6
+ jest.mock('@apollo/client', () => ({
7
+ ...jest.requireActual('@apollo/client'),
7
8
  useApolloClient: jest.fn(() => ({ resetStore: () => null }))
8
9
  }));
9
10
 
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import '@testing-library/jest-dom/extend-expect';
3
- import { MockedProvider } from '@apollo/react-testing';
3
+ import { MockedProvider } from '@apollo/client/testing';
4
4
  import { render, act } from '@testing-library/react';
5
5
  import {
6
6
  CARD_RENDER_ENTITY_DATA_MOCK,