@blaze-cms/react-page-builder 0.146.0-alpha.2 → 0.146.0-alpha.21
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 +132 -0
- package/lib/components/Card/Card.js +14 -9
- package/lib/components/Card/Card.js.map +1 -1
- package/lib/components/Card/CardsContainer.js +8 -4
- package/lib/components/Card/CardsContainer.js.map +1 -1
- package/lib/components/Card/CardsFactory.js +37 -7
- package/lib/components/Card/CardsFactory.js.map +1 -1
- package/lib/components/Card/CardsRender.js +8 -4
- package/lib/components/Card/CardsRender.js.map +1 -1
- package/lib/components/Card/helpers/index.js +6 -6
- package/lib/components/Card/helpers/index.js.map +1 -1
- package/lib/components/Image/Lightbox/Lightbox.js +2 -2
- package/lib/components/Image/Lightbox/Lightbox.js.map +1 -1
- package/lib/components/List/ListRender.js.map +1 -1
- package/lib/components/MenuItem/MenuEntitiesItem.js +204 -0
- package/lib/components/MenuItem/MenuEntitiesItem.js.map +1 -0
- package/lib/components/MenuItem/MenuItem.js +25 -68
- package/lib/components/MenuItem/MenuItem.js.map +1 -1
- package/lib/components/MenuItem/MenuItemRender.js +104 -0
- package/lib/components/MenuItem/MenuItemRender.js.map +1 -0
- package/lib/components/MenuItem/helpers/index.js +15 -0
- package/lib/components/MenuItem/helpers/index.js.map +1 -0
- package/lib/components/MenuItem/helpers/inject-helper-into-template.js +17 -0
- package/lib/components/MenuItem/helpers/inject-helper-into-template.js.map +1 -0
- package/lib/components/Modal/Modal.js +2 -2
- package/lib/components/Modal/Modal.js.map +1 -1
- package/lib/components/ModalAdapter/ModalAdapter.js +21 -0
- package/lib/components/ModalAdapter/ModalAdapter.js.map +1 -0
- package/lib/components/ModalAdapter/index.js +11 -0
- package/lib/components/ModalAdapter/index.js.map +1 -0
- package/lib/components/SearchFilter/SearchFilter/SearchFilter.js +22 -4
- package/lib/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
- package/lib/components/SearchFilter/SearchFilterContainer.js +22 -27
- package/lib/components/SearchFilter/SearchFilterContainer.js.map +1 -1
- package/lib/components/SearchFilter/components/Select.js.map +1 -1
- package/lib/components/SearchFilter/helpers/build-list-name-query.js +31 -0
- package/lib/components/SearchFilter/helpers/build-list-name-query.js.map +1 -0
- package/lib/components/SearchFilter/helpers/decode-encode.js.map +1 -1
- package/lib/components/SearchFilter/helpers/index.js +7 -0
- package/lib/components/SearchFilter/helpers/index.js.map +1 -1
- package/lib/components/Video/Video.js +2 -1
- package/lib/components/Video/Video.js.map +1 -1
- package/lib/components/Video/VideoContext.js +12 -0
- package/lib/components/Video/VideoContext.js.map +1 -0
- package/lib/components/Video/VideoModal.js +2 -2
- package/lib/components/Video/VideoModal.js.map +1 -1
- package/lib/components/Video/VideoRender.js +36 -3
- package/lib/components/Video/VideoRender.js.map +1 -1
- package/lib/components/Video/constants.js +14 -0
- package/lib/components/Video/constants.js.map +1 -0
- package/lib/components/Video/helpers/emit-gtm-event.js +31 -0
- package/lib/components/Video/helpers/emit-gtm-event.js.map +1 -0
- package/lib/components/Video/providers/JWPlayer/JWPlayerController.js +28 -8
- package/lib/components/Video/providers/JWPlayer/JWPlayerController.js.map +1 -1
- package/lib/components/Video/providers/JWPlayer/JWPlayerProvider.js +16 -4
- package/lib/components/Video/providers/JWPlayer/JWPlayerProvider.js.map +1 -1
- package/lib/components/Video/providers/YouTube/YoutubeEmbeded.js +57 -0
- package/lib/components/Video/providers/YouTube/YoutubeEmbeded.js.map +1 -1
- package/lib/helpers/build-filters-query.js +1 -2
- package/lib/helpers/build-filters-query.js.map +1 -1
- package/lib/{components/Card/helpers → helpers}/filter-query-setup.js +10 -7
- package/lib/helpers/filter-query-setup.js.map +1 -0
- package/lib/{components/Card/helpers → helpers}/filters-setup.js +8 -5
- package/lib/helpers/filters-setup.js.map +1 -0
- package/lib/helpers/get-updated-items-to-display.js.map +1 -0
- package/lib/helpers/get-updated-sort-properties.js.map +1 -0
- package/lib/helpers/index.js +42 -0
- package/lib/helpers/index.js.map +1 -1
- package/lib/helpers/should-return.js.map +1 -0
- package/lib/{components/Card/helpers → helpers}/should-skip-single-query.js +1 -1
- package/lib/helpers/should-skip-single-query.js.map +1 -0
- package/lib/hooks/index.js +14 -0
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/use-filter-aggregation-values.js +54 -0
- package/lib/hooks/use-filter-aggregation-values.js.map +1 -0
- package/lib/hooks/use-portal.js +30 -0
- package/lib/hooks/use-portal.js.map +1 -0
- package/lib-es/components/Card/Card.js +14 -9
- package/lib-es/components/Card/Card.js.map +1 -1
- package/lib-es/components/Card/CardsContainer.js +9 -5
- package/lib-es/components/Card/CardsContainer.js.map +1 -1
- package/lib-es/components/Card/CardsFactory.js +40 -9
- package/lib-es/components/Card/CardsFactory.js.map +1 -1
- package/lib-es/components/Card/CardsRender.js +9 -5
- package/lib-es/components/Card/CardsRender.js.map +1 -1
- package/lib-es/components/Card/helpers/index.js +6 -6
- package/lib-es/components/Card/helpers/index.js.map +1 -1
- package/lib-es/components/Image/Lightbox/Lightbox.js +1 -1
- package/lib-es/components/Image/Lightbox/Lightbox.js.map +1 -1
- package/lib-es/components/List/ListRender.js.map +1 -1
- package/lib-es/components/MenuItem/MenuEntitiesItem.js +178 -0
- package/lib-es/components/MenuItem/MenuEntitiesItem.js.map +1 -0
- package/lib-es/components/MenuItem/MenuItem.js +28 -57
- package/lib-es/components/MenuItem/MenuItem.js.map +1 -1
- package/lib-es/components/MenuItem/MenuItemRender.js +84 -0
- package/lib-es/components/MenuItem/MenuItemRender.js.map +1 -0
- package/lib-es/components/MenuItem/helpers/index.js +3 -0
- package/lib-es/components/MenuItem/helpers/index.js.map +1 -0
- package/lib-es/components/MenuItem/helpers/inject-helper-into-template.js +8 -0
- package/lib-es/components/MenuItem/helpers/inject-helper-into-template.js.map +1 -0
- package/lib-es/components/Modal/Modal.js +1 -1
- package/lib-es/components/Modal/Modal.js.map +1 -1
- package/lib-es/components/ModalAdapter/ModalAdapter.js +13 -0
- package/lib-es/components/ModalAdapter/ModalAdapter.js.map +1 -0
- package/lib-es/components/ModalAdapter/index.js +3 -0
- package/lib-es/components/ModalAdapter/index.js.map +1 -0
- package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js +15 -4
- package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
- package/lib-es/components/SearchFilter/SearchFilterContainer.js +23 -20
- package/lib-es/components/SearchFilter/SearchFilterContainer.js.map +1 -1
- package/lib-es/components/SearchFilter/components/Select.js.map +1 -1
- package/lib-es/components/SearchFilter/helpers/build-list-name-query.js +15 -0
- package/lib-es/components/SearchFilter/helpers/build-list-name-query.js.map +1 -0
- package/lib-es/components/SearchFilter/helpers/decode-encode.js.map +1 -1
- package/lib-es/components/SearchFilter/helpers/index.js +2 -1
- package/lib-es/components/SearchFilter/helpers/index.js.map +1 -1
- package/lib-es/components/Video/Video.js +2 -1
- package/lib-es/components/Video/Video.js.map +1 -1
- package/lib-es/components/Video/VideoContext.js +6 -0
- package/lib-es/components/Video/VideoContext.js.map +1 -0
- package/lib-es/components/Video/VideoModal.js +1 -1
- package/lib-es/components/Video/VideoModal.js.map +1 -1
- package/lib-es/components/Video/VideoRender.js +28 -3
- package/lib-es/components/Video/VideoRender.js.map +1 -1
- package/lib-es/components/Video/constants.js +7 -0
- package/lib-es/components/Video/constants.js.map +1 -0
- package/lib-es/components/Video/helpers/emit-gtm-event.js +25 -0
- package/lib-es/components/Video/helpers/emit-gtm-event.js.map +1 -0
- package/lib-es/components/Video/providers/JWPlayer/JWPlayerController.js +28 -4
- package/lib-es/components/Video/providers/JWPlayer/JWPlayerController.js.map +1 -1
- package/lib-es/components/Video/providers/JWPlayer/JWPlayerProvider.js +10 -4
- package/lib-es/components/Video/providers/JWPlayer/JWPlayerProvider.js.map +1 -1
- package/lib-es/components/Video/providers/YouTube/YoutubeEmbeded.js +60 -2
- package/lib-es/components/Video/providers/YouTube/YoutubeEmbeded.js.map +1 -1
- package/lib-es/helpers/build-filters-query.js +1 -2
- package/lib-es/helpers/build-filters-query.js.map +1 -1
- package/lib-es/{components/Card/helpers → helpers}/filter-query-setup.js +5 -3
- package/lib-es/helpers/filter-query-setup.js.map +1 -0
- package/lib-es/{components/Card/helpers → helpers}/filters-setup.js +4 -2
- package/lib-es/helpers/filters-setup.js.map +1 -0
- package/lib-es/helpers/get-updated-items-to-display.js.map +1 -0
- package/lib-es/helpers/get-updated-sort-properties.js.map +1 -0
- package/lib-es/helpers/index.js +6 -0
- package/lib-es/helpers/index.js.map +1 -1
- package/lib-es/helpers/should-return.js.map +1 -0
- package/lib-es/{components/Card/helpers → helpers}/should-skip-single-query.js +1 -1
- package/lib-es/helpers/should-skip-single-query.js.map +1 -0
- package/lib-es/hooks/index.js +2 -0
- package/lib-es/hooks/index.js.map +1 -1
- package/lib-es/hooks/use-filter-aggregation-values.js +31 -0
- package/lib-es/hooks/use-filter-aggregation-values.js.map +1 -0
- package/lib-es/hooks/use-portal.js +14 -0
- package/lib-es/hooks/use-portal.js.map +1 -0
- package/package.json +7 -7
- package/src/components/Card/Card.js +25 -16
- package/src/components/Card/CardsContainer.js +7 -3
- package/src/components/Card/CardsFactory.js +34 -6
- package/src/components/Card/CardsRender.js +6 -2
- package/src/components/Card/helpers/index.js +6 -6
- package/src/components/Image/Lightbox/Lightbox.js +1 -1
- package/src/components/List/ListRender.js +0 -1
- package/src/components/MenuItem/MenuEntitiesItem.js +204 -0
- package/src/components/MenuItem/MenuItem.js +15 -58
- package/src/components/MenuItem/MenuItemRender.js +92 -0
- package/src/components/MenuItem/helpers/index.js +3 -0
- package/src/components/MenuItem/helpers/inject-helper-into-template.js +11 -0
- package/src/components/Modal/Modal.js +1 -1
- package/src/components/ModalAdapter/ModalAdapter.js +12 -0
- package/src/components/ModalAdapter/index.js +3 -0
- package/src/components/SearchFilter/SearchFilter/SearchFilter.js +16 -5
- package/src/components/SearchFilter/SearchFilterContainer.js +21 -22
- package/src/components/SearchFilter/components/Select.js +2 -0
- package/src/components/SearchFilter/helpers/build-list-name-query.js +18 -0
- package/src/components/SearchFilter/helpers/decode-encode.js +0 -1
- package/src/components/SearchFilter/helpers/index.js +2 -0
- package/src/components/Video/Video.js +1 -1
- package/src/components/Video/VideoContext.js +7 -0
- package/src/components/Video/VideoModal.js +1 -1
- package/src/components/Video/VideoRender.js +28 -3
- package/src/components/Video/constants.js +6 -0
- package/src/components/Video/helpers/emit-gtm-event.js +25 -0
- package/src/components/Video/providers/JWPlayer/JWPlayerController.js +21 -4
- package/src/components/Video/providers/JWPlayer/JWPlayerProvider.js +7 -5
- package/src/components/Video/providers/YouTube/YoutubeEmbeded.js +65 -2
- package/src/helpers/build-filters-query.js +1 -3
- package/src/{components/Card/helpers → helpers}/filter-query-setup.js +5 -3
- package/src/{components/Card/helpers → helpers}/filters-setup.js +5 -2
- package/src/helpers/index.js +6 -0
- package/src/{components/Card/helpers → helpers}/should-skip-single-query.js +1 -1
- package/src/hooks/index.js +2 -0
- package/src/hooks/use-filter-aggregation-values.js +37 -0
- package/src/hooks/use-portal.js +18 -0
- package/tests/unit/src/components/Card/Card.test.js +16 -1
- package/tests/unit/src/components/Card/__snapshots__/Card.test.js.snap +83 -0
- package/tests/unit/src/components/Card/helpers/get-updated-items-to-display.test.js +1 -1
- package/tests/unit/src/components/Image/Lightbox/Lightbox.test.js +4 -0
- package/tests/unit/src/components/Image/Lightbox/__snapshots__/Lightbox.test.js.snap +3 -38
- package/tests/unit/src/components/MenuItem/MenuEntitiesItem.test.js +23 -0
- package/tests/unit/src/components/MenuItem/MenuItem.test.js +30 -11
- package/tests/unit/src/components/MenuItem/MenuItemRender.test.js +55 -0
- package/tests/unit/src/components/MenuItem/__snapshots__/MenuEntitiesItem.test.js.snap +3 -0
- package/tests/unit/src/components/MenuItem/__snapshots__/MenuItem.test.js.snap +5 -51
- package/tests/unit/src/components/MenuItem/helpers/inject-helper-into-template.test.js +44 -0
- package/tests/unit/src/components/MenuItem/mocks.js +71 -0
- package/tests/unit/src/components/Modal/Modal.test.js +4 -0
- package/tests/unit/src/components/Modal/__snapshots__/Modal.test.js.snap +7 -42
- package/tests/unit/src/components/SearchFilter/__snapshots__/SearchFilterContainer.test.js.snap +7 -1
- package/lib/components/Card/helpers/filter-query-setup.js.map +0 -1
- package/lib/components/Card/helpers/filters-setup.js.map +0 -1
- package/lib/components/Card/helpers/get-updated-items-to-display.js.map +0 -1
- package/lib/components/Card/helpers/get-updated-sort-properties.js.map +0 -1
- package/lib/components/Card/helpers/should-return.js.map +0 -1
- package/lib/components/Card/helpers/should-skip-single-query.js.map +0 -1
- package/lib-es/components/Card/helpers/filter-query-setup.js.map +0 -1
- package/lib-es/components/Card/helpers/filters-setup.js.map +0 -1
- package/lib-es/components/Card/helpers/get-updated-items-to-display.js.map +0 -1
- package/lib-es/components/Card/helpers/get-updated-sort-properties.js.map +0 -1
- package/lib-es/components/Card/helpers/should-return.js.map +0 -1
- package/lib-es/components/Card/helpers/should-skip-single-query.js.map +0 -1
- /package/lib/{components/Card/helpers → helpers}/get-updated-items-to-display.js +0 -0
- /package/lib/{components/Card/helpers → helpers}/get-updated-sort-properties.js +0 -0
- /package/lib/{components/Card/helpers → helpers}/should-return.js +0 -0
- /package/lib-es/{components/Card/helpers → helpers}/get-updated-items-to-display.js +0 -0
- /package/lib-es/{components/Card/helpers → helpers}/get-updated-sort-properties.js +0 -0
- /package/lib-es/{components/Card/helpers → helpers}/should-return.js +0 -0
- /package/src/{components/Card/helpers → helpers}/get-updated-items-to-display.js +0 -0
- /package/src/{components/Card/helpers → helpers}/get-updated-sort-properties.js +0 -0
- /package/src/{components/Card/helpers → helpers}/should-return.js +0 -0
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useEffect, useContext, useRef } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { useInView } from '@blaze-react/utils/lib/customHooks';
|
|
4
4
|
import { IN_VIEW_CONFIG } from '../../../../constants';
|
|
5
5
|
import { getPosterUrl, YT_HQ_FORMAT, YT_IMAGE_URL } from './helpers';
|
|
6
|
+
import { VideoContext } from '../../VideoContext';
|
|
7
|
+
import { EVENT_ACTIONS } from '../../constants';
|
|
8
|
+
|
|
9
|
+
const SCRIPT_ID = 'youtube-iframe-api';
|
|
6
10
|
|
|
7
11
|
const YoutubeEmbeded = ({
|
|
8
12
|
autoplay,
|
|
@@ -23,6 +27,9 @@ const YoutubeEmbeded = ({
|
|
|
23
27
|
placeholderOnly,
|
|
24
28
|
imageData
|
|
25
29
|
}) => {
|
|
30
|
+
const ref = useRef(null);
|
|
31
|
+
const playerRef = useRef(null);
|
|
32
|
+
const { emitEvent } = useContext(VideoContext);
|
|
26
33
|
const [isIntersecting, outerRef] = useInView(IN_VIEW_CONFIG);
|
|
27
34
|
const [preconnected, setPreconnected] = useState(false);
|
|
28
35
|
const [renderIframe, setRenderIframe] = useState(!!autoplay);
|
|
@@ -43,10 +50,64 @@ const YoutubeEmbeded = ({
|
|
|
43
50
|
webp
|
|
44
51
|
});
|
|
45
52
|
const mutedValue = muted ? '&mute=1' : '';
|
|
46
|
-
|
|
53
|
+
let iframeSrc = !playlist
|
|
47
54
|
? `${ytUrl}/embed/${encodedId}?autoplay=1${mutedValue}${paramsImp}`
|
|
48
55
|
: `${ytUrl}/embed/videoseries?autoplay=1${mutedValue}&list=${encodedId}${paramsImp}`;
|
|
56
|
+
if (emitEvent) {
|
|
57
|
+
iframeSrc += `&enablejsapi=1`;
|
|
58
|
+
}
|
|
59
|
+
|
|
49
60
|
const parsedWrapperClassname = `yt-facade ${renderIframe ? 'yt-activated' : ''}`;
|
|
61
|
+
const iframeId = `yt-iframe-${videoId}`;
|
|
62
|
+
|
|
63
|
+
useEffect(
|
|
64
|
+
() => {
|
|
65
|
+
if (!emitEvent || !renderIframe) return;
|
|
66
|
+
|
|
67
|
+
if (!document.getElementById(SCRIPT_ID)) {
|
|
68
|
+
// if script not already loaded
|
|
69
|
+
const tag = document.createElement('script');
|
|
70
|
+
tag.id = SCRIPT_ID;
|
|
71
|
+
tag.src = 'https://www.youtube.com/iframe_api';
|
|
72
|
+
const firstScriptTag = document.getElementsByTagName('script')[0];
|
|
73
|
+
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const onStateChange = event => {
|
|
77
|
+
let action = '';
|
|
78
|
+
if (event.data === window.YT.PlayerState.ENDED) {
|
|
79
|
+
action = EVENT_ACTIONS.ENDED;
|
|
80
|
+
} else if (event.data === window.YT.PlayerState.PAUSED) {
|
|
81
|
+
action = EVENT_ACTIONS.PAUSED;
|
|
82
|
+
} else if (event.data === window.YT.PlayerState.PLAYING) {
|
|
83
|
+
action = EVENT_ACTIONS.PLAYING;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
emitEvent({ action, videoId });
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
if (window.YT) {
|
|
90
|
+
// if script already loaded then attach player
|
|
91
|
+
window.YT.ready(() => {
|
|
92
|
+
playerRef.current = new window.YT.Player(iframeId, {
|
|
93
|
+
events: {
|
|
94
|
+
onStateChange
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
// called on script load
|
|
100
|
+
window.onYouTubeIframeAPIReady = () => {
|
|
101
|
+
playerRef.current = new window.YT.Player(ref.current, {
|
|
102
|
+
events: {
|
|
103
|
+
onStateChange
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
[emitEvent, iframeId, renderIframe, videoId]
|
|
110
|
+
);
|
|
50
111
|
|
|
51
112
|
useEffect(
|
|
52
113
|
() => {
|
|
@@ -114,6 +175,8 @@ const YoutubeEmbeded = ({
|
|
|
114
175
|
</div>
|
|
115
176
|
{renderIframe && (
|
|
116
177
|
<iframe
|
|
178
|
+
ref={ref}
|
|
179
|
+
id={iframeId}
|
|
117
180
|
className={iframeClass}
|
|
118
181
|
title={videoTitle}
|
|
119
182
|
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
|
@@ -32,16 +32,14 @@ const builFilterObject = ({ queryKey, value, filters, isRange, isInQuery }) => {
|
|
|
32
32
|
|
|
33
33
|
const buildFiltersQuery = ({
|
|
34
34
|
shouldAddFilters,
|
|
35
|
-
|
|
36
35
|
filterBy,
|
|
37
36
|
filterByProperty,
|
|
38
37
|
rangeValues,
|
|
39
38
|
queryKeys,
|
|
40
39
|
query
|
|
41
40
|
}) => {
|
|
42
|
-
if (!shouldAddFilters) return [];
|
|
43
41
|
const mustFilters = [];
|
|
44
|
-
if (query) {
|
|
42
|
+
if (shouldAddFilters && query) {
|
|
45
43
|
Object.keys(query).forEach(queryKey => {
|
|
46
44
|
if (QUERY_KEYS_TO_IGNORE.includes(queryKey)) return;
|
|
47
45
|
if (!queryKey || !query[queryKey]) return;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getStringTypeProps } from '@blaze-cms/utils/src/helpers';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import getGenericRenderVariables from './get-generic-render-variables';
|
|
3
|
+
import buildRawQueryBase from './build-raw-query-base';
|
|
4
|
+
import buildSetFilters from './build-set-filters';
|
|
5
|
+
import { DEFAULT_LIMIT } from '../constants';
|
|
4
6
|
|
|
5
7
|
const filterQuerySetup = ({
|
|
6
8
|
getEntitySchemas,
|
|
@@ -13,7 +15,7 @@ const filterQuerySetup = ({
|
|
|
13
15
|
itemsToDisplay,
|
|
14
16
|
entitySameAsCurrentItemEntity,
|
|
15
17
|
entitySchema,
|
|
16
|
-
useRandomSort
|
|
18
|
+
useRandomSort = false
|
|
17
19
|
}) => {
|
|
18
20
|
const stringProps = getStringTypeProps(entity, filterEntityRelations, getEntitySchemas);
|
|
19
21
|
const filterValues =
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import buildQueryFields from './build-query-fields';
|
|
2
|
+
import getInheritedFilters from './get-inherited-filters';
|
|
3
|
+
import getQueryProps from './get-query-props';
|
|
4
|
+
import { getSearchPublishedContent } from '../application/query';
|
|
3
5
|
|
|
4
6
|
const filtersSetup = ({
|
|
5
7
|
entityFields,
|
|
@@ -16,6 +18,7 @@ const filtersSetup = ({
|
|
|
16
18
|
const fields = buildQueryFields(entityFields, entityTypes, isFull);
|
|
17
19
|
const action = getSearchPublishedContent(fields);
|
|
18
20
|
const inheritedFilters = getInheritedFilters(filterBy, filterByProperty);
|
|
21
|
+
|
|
19
22
|
const entitySameAsCurrentItemEntity = entities.includes(itemEntityUpdated);
|
|
20
23
|
const { relations: filterEntityRelations = [] } = filterEntitySchema;
|
|
21
24
|
const queryProps = getQueryProps(inheritedFilters, currentSchema, filterEntitySchema);
|
package/src/helpers/index.js
CHANGED
|
@@ -53,5 +53,11 @@ export { default as appendImages } from './append-images';
|
|
|
53
53
|
export { default as parseTextBlock } from './parse-TextBlock';
|
|
54
54
|
export { default as processDataSummaryValue } from './process-data-summary-value';
|
|
55
55
|
export { default as buildQueryKey } from './build-query-key';
|
|
56
|
+
export { default as filterQuerySetup } from './filter-query-setup';
|
|
57
|
+
export { default as filtersSetup } from './filters-setup';
|
|
58
|
+
export { default as getUpdatedItemsToDisplay } from './get-updated-items-to-display';
|
|
59
|
+
export { default as getUpdatedSortProperties } from './get-updated-sort-properties';
|
|
60
|
+
export { default as shouldReturn } from './should-return';
|
|
61
|
+
export { default as shouldSkipSingleQuery } from './should-skip-single-query';
|
|
56
62
|
export { default as buildRawQueryStringified } from './build-raw-query-stringified';
|
|
57
63
|
export { default as buildFiltersQuery } from './build-filters-query';
|
package/src/hooks/index.js
CHANGED
|
@@ -7,3 +7,5 @@ export { default as useGetSingleEntitySchema } from './use-get-single-entity-sch
|
|
|
7
7
|
export { default as useCheckMobileScreen } from './use-check-mobile-screen';
|
|
8
8
|
export { default as useBannerInsertion } from './use-banner-insertion';
|
|
9
9
|
export { default as useAppSyncEventHook } from './use-app-sync-event-hook';
|
|
10
|
+
export { default as usePortal } from './use-portal';
|
|
11
|
+
export { default as useFilterAggregationValues } from './use-filter-aggregation-values';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
const useFilterAggregationValues = ({ data, filterValues }) => {
|
|
4
|
+
const [stateValues, setStateValues] = useState(data);
|
|
5
|
+
const [prop, setProp] = useState('');
|
|
6
|
+
|
|
7
|
+
useEffect(
|
|
8
|
+
() => {
|
|
9
|
+
if (!stateValues) return setStateValues(data);
|
|
10
|
+
|
|
11
|
+
const lastChangedFilter = filterValues?.[prop];
|
|
12
|
+
|
|
13
|
+
if (!data) return;
|
|
14
|
+
|
|
15
|
+
const newOptions = data[prop];
|
|
16
|
+
const currentOptions = stateValues?.[prop];
|
|
17
|
+
|
|
18
|
+
if (lastChangedFilter === null || lastChangedFilter === '') {
|
|
19
|
+
return setStateValues(prevState => ({
|
|
20
|
+
...data,
|
|
21
|
+
[prop]: newOptions
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setStateValues(prevState => ({
|
|
26
|
+
...data,
|
|
27
|
+
[prop]: currentOptions
|
|
28
|
+
}));
|
|
29
|
+
},
|
|
30
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31
|
+
[data, prop, filterValues]
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return [stateValues, setStateValues, setProp, prop];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default useFilterAggregationValues;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
function usePortal() {
|
|
4
|
+
const rootElemRef = React.useRef(document.createElement('div'));
|
|
5
|
+
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
document.body.appendChild(rootElemRef.current);
|
|
8
|
+
|
|
9
|
+
const element = rootElemRef.current;
|
|
10
|
+
return function removeElement() {
|
|
11
|
+
element.remove();
|
|
12
|
+
};
|
|
13
|
+
}, []);
|
|
14
|
+
|
|
15
|
+
return rootElemRef.current;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default usePortal;
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* @jest-environment jsdom
|
|
3
3
|
*/
|
|
4
4
|
import React from 'react';
|
|
5
|
-
import { render as _render, act, waitFor } from '@testing-library/react';
|
|
5
|
+
import { render as _render, act, waitFor, screen } from '@testing-library/react';
|
|
6
6
|
import '@testing-library/jest-dom/extend-expect';
|
|
7
|
+
import { setEnvs, deleteEnvs } from '@blaze-cms/tools/test-helpers/test-files/test-env';
|
|
7
8
|
import Card from '../../../../../src/components/Card/Card';
|
|
8
9
|
import { pageBuilderComponentsMocks } from './mockData';
|
|
9
10
|
|
|
@@ -211,4 +212,18 @@ describe('Card component', () => {
|
|
|
211
212
|
});
|
|
212
213
|
expect(getByTestId('full-card')).toBeInTheDocument();
|
|
213
214
|
});
|
|
215
|
+
|
|
216
|
+
it('should render link wrapper', async () => {
|
|
217
|
+
const envs = {
|
|
218
|
+
BLAZE_PB_ADD_CLICK_TO_CARDS: 'true'
|
|
219
|
+
};
|
|
220
|
+
setEnvs(envs);
|
|
221
|
+
const { asFragment } = await render(Card, {
|
|
222
|
+
...componentProps,
|
|
223
|
+
pageBuilderComponents: pageBuilderComponentsMocks
|
|
224
|
+
});
|
|
225
|
+
expect(screen.getByLabelText(componentProps.name)).toBeInTheDocument();
|
|
226
|
+
expect(asFragment()).toMatchSnapshot();
|
|
227
|
+
deleteEnvs(envs);
|
|
228
|
+
});
|
|
214
229
|
});
|
|
@@ -303,6 +303,89 @@ exports[`Card component should render customPreheader and alternativeHeadline in
|
|
|
303
303
|
</DocumentFragment>
|
|
304
304
|
`;
|
|
305
305
|
|
|
306
|
+
exports[`Card component should render link wrapper 1`] = `
|
|
307
|
+
<DocumentFragment>
|
|
308
|
+
<a
|
|
309
|
+
aria-label="mock name"
|
|
310
|
+
class="card card--portrait"
|
|
311
|
+
href="/mockurl"
|
|
312
|
+
>
|
|
313
|
+
<div
|
|
314
|
+
class="card__image card__image--portrait"
|
|
315
|
+
>
|
|
316
|
+
<div
|
|
317
|
+
class="card__image-link"
|
|
318
|
+
gtmid=""
|
|
319
|
+
>
|
|
320
|
+
<img
|
|
321
|
+
alt="test-altText"
|
|
322
|
+
src="test-url"
|
|
323
|
+
/>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
<div
|
|
327
|
+
class="card__content-wrapper card__content-wrapper--portrait "
|
|
328
|
+
>
|
|
329
|
+
<div
|
|
330
|
+
class="card__content card__content--portrait"
|
|
331
|
+
>
|
|
332
|
+
<div
|
|
333
|
+
class="badge badge--label"
|
|
334
|
+
gtmid=""
|
|
335
|
+
href="published-url"
|
|
336
|
+
>
|
|
337
|
+
category-name
|
|
338
|
+
</div>
|
|
339
|
+
<div
|
|
340
|
+
class="card__title card__title--portrait "
|
|
341
|
+
>
|
|
342
|
+
<div
|
|
343
|
+
gtmid=""
|
|
344
|
+
title="mock name"
|
|
345
|
+
>
|
|
346
|
+
mock name
|
|
347
|
+
</div>
|
|
348
|
+
</div>
|
|
349
|
+
<div
|
|
350
|
+
class="card__item card__item--full"
|
|
351
|
+
data-testid="full-card"
|
|
352
|
+
/>
|
|
353
|
+
<div
|
|
354
|
+
class="card__details card__details--portrait"
|
|
355
|
+
>
|
|
356
|
+
<span
|
|
357
|
+
class=""
|
|
358
|
+
data-testid="some%20description"
|
|
359
|
+
>
|
|
360
|
+
some description
|
|
361
|
+
</span>
|
|
362
|
+
<span
|
|
363
|
+
class=""
|
|
364
|
+
>
|
|
365
|
+
extra props
|
|
366
|
+
</span>
|
|
367
|
+
</div>
|
|
368
|
+
</div>
|
|
369
|
+
<div
|
|
370
|
+
class="card__child-content"
|
|
371
|
+
>
|
|
372
|
+
<div
|
|
373
|
+
class="child_1"
|
|
374
|
+
>
|
|
375
|
+
some stuff
|
|
376
|
+
</div>
|
|
377
|
+
<div
|
|
378
|
+
class="child_2"
|
|
379
|
+
modifier="child-modi"
|
|
380
|
+
>
|
|
381
|
+
another child
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
</a>
|
|
386
|
+
</DocumentFragment>
|
|
387
|
+
`;
|
|
388
|
+
|
|
306
389
|
exports[`Card component should render without throwing an error and match snapshot 1`] = `
|
|
307
390
|
<DocumentFragment>
|
|
308
391
|
<div
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '@testing-library/jest-dom/extend-expect';
|
|
2
|
-
import getUpdatedItemsToDisplay from '../../../../../../src/
|
|
2
|
+
import getUpdatedItemsToDisplay from '../../../../../../src/helpers/get-updated-items-to-display';
|
|
3
3
|
|
|
4
4
|
const mockedProps = {
|
|
5
5
|
itemsToDisplay: [
|
|
@@ -10,6 +10,10 @@ jest.mock('../../../../../../src/components/Banner', () =>
|
|
|
10
10
|
jest.fn().mockImplementation(() => <span>Banner</span>)
|
|
11
11
|
);
|
|
12
12
|
|
|
13
|
+
jest.mock('../../../../../../src/components/ModalAdapter', () =>
|
|
14
|
+
jest.fn().mockImplementation(({ children }) => children)
|
|
15
|
+
);
|
|
16
|
+
|
|
13
17
|
const mockProps = {
|
|
14
18
|
imageUrl: 'some-url',
|
|
15
19
|
altTxt: 'atl text',
|
|
@@ -3,48 +3,13 @@
|
|
|
3
3
|
exports[`LightBox component should render without throwing an error and match snapshot 1`] = `
|
|
4
4
|
<DocumentFragment>
|
|
5
5
|
<div
|
|
6
|
-
class="
|
|
7
|
-
/>
|
|
8
|
-
<div
|
|
9
|
-
class=" modal modal--show modal--full-screen"
|
|
6
|
+
class="row row--display-row"
|
|
10
7
|
>
|
|
11
8
|
<div
|
|
12
|
-
class="
|
|
13
|
-
>
|
|
14
|
-
<div
|
|
15
|
-
class="modal__title"
|
|
16
|
-
/>
|
|
17
|
-
<div
|
|
18
|
-
class="modal__close"
|
|
19
|
-
role="button"
|
|
20
|
-
>
|
|
21
|
-
<i
|
|
22
|
-
class="material-icons"
|
|
23
|
-
>
|
|
24
|
-
close
|
|
25
|
-
</i>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
<div
|
|
29
|
-
class="modal__content"
|
|
30
|
-
>
|
|
31
|
-
<div
|
|
32
|
-
class="row row--display-row"
|
|
33
|
-
>
|
|
34
|
-
<div
|
|
35
|
-
class="column column--two-thirds"
|
|
36
|
-
>
|
|
37
|
-
<div
|
|
38
|
-
class="image"
|
|
39
|
-
/>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
<div
|
|
44
|
-
class="modal__footer"
|
|
9
|
+
class="column column--two-thirds"
|
|
45
10
|
>
|
|
46
11
|
<div
|
|
47
|
-
class="
|
|
12
|
+
class="image"
|
|
48
13
|
/>
|
|
49
14
|
</div>
|
|
50
15
|
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
5
|
+
import { render } from '@testing-library/react';
|
|
6
|
+
import MenuEntitiesItem from '../../../../../src/components/MenuItem/MenuEntitiesItem';
|
|
7
|
+
import { MOCKED_MENUITEMS_PROPS } from './mocks';
|
|
8
|
+
|
|
9
|
+
jest.mock('@apollo/client', () => ({
|
|
10
|
+
...jest.requireActual('@apollo/client'),
|
|
11
|
+
useQuery: jest.fn(({ data, loading, error, fetchMore }) => ({ data, loading, error, fetchMore }))
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
jest.mock('@blaze-cms/utils-handlebars', () => ({
|
|
15
|
+
useStringTemplate: jest.fn((parent, [title]) => ({ loading: false, data: [title] }))
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
describe('MenuEntitiesItem component', () => {
|
|
19
|
+
it('should render based on listData received', async () => {
|
|
20
|
+
const { asFragment } = await render(MenuEntitiesItem, MOCKED_MENUITEMS_PROPS);
|
|
21
|
+
expect(asFragment()).toMatchSnapshot();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -6,25 +6,44 @@ import { render } from '@blaze-cms/tools/test-helpers/test-functions';
|
|
|
6
6
|
import '@testing-library/jest-dom/extend-expect';
|
|
7
7
|
import MenuItem from '../../../../../src/components/MenuItem';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
jest.mock('@apollo/client', () => ({
|
|
10
|
+
...jest.requireActual('@apollo/client'),
|
|
11
|
+
useQuery: jest.fn(({ data, loading, error, fetchMore }) => ({ data, loading, error, fetchMore }))
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
jest.mock('@blaze-cms/utils-handlebars', () => ({
|
|
15
|
+
useStringTemplate: jest.fn((parent, [title]) => ({ loading: false, data: [title] }))
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
const componentProps = {
|
|
19
|
+
id: 'id',
|
|
20
|
+
name: 'mock name',
|
|
10
21
|
eventType: 'hover',
|
|
11
|
-
|
|
22
|
+
url: '/search?category.name={{currentParent.name}}',
|
|
23
|
+
text: 'Category: {{currentParent.name}}',
|
|
24
|
+
entity: 'page',
|
|
25
|
+
parent: {
|
|
26
|
+
itemEntity: 'page',
|
|
27
|
+
itemId: 'item-id'
|
|
28
|
+
},
|
|
29
|
+
category: {
|
|
30
|
+
publishedListingPage: {
|
|
31
|
+
url: 'published-url'
|
|
32
|
+
},
|
|
33
|
+
name: 'Category name'
|
|
34
|
+
},
|
|
12
35
|
modifier: 'menu-item-mod',
|
|
13
36
|
children: [
|
|
14
37
|
<div className="child_1" key="1" component={{ type: 'menuitem' }}>
|
|
15
|
-
|
|
38
|
+
menu child
|
|
16
39
|
</div>
|
|
17
|
-
]
|
|
40
|
+
],
|
|
41
|
+
displayCategory: true
|
|
18
42
|
};
|
|
19
43
|
|
|
20
44
|
describe('MenuItem component', () => {
|
|
21
|
-
it('should render
|
|
22
|
-
const { asFragment } = render(MenuItem,
|
|
23
|
-
expect(asFragment()).toMatchSnapshot();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should render link if url is passed', () => {
|
|
27
|
-
const { asFragment } = render(MenuItem, { ...props, url: '/somewhere' });
|
|
45
|
+
it('should render a MenuItem based on passed parameters', async () => {
|
|
46
|
+
const { asFragment } = await render(MenuItem, componentProps);
|
|
28
47
|
expect(asFragment()).toMatchSnapshot();
|
|
29
48
|
});
|
|
30
49
|
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { render, fireEvent } from '@testing-library/react';
|
|
7
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
8
|
+
import MenuRender from '../../../../../src/components/MenuItem/MenuItemRender';
|
|
9
|
+
|
|
10
|
+
jest.mock('@blaze-cms/utils-handlebars', () => ({
|
|
11
|
+
useStringTemplate: jest.fn((parent, [title]) => ({ loadig: false, data: [title] }))
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
describe('MenuRender component', () => {
|
|
15
|
+
it('renders menu item with link when URL is provided', () => {
|
|
16
|
+
const { getByText } = render(<MenuRender eventType="click" text="Home" url="/home" />);
|
|
17
|
+
const linkElement = getByText('Home');
|
|
18
|
+
expect(linkElement).toBeInTheDocument();
|
|
19
|
+
expect(linkElement.tagName).toBe('A');
|
|
20
|
+
expect(linkElement.getAttribute('href')).toBe('/home');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('renders menu item without link when URL is not provided', () => {
|
|
24
|
+
const { getByText } = render(<MenuRender eventType="click" text="About" />);
|
|
25
|
+
const spanElement = getByText('About');
|
|
26
|
+
expect(spanElement).toBeInTheDocument();
|
|
27
|
+
expect(spanElement.tagName).toBe('SPAN');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('toggles display of children on mouse enter and leave events', () => {
|
|
31
|
+
const { getByText, getByTestId } = render(
|
|
32
|
+
<MenuRender eventType="hover" text="Parent">
|
|
33
|
+
<div data-testid="child">Child</div>
|
|
34
|
+
</MenuRender>
|
|
35
|
+
);
|
|
36
|
+
const parentElement = getByText('Parent');
|
|
37
|
+
const childElement = getByTestId('child');
|
|
38
|
+
|
|
39
|
+
fireEvent.mouseEnter(parentElement);
|
|
40
|
+
expect(childElement).toBeInTheDocument();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('toggles display of children on click event when URL is not provided', () => {
|
|
44
|
+
const { getByText, getByTestId } = render(
|
|
45
|
+
<MenuRender eventType="click" text="Parent">
|
|
46
|
+
<div data-testid="child">Child</div>
|
|
47
|
+
</MenuRender>
|
|
48
|
+
);
|
|
49
|
+
const parentElement = getByText('Parent');
|
|
50
|
+
const childElement = getByTestId('child');
|
|
51
|
+
|
|
52
|
+
fireEvent.click(parentElement);
|
|
53
|
+
expect(childElement).toBeInTheDocument();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
-
exports[`MenuItem component should render
|
|
3
|
+
exports[`MenuItem component should render a MenuItem based on passed parameters 1`] = `
|
|
4
4
|
<DocumentFragment>
|
|
5
5
|
<li
|
|
6
6
|
class="menu-item-mod"
|
|
@@ -9,10 +9,10 @@ exports[`MenuItem component should render link if url is passed 1`] = `
|
|
|
9
9
|
class="menu--item--link"
|
|
10
10
|
>
|
|
11
11
|
<a
|
|
12
|
-
aria-label="
|
|
13
|
-
href="/
|
|
12
|
+
aria-label="Category: {{currentParent.name}}"
|
|
13
|
+
href="/search?category.name={{url_encode currentParent.name}}"
|
|
14
14
|
>
|
|
15
|
-
|
|
15
|
+
Category: {{currentParent.name}}
|
|
16
16
|
</a>
|
|
17
17
|
<i
|
|
18
18
|
class="menu--item--link--icon"
|
|
@@ -40,53 +40,7 @@ exports[`MenuItem component should render link if url is passed 1`] = `
|
|
|
40
40
|
class="child_1"
|
|
41
41
|
component="[object Object]"
|
|
42
42
|
>
|
|
43
|
-
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
46
|
-
</li>
|
|
47
|
-
</DocumentFragment>
|
|
48
|
-
`;
|
|
49
|
-
|
|
50
|
-
exports[`MenuItem component should render without throwing an error and match snapshot 1`] = `
|
|
51
|
-
<DocumentFragment>
|
|
52
|
-
<li
|
|
53
|
-
class="menu-item-mod"
|
|
54
|
-
>
|
|
55
|
-
<div
|
|
56
|
-
class="menu--item--link"
|
|
57
|
-
>
|
|
58
|
-
<span
|
|
59
|
-
role="button"
|
|
60
|
-
>
|
|
61
|
-
Item 1
|
|
62
|
-
</span>
|
|
63
|
-
<i
|
|
64
|
-
class="menu--item--link--icon"
|
|
65
|
-
role="button"
|
|
66
|
-
>
|
|
67
|
-
<svg
|
|
68
|
-
fill="currentColor"
|
|
69
|
-
height="1em"
|
|
70
|
-
stroke="currentColor"
|
|
71
|
-
stroke-width="0"
|
|
72
|
-
viewBox="0 0 448 512"
|
|
73
|
-
width="1em"
|
|
74
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
75
|
-
>
|
|
76
|
-
<path
|
|
77
|
-
d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"
|
|
78
|
-
/>
|
|
79
|
-
</svg>
|
|
80
|
-
</i>
|
|
81
|
-
</div>
|
|
82
|
-
<div
|
|
83
|
-
class="menu--item-children hidden"
|
|
84
|
-
>
|
|
85
|
-
<div
|
|
86
|
-
class="child_1"
|
|
87
|
-
component="[object Object]"
|
|
88
|
-
>
|
|
89
|
-
some child
|
|
43
|
+
menu child
|
|
90
44
|
</div>
|
|
91
45
|
</div>
|
|
92
46
|
</li>
|