@shopgate/engage 7.11.1 → 7.12.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cart/components/CartItem/CartItem.js +2 -2
- package/favorites/components/Item/Item.js +3 -3
- package/favorites/components/List/List.js +2 -2
- package/package.json +7 -7
- package/product/hocs/withProductListEntry.js +11 -0
- package/product/hocs/withProductListType.js +11 -0
- package/product/hooks/useProductListEntry.js +5 -0
- package/product/hooks/useProductListType.js +5 -0
- package/product/index.js +4 -3
- package/product/providers/ProductListEntry/context.js +9 -0
- package/product/providers/ProductListEntry/index.js +11 -0
- package/product/providers/ProductListType/context.js +12 -0
- package/product/providers/ProductListType/index.js +14 -0
- package/reviews/components/Reviews/components/AllReviewsLink/connector.js +10 -0
- package/reviews/components/Reviews/components/AllReviewsLink/index.js +4 -0
- package/reviews/components/Reviews/components/AllReviewsLink/style.js +4 -0
- package/reviews/components/Reviews/components/Header/components/AverageRating/index.js +7 -0
- package/reviews/components/Reviews/components/Header/components/AverageRating/style.js +1 -0
- package/reviews/components/Reviews/components/Header/components/NoReviews/index.js +3 -0
- package/reviews/components/Reviews/components/Header/components/NoReviews/style.js +1 -0
- package/reviews/components/Reviews/components/Header/components/ReviewsExcerpt/index.js +4 -0
- package/reviews/components/Reviews/components/Header/components/ReviewsExcerpt/style.js +2 -0
- package/reviews/components/Reviews/components/Header/components/WriteReviewLink/index.js +4 -0
- package/reviews/components/Reviews/components/Header/components/WriteReviewLink/spec.js +5 -0
- package/reviews/components/Reviews/components/Header/connector.js +6 -0
- package/reviews/components/Reviews/components/Header/index.js +6 -0
- package/reviews/components/Reviews/components/Header/spec.js +6 -0
- package/reviews/components/Reviews/components/List/components/Info/components/Author/index.js +5 -0
- package/reviews/components/Reviews/components/List/components/Info/components/ReviewDate/index.js +5 -0
- package/reviews/components/Reviews/components/List/components/Info/index.js +6 -0
- package/reviews/components/Reviews/components/List/components/Info/style.js +1 -0
- package/reviews/components/Reviews/components/List/components/Rating/index.js +5 -0
- package/reviews/components/Reviews/components/List/components/Rating/style.js +1 -0
- package/reviews/components/Reviews/components/List/components/Review/index.js +5 -0
- package/reviews/components/Reviews/components/List/components/Text/index.js +5 -0
- package/reviews/components/Reviews/components/List/components/Text/style.js +1 -0
- package/reviews/components/Reviews/components/List/components/Title/index.js +5 -0
- package/reviews/components/Reviews/components/List/components/Title/style.js +1 -0
- package/reviews/components/Reviews/components/List/index.js +5 -0
- package/reviews/components/Reviews/components/List/spec.js +1 -0
- package/reviews/components/Reviews/components/List/style.js +1 -0
- package/reviews/components/Reviews/components/RatingCount/index.js +4 -0
- package/reviews/components/Reviews/components/RatingCount/spec.js +1 -0
- package/reviews/components/Reviews/components/RatingCount/style.js +2 -0
- package/reviews/components/Reviews/components/ReviewsInfo/index.js +6 -0
- package/reviews/components/Reviews/connector.js +6 -0
- package/reviews/components/Reviews/index.js +6 -0
- package/reviews/components/Reviews/mock.js +22 -0
- package/reviews/components/Reviews/spec.js +7 -0
- package/reviews/components/Reviews/style.js +1 -0
- package/reviews/index.js +2 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{hot}from'react-hot-loader/root';import*as React from'react';import{SurroundPortals}from'@shopgate/engage/components';import{CART_ITEM_TYPE_PRODUCT,CART_ITEM_TYPE_COUPON,CART_ITEM}from'@shopgate/pwa-common-commerce/cart';import CartItemProduct from"./CartItemProduct";import CartItemCoupon from"./CartItemCoupon";import CartItemProductProvider from"./CartItemProductProvider";/**
|
|
1
|
+
import{hot}from'react-hot-loader/root';import*as React from'react';import{SurroundPortals}from'@shopgate/engage/components';import{CART_ITEM_TYPE_PRODUCT,CART_ITEM_TYPE_COUPON,CART_ITEM}from'@shopgate/pwa-common-commerce/cart';import{ProductListEntryProvider}from'@shopgate/engage/product';import CartItemProduct from"./CartItemProduct";import CartItemCoupon from"./CartItemCoupon";import CartItemProductProvider from"./CartItemProductProvider";/**
|
|
2
2
|
* The cart item component.
|
|
3
3
|
* @param {Object} props The component props.
|
|
4
4
|
* @property {Object} props.item The cart item.
|
|
5
5
|
* @property {Function} props.onFocus A function to indicate when the item has been focussed.
|
|
6
6
|
* @return {JSX.Element}
|
|
7
|
-
*/function CartItem(_ref){var item=_ref.item,onFocus=_ref.onFocus,editable=_ref.editable,currencyOverride=_ref.currencyOverride;if(item.type!==CART_ITEM_TYPE_PRODUCT&&item.type!==CART_ITEM_TYPE_COUPON){return null;}var props={item:item};var isProduct=item.type===CART_ITEM_TYPE_PRODUCT;if(isProduct){return React.createElement(SurroundPortals,{portalName:CART_ITEM,portalProps:props},React.createElement(CartItemProductProvider,{cartItem:item,onFocus:onFocus,isEditable:editable,currencyOverride:currencyOverride},React.createElement(CartItemProduct,null)));}return React.createElement(SurroundPortals,{portalName:CART_ITEM,portalProps:props},React.createElement(CartItemCoupon,{id:item.id,key:item.id,coupon:item.coupon,messages:item.messages,editable:editable}));}CartItem.defaultProps={editable:true,currencyOverride:null};export default hot(React.memo(CartItem));
|
|
7
|
+
*/function CartItem(_ref){var item=_ref.item,onFocus=_ref.onFocus,editable=_ref.editable,currencyOverride=_ref.currencyOverride;if(item.type!==CART_ITEM_TYPE_PRODUCT&&item.type!==CART_ITEM_TYPE_COUPON){return null;}var props={item:item};var isProduct=item.type===CART_ITEM_TYPE_PRODUCT;if(isProduct){var _item$product;return React.createElement(ProductListEntryProvider,{productId:item===null||item===void 0?void 0:(_item$product=item.product)===null||_item$product===void 0?void 0:_item$product.id},React.createElement(SurroundPortals,{portalName:CART_ITEM,portalProps:props},React.createElement(CartItemProductProvider,{cartItem:item,onFocus:onFocus,isEditable:editable,currencyOverride:currencyOverride},React.createElement(CartItemProduct,null))));}return React.createElement(SurroundPortals,{portalName:CART_ITEM,portalProps:props},React.createElement(CartItemCoupon,{id:item.id,key:item.id,coupon:item.coupon,messages:item.messages,editable:editable}));}CartItem.defaultProps={editable:true,currencyOverride:null};export default hot(React.memo(CartItem));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var _css;function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import React,{useCallback,useMemo,useLayoutEffect,useState,useEffect,useRef}from'react';import PropTypes from'prop-types';import{connect}from'react-redux';import{css}from'glamor';import{MODAL_VARIANT_SELECT}from'@shopgate/pwa-ui-shared/Dialog/constants';import{ProductImage,ITEM_PATH,PriceInfo,isBaseProduct as isBaseProductSelector,isProductOrderable,hasProductVariants}from'@shopgate/engage/product';import{bin2hex,showModal as showModalAction,historyPush as historyPushAction,getThemeSettings,i18n}from'@shopgate/engage/core';import{Link,TextLink,SurroundPortals}from'@shopgate/engage/components';import{makeIsRopeProductOrderable,getPreferredLocation,StockInfoLists}from'@shopgate/engage/locations';import{FAVORITES_PRODUCT_NAME,FAVORITES_PRODUCT_PRICE,FAVORITES_ADD_TO_CART}from'@shopgate/engage/favorites';import{broadcastLiveMessage}from'@shopgate/engage/a11y';import{responsiveMediaQuery}from'@shopgate/engage/styles';import Price from'@shopgate/pwa-ui-shared/Price';import PriceStriked from'@shopgate/pwa-ui-shared/PriceStriked';import AddToCart from'@shopgate/pwa-ui-shared/AddToCartButton';import{themeConfig}from'@shopgate/pwa-common/helpers/config';import{updateFavorite}from'@shopgate/pwa-common-commerce/favorites/actions/toggleFavorites';import{openFavoritesCommentDialog}from'@shopgate/pwa-common-commerce/favorites/action-creators';import classNames from'classnames';import Remove from"../RemoveButton";import ItemCharacteristics from"./ItemCharacteristics";import ItemQuantity from"./ItemQuantity";import ItemNotes from"./ItemNotes";import{FAVORITES_LIST_ITEM,FAVORITES_NOTES,FAVORITES_QUANTITY}from"../../constants/Portals";var variables=themeConfig.variables;/**
|
|
1
|
+
var _css;function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import React,{useCallback,useMemo,useLayoutEffect,useState,useEffect,useRef}from'react';import PropTypes from'prop-types';import{connect}from'react-redux';import{css}from'glamor';import{MODAL_VARIANT_SELECT}from'@shopgate/pwa-ui-shared/Dialog/constants';import{ProductImage,ITEM_PATH,PriceInfo,isBaseProduct as isBaseProductSelector,isProductOrderable,hasProductVariants,ProductListEntryProvider}from'@shopgate/engage/product';import{bin2hex,showModal as showModalAction,historyPush as historyPushAction,getThemeSettings,i18n}from'@shopgate/engage/core';import{Link,TextLink,SurroundPortals}from'@shopgate/engage/components';import{makeIsRopeProductOrderable,getPreferredLocation,StockInfoLists}from'@shopgate/engage/locations';import{FAVORITES_PRODUCT_NAME,FAVORITES_PRODUCT_PRICE,FAVORITES_ADD_TO_CART}from'@shopgate/engage/favorites';import{broadcastLiveMessage}from'@shopgate/engage/a11y';import{responsiveMediaQuery}from'@shopgate/engage/styles';import Price from'@shopgate/pwa-ui-shared/Price';import PriceStriked from'@shopgate/pwa-ui-shared/PriceStriked';import AddToCart from'@shopgate/pwa-ui-shared/AddToCartButton';import{themeConfig}from'@shopgate/pwa-common/helpers/config';import{updateFavorite}from'@shopgate/pwa-common-commerce/favorites/actions/toggleFavorites';import{openFavoritesCommentDialog}from'@shopgate/pwa-common-commerce/favorites/action-creators';import classNames from'classnames';import Remove from"../RemoveButton";import ItemCharacteristics from"./ItemCharacteristics";import ItemQuantity from"./ItemQuantity";import ItemNotes from"./ItemNotes";import{FAVORITES_LIST_ITEM,FAVORITES_NOTES,FAVORITES_QUANTITY}from"../../constants/Portals";var variables=themeConfig.variables;/**
|
|
2
2
|
* @return {Function} The extended component props.
|
|
3
3
|
*/var makeMapStateToProps=function makeMapStateToProps(){var isRopeProductOrderable=makeIsRopeProductOrderable(function(state,props){var _getPreferredLocation;return(_getPreferredLocation=getPreferredLocation(state,props))===null||_getPreferredLocation===void 0?void 0:_getPreferredLocation.code;},function(state,props){return props.variantId||props.productId||null;});return function(state,props){return{isBaseProduct:isBaseProductSelector(state,props),hasVariants:hasProductVariants(state,props),isOrderable:isProductOrderable(state,props),isRopeProductOrderable:isRopeProductOrderable(state,props)};};};/**
|
|
4
4
|
* @param {Function} dispatch Dispatch.
|
|
@@ -10,5 +10,5 @@ var _css;function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableTo
|
|
|
10
10
|
showModal({title:null,type:MODAL_VARIANT_SELECT,message:'favorites.modal.message',confirm:'favorites.modal.confirm',dismiss:'common.cancel',params:{productId:product.id}});return false;}if(!isRopeProductOrderable){// Product is not orderable for ROPE. So users need to do some corrections. Just redirect.
|
|
11
11
|
historyPush({pathname:productLink});return false;}broadcastLiveMessage('product.adding_item',{params:{count:1}});return addToCart(e);},[addToCart,hasVariants,historyPush,isBaseProduct,isRopeProductOrderable,product.id,productLink,showModal]);var commonPortalProps=useMemo(function(){var availability=product.availability,id=product.id,name=product.name;return{availability:availability,characteristics:characteristics,id:id,name:name,price:price,listId:listId};},[characteristics,listId,price,product]);var ctaPortalProps=useMemo(function(){return{isLoading:false,noShadow:false,listId:listId,isBaseProduct:isBaseProduct,isDisabled:isDisabled,productId:product.id,handleRemoveFromCart:remove,handleAddToCart:handleAddToCart};},[handleAddToCart,isBaseProduct,isDisabled,listId,product.id,remove]);var handleChangeQuantity=useCallback(function(newQuantity){// Do nothing when quantity didn't change
|
|
12
12
|
if(newQuantity===quantity)return;updateFavoriteItem(product.id,listId,newQuantity,notes);},[listId,notes,product.id,quantity,updateFavoriteItem]);var handleDeleteComment=useCallback(function(event){event.preventDefault();event.stopPropagation();updateFavoriteItem(product.id,listId,quantity,'');setTimeout(function(){if(notesButtonRef===null||notesButtonRef===void 0?void 0:notesButtonRef.current){// Focus the add button after item deletion to improve a11y
|
|
13
|
-
notesButtonRef.current.focus();}broadcastLiveMessage('favorites.comments.removed');},300);},[listId,product.id,quantity,updateFavoriteItem]);return React.createElement(SurroundPortals,{portalName:FAVORITES_LIST_ITEM,portalProps:product},React.createElement("div",{className:styles.root},React.createElement(Link,{className:styles.imageContainer,component:"div",href:productLink,"aria-hidden":true},React.createElement(ProductImage,{src:product.featuredImageBaseUrl,resolutions:gridResolutions})),React.createElement("div",{className:styles.infoContainer},React.createElement("div",{className:classNames(styles.infoContainerRow)},React.createElement("div",{className:styles.titleWrapper},React.createElement(SurroundPortals,{portalName:FAVORITES_PRODUCT_NAME,portalProps:commonPortalProps},React.createElement(TextLink,{href:productLink,tag:"span",className:styles.titleContainer},React.createElement("span",{className:styles.title// eslint-disable-next-line react/no-danger
|
|
14
|
-
,dangerouslySetInnerHTML:{__html:"".concat(product.name)}})))),React.createElement("div",{className:styles.removeContainer},React.createElement(Remove,{onClick:remove}))),React.createElement(ItemCharacteristics,{characteristics:characteristics}),React.createElement(StockInfoLists,{product:product}),React.createElement("div",{className:styles.infoContainerRow},React.createElement("div",{className:styles.quantityContainer},React.createElement(SurroundPortals,{portalName:FAVORITES_QUANTITY,portalProps:commonPortalProps},React.createElement(ItemQuantity,{quantity:internalQuantity,onChange:handleChangeQuantity})),React.createElement(SurroundPortals,{portalName:FAVORITES_PRODUCT_PRICE,portalProps:commonPortalProps},React.createElement("div",{className:styles.priceContainer},hasStrikePrice?React.createElement(PriceStriked,{value:defaultPrice,currency:currency}):null,React.createElement(Price,{currency:currency,discounted:hasStrikePrice,taxDisclaimer:true,unitPrice:price}),React.createElement(PriceInfo,{product:product,currency:currency,className:styles.priceInfo})))),React.createElement(SurroundPortals,{portalName:FAVORITES_ADD_TO_CART,portalProps:ctaPortalProps},React.createElement(AddToCart,{onClick:handleAddToCart,isLoading:false,isDisabled:isDisabled,"aria-label":i18n.text('product.add_to_cart')}))),React.createElement(SurroundPortals,{portalName:FAVORITES_NOTES,portalProps:commonPortalProps},React.createElement(ItemNotes,{notes:notes,onClickDeleteComment:handleDeleteComment,onClickOpenComment:handleOpenComment,notesButtonRef:notesButtonRef})))));};FavoriteItem.defaultProps={isBaseProduct:true,isOrderable:true,isRopeProductOrderable:true,hasVariants:false,notes:undefined,quantity:1};export default connect(makeMapStateToProps,mapDispatchToProps)(FavoriteItem);
|
|
13
|
+
notesButtonRef.current.focus();}broadcastLiveMessage('favorites.comments.removed');},300);},[listId,product.id,quantity,updateFavoriteItem]);return React.createElement(ProductListEntryProvider,{productId:product.id},React.createElement(SurroundPortals,{portalName:FAVORITES_LIST_ITEM,portalProps:product},React.createElement("div",{className:styles.root},React.createElement(Link,{className:styles.imageContainer,component:"div",href:productLink,"aria-hidden":true},React.createElement(ProductImage,{src:product.featuredImageBaseUrl,resolutions:gridResolutions})),React.createElement("div",{className:styles.infoContainer},React.createElement("div",{className:classNames(styles.infoContainerRow)},React.createElement("div",{className:styles.titleWrapper},React.createElement(SurroundPortals,{portalName:FAVORITES_PRODUCT_NAME,portalProps:commonPortalProps},React.createElement(TextLink,{href:productLink,tag:"span",className:styles.titleContainer},React.createElement("span",{className:styles.title// eslint-disable-next-line react/no-danger
|
|
14
|
+
,dangerouslySetInnerHTML:{__html:"".concat(product.name)}})))),React.createElement("div",{className:styles.removeContainer},React.createElement(Remove,{onClick:remove}))),React.createElement(ItemCharacteristics,{characteristics:characteristics}),React.createElement(StockInfoLists,{product:product}),React.createElement("div",{className:styles.infoContainerRow},React.createElement("div",{className:styles.quantityContainer},React.createElement(SurroundPortals,{portalName:FAVORITES_QUANTITY,portalProps:commonPortalProps},React.createElement(ItemQuantity,{quantity:internalQuantity,onChange:handleChangeQuantity})),React.createElement(SurroundPortals,{portalName:FAVORITES_PRODUCT_PRICE,portalProps:commonPortalProps},React.createElement("div",{className:styles.priceContainer},hasStrikePrice?React.createElement(PriceStriked,{value:defaultPrice,currency:currency}):null,React.createElement(Price,{currency:currency,discounted:hasStrikePrice,taxDisclaimer:true,unitPrice:price}),React.createElement(PriceInfo,{product:product,currency:currency,className:styles.priceInfo})))),React.createElement(SurroundPortals,{portalName:FAVORITES_ADD_TO_CART,portalProps:ctaPortalProps},React.createElement(AddToCart,{onClick:handleAddToCart,isLoading:false,isDisabled:isDisabled,"aria-label":i18n.text('product.add_to_cart')}))),React.createElement(SurroundPortals,{portalName:FAVORITES_NOTES,portalProps:commonPortalProps},React.createElement(ItemNotes,{notes:notes,onClickDeleteComment:handleDeleteComment,onClickOpenComment:handleOpenComment,notesButtonRef:notesButtonRef}))))));};FavoriteItem.defaultProps={isBaseProduct:true,isOrderable:true,isRopeProductOrderable:true,hasVariants:false,notes:undefined,quantity:1};export default connect(makeMapStateToProps,mapDispatchToProps)(FavoriteItem);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import _regeneratorRuntime from"@babel/runtime/regenerator";function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value;}catch(error){reject(error);return;}if(info.done){resolve(value);}else{Promise.resolve(value).then(_next,_throw);}}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value);}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err);}_next(undefined);});};}import React,{Fragment}from'react';import PropTypes from'prop-types';import{connect}from'react-redux';import{css}from'glamor';import{i18n,showModal}from'@shopgate/engage/core';import{Accordion,Card,ContextMenu,SurroundPortals}from'@shopgate/engage/components';import{makeGetFavorites}from'@shopgate/pwa-common-commerce/favorites/selectors';import{FAVORITES_LIST_CONTEXT_MENU}from"../../constants/Portals";import Item from"../Item";var styles={root:css({margin:'8px 8px 10px'}).toString(),title:css({flex:1}).toString(),divider:css({height:1,width:'calc(100% + 32px)',backgroundColor:'rgb(234, 234, 234)',marginLeft:-16,marginRight:-16,marginBottom:16}).toString()};/**
|
|
1
|
+
import _regeneratorRuntime from"@babel/runtime/regenerator";function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value;}catch(error){reject(error);return;}if(info.done){resolve(value);}else{Promise.resolve(value).then(_next,_throw);}}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value);}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err);}_next(undefined);});};}import React,{Fragment}from'react';import PropTypes from'prop-types';import{connect}from'react-redux';import{css}from'glamor';import{i18n,showModal}from'@shopgate/engage/core';import{Accordion,Card,ContextMenu,SurroundPortals}from'@shopgate/engage/components';import{ProductListTypeProvider}from'@shopgate/engage/product';import{makeGetFavorites}from'@shopgate/pwa-common-commerce/favorites/selectors';import{FAVORITES_LIST_CONTEXT_MENU}from"../../constants/Portals";import Item from"../Item";var styles={root:css({margin:'8px 8px 10px'}).toString(),title:css({flex:1}).toString(),divider:css({height:1,width:'calc(100% + 32px)',backgroundColor:'rgb(234, 234, 234)',marginLeft:-16,marginRight:-16,marginBottom:16}).toString()};/**
|
|
2
2
|
* Favorite List Label component
|
|
3
3
|
* @return {JSX}
|
|
4
4
|
*/var FavoriteListLabel=function FavoriteListLabel(_ref){var id=_ref.id,title=_ref.title,rename=_ref.rename,remove=_ref.remove;return React.createElement(Fragment,null,React.createElement("span",{className:styles.title},title),React.createElement(SurroundPortals,{portalName:FAVORITES_LIST_CONTEXT_MENU,portalProps:{id:id}},React.createElement(ContextMenu,null,React.createElement(ContextMenu.Item,{onClick:rename},i18n.text('favorites.rename_list')),React.createElement(ContextMenu.Item,{onClick:remove,disabled:id==='DEFAULT'},i18n.text('favorites.remove_list')))));};/**
|
|
@@ -12,4 +12,4 @@ import _regeneratorRuntime from"@babel/runtime/regenerator";function asyncGenera
|
|
|
12
12
|
*/var mapDispatchToProps=function mapDispatchToProps(dispatch,props){return{remove:function(){var _remove=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(id){var confirmed;return _regeneratorRuntime.wrap(function _callee$(_context){while(1){switch(_context.prev=_context.next){case 0:_context.next=2;return dispatch(showModal({message:'favorites.delete_list_modal.message',title:'favorites.delete_list_modal.title',params:{name:props.name}}));case 2:confirmed=_context.sent;if(confirmed){props.remove(id);}case 4:case"end":return _context.stop();}}},_callee);}));function remove(_x){return _remove.apply(this,arguments);}return remove;}()};};/**
|
|
13
13
|
* Favorite List component
|
|
14
14
|
* @return {JSX}
|
|
15
|
-
*/var FavoriteList=function FavoriteList(_ref3){var id=_ref3.id,name=_ref3.name,items=_ref3.items,_rename=_ref3.rename,remove=_ref3.remove,removeItem=_ref3.removeItem,_addToCart=_ref3.addToCart;return React.createElement(Card,{className:styles.root},React.createElement(Accordion,{className:"",openWithChevron:true,renderLabel:function renderLabel(){return React.createElement(FavoriteListLabel,{id:id,title:name,rename:function rename(newName){return _rename(id,newName);},remove:remove});},chevronPosition:"left",startOpened:true},React.createElement("div",{className:styles.divider}),items.length===0?React.createElement("span",null,i18n.text('favorites.empty')):null,items.filter(function(_ref4){var product=_ref4.product;return product;}).map(function(_ref5,index){var product=_ref5.product,notes=_ref5.notes,quantity=_ref5.quantity;return React.createElement("div",{key:product.id},React.createElement(Item,{product:product,notes:notes,quantity:quantity,listId:id,productId:product.id,addToCart:function addToCart(e){e.preventDefault();e.stopPropagation();return _addToCart(product,quantity);},remove:function remove(e){e.preventDefault();e.stopPropagation();removeItem(product.id);}}),index===items.length-1?null:React.createElement("div",{className:styles.divider}));})));};export default connect(makeMapStateToProps,mapDispatchToProps)(FavoriteList);
|
|
15
|
+
*/var FavoriteList=function FavoriteList(_ref3){var id=_ref3.id,name=_ref3.name,items=_ref3.items,_rename=_ref3.rename,remove=_ref3.remove,removeItem=_ref3.removeItem,_addToCart=_ref3.addToCart;return React.createElement(Card,{className:styles.root},React.createElement(Accordion,{className:"",openWithChevron:true,renderLabel:function renderLabel(){return React.createElement(FavoriteListLabel,{id:id,title:name,rename:function rename(newName){return _rename(id,newName);},remove:remove});},chevronPosition:"left",startOpened:true},React.createElement("div",{className:styles.divider}),items.length===0?React.createElement("span",null,i18n.text('favorites.empty')):null,React.createElement(ProductListTypeProvider,{type:"favoritesList"},items.filter(function(_ref4){var product=_ref4.product;return product;}).map(function(_ref5,index){var product=_ref5.product,notes=_ref5.notes,quantity=_ref5.quantity;return React.createElement("div",{key:product.id},React.createElement(Item,{product:product,notes:notes,quantity:quantity,listId:id,productId:product.id,addToCart:function addToCart(e){e.preventDefault();e.stopPropagation();return _addToCart(product,quantity);},remove:function remove(e){e.preventDefault();e.stopPropagation();removeItem(product.id);}}),index===items.length-1?null:React.createElement("div",{className:styles.divider}));}))));};export default connect(makeMapStateToProps,mapDispatchToProps)(FavoriteList);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopgate/engage",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.12.0-beta.2",
|
|
4
4
|
"description": "Shopgate's ENGAGE library.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Shopgate <support@shopgate.com>",
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@shopgate/native-modules": "1.0.0-beta.18",
|
|
19
|
-
"@shopgate/pwa-common": "7.
|
|
20
|
-
"@shopgate/pwa-common-commerce": "7.
|
|
21
|
-
"@shopgate/pwa-core": "7.
|
|
22
|
-
"@shopgate/pwa-ui-ios": "7.
|
|
23
|
-
"@shopgate/pwa-ui-material": "7.
|
|
24
|
-
"@shopgate/pwa-ui-shared": "7.
|
|
19
|
+
"@shopgate/pwa-common": "7.12.0-beta.2",
|
|
20
|
+
"@shopgate/pwa-common-commerce": "7.12.0-beta.2",
|
|
21
|
+
"@shopgate/pwa-core": "7.12.0-beta.2",
|
|
22
|
+
"@shopgate/pwa-ui-ios": "7.12.0-beta.2",
|
|
23
|
+
"@shopgate/pwa-ui-material": "7.12.0-beta.2",
|
|
24
|
+
"@shopgate/pwa-ui-shared": "7.12.0-beta.2",
|
|
25
25
|
"@stripe/react-stripe-js": "^1.1.2",
|
|
26
26
|
"@stripe/stripe-js": "^1.3.1",
|
|
27
27
|
"@virtuous/conductor": "~2.5.0",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import React from'react';import ProductListEntryContext from"../providers/ProductListEntry/context";/**
|
|
2
|
+
* Injects the ProductListEntryContext properties into the desired component. Properties will be
|
|
3
|
+
* accessible via the "productListEntry" prop.
|
|
4
|
+
*
|
|
5
|
+
* @param {Function} WrappedComponent The react component to wrap.
|
|
6
|
+
* @returns {JSX}
|
|
7
|
+
*/export default function withProductListEntry(WrappedComponent){/**
|
|
8
|
+
* The actual HOC.
|
|
9
|
+
* @param {Object} props The component props.
|
|
10
|
+
* @returns {JSX}
|
|
11
|
+
*/var WithApp=function WithApp(props){return React.createElement(ProductListEntryContext.Consumer,null,function(contextValue){return React.createElement(WrappedComponent,_extends({},props,{productListEntry:contextValue}));});};var displayName=WrappedComponent.displayName||WrappedComponent.name||'Component';WithApp.displayName="WithProductListEntry(".concat(displayName,")");return WithApp;}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import React from'react';import ProductListTypeContext from"../providers/ProductListType/context";/**
|
|
2
|
+
* Injects the ProductListTypeContext properties into the desired component. Properties will be
|
|
3
|
+
* accessible via the "productListType" prop.
|
|
4
|
+
*
|
|
5
|
+
* @param {Function} WrappedComponent The react component to wrap.
|
|
6
|
+
* @returns {JSX}
|
|
7
|
+
*/export default function withProductListType(WrappedComponent){/**
|
|
8
|
+
* The actual HOC.
|
|
9
|
+
* @param {Object} props The component props.
|
|
10
|
+
* @returns {JSX}
|
|
11
|
+
*/var WithApp=function WithApp(props){return React.createElement(ProductListTypeContext.Consumer,null,function(contextValue){return React.createElement(WrappedComponent,_extends({},props,{productListType:contextValue}));});};var displayName=WrappedComponent.displayName||WrappedComponent.name||'Component';WithApp.displayName="WithProductListType(".concat(displayName,")");return WithApp;}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{useContext}from'react';import ProductListEntryContext,{// eslint-disable-next-line import/named, no-unused-vars
|
|
2
|
+
ProductListEntryContextValue}from"../providers/ProductListEntry/context";/**
|
|
3
|
+
* Provides the properties of the ProductListEntryContext.
|
|
4
|
+
* @returns {ProductListEntryContextValue}
|
|
5
|
+
*/export default function useProductListEntry(){var context=useContext(ProductListEntryContext);return context;}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{useContext}from'react';import ProductListTypeContext,{// eslint-disable-next-line import/named, no-unused-vars
|
|
2
|
+
ProductListTypeContextValue}from"../providers/ProductListType/context";/**
|
|
3
|
+
* Provides the properties of the ProductListTypeContext.
|
|
4
|
+
* @returns {ProductListTypeContextValue}
|
|
5
|
+
*/export default function useProductListType(){var context=useContext(ProductListTypeContext);return context;}
|
package/product/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export*from'@shopgate/pwa-common-commerce/product/helpers';export*from"./helpers
|
|
|
7
7
|
export*from'@shopgate/pwa-common-commerce/product/selectors/options';export*from'@shopgate/pwa-common-commerce/product/selectors/page';export*from'@shopgate/pwa-common-commerce/product/selectors/price';export*from'@shopgate/pwa-common-commerce/product/selectors/product';export*from'@shopgate/pwa-common-commerce/product/selectors/relations';export*from'@shopgate/pwa-common-commerce/product/selectors/variants';export*from"./selectors/media";export{getProductIsFetching,makeGetProductProperties,makeGetProductEffectivityDates,makeGetProductCharacteristics,makeGetProductFeaturedMedia,makeIsProductActive,makeIsBaseProductActive}from"./selectors/product";export*from"./selectors/price";export*from"./selectors/variants";export*from"./selectors/relations";// STREAMS
|
|
8
8
|
export*from'@shopgate/pwa-common-commerce/product/streams';// COMPONENTS
|
|
9
9
|
export{default as ProductProperties}from"./components/ProductProperties/ProductProperties";export{default as MapPriceHint}from"./components/MapPriceHint";export{default as OrderQuantityHint}from"./components/OrderQuantityHint";export{default as ProductImage}from"./components/ProductImage";export{default as MediaSlider}from"./components/MediaSlider";export{default as QuantityPicker}from"./components/QuantityPicker";export{default as EffectivityDates}from"./components/EffectivityDates";export{Availability}from"./components/Availability";export{default as PriceDifference}from"./components/PriceDifference";export{FeaturedMedia,MediaImage}from"./components/Media";export{VariantSwatch}from"./components/Swatch";export{Swatches}from"./components/Swatches";export{RelationsSlider}from"./components/RelationsSlider";export{default as ProductCard}from"./components/ProductCard";export{default as ProductGridPrice}from"./components/ProductGridPrice";export{default as ProductCharacteristics}from"./components/ProductCharacteristics";export{default as Description}from"./components/Description";export{VariantAvailability}from"./components/ProductVariants";export{PriceInfo}from"./components/PriceInfo";export{ProductName}from"./components/ProductName";export{default as ProductBadges}from"./components/ProductBadges";export{default as ProductDiscountBadge}from"./components/ProductDiscountBadge";export{ProductUnitQuantityPicker,UnitQuantityPicker,CartUnitQuantityPicker}from"./components/UnitQuantityPicker";// HOCs
|
|
10
|
-
export{default as withPriceCalculation}from"./hocs/withPriceCalculation";export{default as withProductStock}from"./hocs/withProductStock";export{default as withProduct}from"./hocs/withProduct";// HOOKs
|
|
11
|
-
export{useLoadProductImage}from"./hooks/useLoadProductImage";// CONTEXTS
|
|
12
|
-
export{ProductContext,VariantContext}from"./components/context";//
|
|
10
|
+
export{default as withPriceCalculation}from"./hocs/withPriceCalculation";export{default as withProductStock}from"./hocs/withProductStock";export{default as withProduct}from"./hocs/withProduct";export{default as withProductListType}from"./hocs/withProductListType";export{default as withProductListEntry}from"./hocs/withProductListEntry";// HOOKs
|
|
11
|
+
export{useLoadProductImage}from"./hooks/useLoadProductImage";export{default as useProductListType}from"./hooks/useProductListType";export{default as useProductListEntry}from"./hooks/useProductListEntry";// CONTEXTS
|
|
12
|
+
export{ProductContext,VariantContext}from"./components/context";export{default as ProductListTypeContext}from"./providers/ProductListType/context";export{default as ProductListEntryContext}from"./providers/ProductListEntry/context";// PROVIDERS
|
|
13
|
+
export{default as ProductListTypeProvider}from"./providers/ProductListType";export{default as ProductListEntryProvider}from"./providers/ProductListEntry";// TYPES
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from'react';/* eslint-disable import/named, no-unused-vars */import{ProductListTypeContextType,ProductListTypeContextSubType}from"../ProductListType/context";/* eslint-enable import/named, no-unused-vars */ /**
|
|
2
|
+
* @typedef ProductListEntryContextValue
|
|
3
|
+
* @property {string} productId A product identifier.
|
|
4
|
+
* @property {ProductListTypeContextType} [productListType=null] Type of the active
|
|
5
|
+
* ProductListTypeContext e.g. "productSlider" or "productGrid".
|
|
6
|
+
* @property {ProductListTypeContextSubType} [productListSubType=null] Optional sub type of the
|
|
7
|
+
* active ProductListTypeContext. Depending on its usage it can make a statement about in which
|
|
8
|
+
* context the product list is used e.g. "widgets".
|
|
9
|
+
*/export{};export default React.createContext({productListType:null,productListSubType:null,productId:null});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React,{useMemo}from'react';import PropTypes from'prop-types';import useProductListType from"../../hooks/useProductListType";import Context from"./context";/**
|
|
2
|
+
* The ProductListEntryProvider is usually wrapped around components that render products and
|
|
3
|
+
* provides basic information about them.
|
|
4
|
+
*
|
|
5
|
+
* Context values can be accessed via the `useProductListEntry` hook, or injected into a class
|
|
6
|
+
* component via the `withProductListEntry` HOC. Both can be imported via `@shopgate/engage/product`
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} param The component props
|
|
9
|
+
* @param {string} param.productId Product identifier.
|
|
10
|
+
* @returns {JSX}
|
|
11
|
+
*/function ProductListEntryProvider(_ref){var children=_ref.children,productId=_ref.productId;var _useProductListType=useProductListType(),type=_useProductListType.type,subType=_useProductListType.subType;var value=useMemo(function(){return{productListType:type,productListSubType:subType,productId:productId};},[productId,subType,type]);return React.createElement(Context.Provider,{value:value},children);}ProductListEntryProvider.defaultProps={children:null};export default ProductListEntryProvider;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from'react';/* eslint-disable max-len */ /**
|
|
2
|
+
* @typedef {"productSlider"|"productGrid"|"productList"|"favoritesList"|"cart"|"liveshopping"|"pdp"|"productGallery"} ProductListTypeContextType
|
|
3
|
+
*/export{};/**
|
|
4
|
+
* @typedef {"widgets"|"category"} ProductListTypeContextSubType
|
|
5
|
+
*/export{};/* eslint-enable max-len */ /**
|
|
6
|
+
* @typedef ProductListTypeContextValue
|
|
7
|
+
* @property {ProductListTypeContextType} [type=null] Type of the active ProductListTypeContext
|
|
8
|
+
* e.g. "productSlider" or "productGrid".
|
|
9
|
+
* @property {ProductListTypeContextSubType} [subType=null] Optional sub type of the active
|
|
10
|
+
* ProductListTypeContext. Depending on its usage it can make a statement about in which context
|
|
11
|
+
* the product list is used e.g. "widgets".
|
|
12
|
+
*/export{};export default React.createContext({type:null,subType:null});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React,{useMemo}from'react';import PropTypes from'prop-types';import Context from"./context";/**
|
|
2
|
+
* The ProductListTypeProvider is usually wrapped around components that render product lists.
|
|
3
|
+
* It provides information about the type / purpose of those product lists which can be used
|
|
4
|
+
* by child components or extensions to determine how they are supposed to render their content.
|
|
5
|
+
*
|
|
6
|
+
* Context values can be accessed via the `useProductListType` hook, or injected into a class
|
|
7
|
+
* component via the `withProductListType` HOC. Both can be imported from `@shopgate/engage/product`
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} param The component props
|
|
10
|
+
* @param {string} param.type Type of the context e.g. "productSlider" or "productGrid".
|
|
11
|
+
* @param {string} param.subType Optional sub type of the context. Depending on its usage it can
|
|
12
|
+
* make a statement about in which context the product list is used e.g. "widgets".
|
|
13
|
+
* @returns {JSX}
|
|
14
|
+
*/function ProductListTypeProvider(_ref){var children=_ref.children,type=_ref.type,subType=_ref.subType;var value=useMemo(function(){return{type:type,subType:subType};},[subType,type]);return React.createElement(Context.Provider,{value:value},children);}ProductListTypeProvider.defaultProps={children:null,subType:null};export default ProductListTypeProvider;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{connect}from'react-redux';import{getProductReviewCount}from'@shopgate/pwa-common-commerce/reviews/selectors';/**
|
|
2
|
+
* Maps the contents of the state to the component props.
|
|
3
|
+
* @param {Object} state The current application state.
|
|
4
|
+
* @param {Object} props The current component props.
|
|
5
|
+
* @return {Object} The extended component props.
|
|
6
|
+
*/var mapStateToProps=function mapStateToProps(state,props){return{count:getProductReviewCount(state,props)};};/**
|
|
7
|
+
* @param {Object} next The next component props.
|
|
8
|
+
* @param {Object} prev The previous component props.
|
|
9
|
+
* @returns {boolean}
|
|
10
|
+
*/var areStatePropsEqual=function areStatePropsEqual(next,prev){if(prev.count!==next.count){return false;}return true;};export default connect(mapStateToProps,null,null,{areStatePropsEqual:areStatePropsEqual});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import{bin2hex}from'@shopgate/pwa-common/helpers/data';import I18n from'@shopgate/pwa-common/components/I18n';import{ITEM_PATH}from'@shopgate/pwa-common-commerce/product/constants/index';import{REVIEW_PREVIEW_COUNT}from'@shopgate/pwa-common-commerce/reviews/constants';import ButtonLink from'@shopgate/pwa-ui-shared/ButtonLink';import connect from"./connector";import{container}from"./style";/**
|
|
2
|
+
* @param {Object} props The component props.
|
|
3
|
+
* @returns {JSX}
|
|
4
|
+
*/var AllReviewsLink=function AllReviewsLink(props){if(!props.productId||props.count<=REVIEW_PREVIEW_COUNT){return null;}return React.createElement("div",{className:"".concat(container," engage__reviews__all-reviews-link"),"data-test-id":"showAllReviewsButton"},React.createElement(ButtonLink,{href:"".concat(ITEM_PATH,"/").concat(bin2hex(props.productId),"/reviews")},React.createElement(I18n.Text,{string:"reviews.button_all",params:props})));};AllReviewsLink.defaultProps={count:0,productId:null};export default connect(AllReviewsLink);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{css}from'glamor';import{themeConfig}from'@shopgate/pwa-common/helpers/config';var variables=themeConfig.variables;/**
|
|
2
|
+
* Styles for a link parent container.
|
|
3
|
+
* @type {string}
|
|
4
|
+
*/export var container=css({display:'flex',justifyContent:'flex-end',textAlign:'right',marginTop:-variables.gap.small,marginBottom:-variables.gap.big});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import RatingStars from'@shopgate/pwa-ui-shared/RatingStars';import Link from'@shopgate/pwa-common/components/Link';import{ITEM_PATH}from'@shopgate/pwa-common-commerce/product/constants';import{bin2hex}from'@shopgate/pwa-common/helpers/data';import appConfig from'@shopgate/pwa-common/helpers/config';import RatingCount from"../../../RatingCount";import{container}from"./style";/**
|
|
2
|
+
* The average rating and number of ratings for a product.
|
|
3
|
+
* @param {Object} rating The rating values.
|
|
4
|
+
* @param {string} productId The related product ID.
|
|
5
|
+
* @returns {JSX}
|
|
6
|
+
*/var AverageRating=function AverageRating(_ref){var average=_ref.average,count=_ref.count,productId=_ref.productId;if(!productId){return null;}return React.createElement(Link,{"data-test-id":"ratedStarsAverage",tagName:"a",href:"".concat(ITEM_PATH,"/").concat(bin2hex(productId),"/write_review"),disabled:!appConfig.showWriteReview,className:container,itemProp:"item",itemScope:true,itemType:"http://schema.org/Review"// eslint-disable-next-line jsx-a11y/aria-role
|
|
7
|
+
,role:"text"},React.createElement(RatingStars,{value:average,display:"large"}),React.createElement(RatingCount,{count:count}));};AverageRating.defaultProps={average:0,count:0,productId:null};export default AverageRating;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{css}from'glamor';var container=css({alignItems:'center',display:'flex',flexDirection:'column',justifyContent:'space-between',marginBottom:8}).toString();export{container};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import React,{Fragment}from'react';import PropTypes from'prop-types';import I18n from'@shopgate/pwa-common/components/I18n';import appConfig from'@shopgate/pwa-common/helpers/config';import AverageRating from"../AverageRating";import WriteReviewLink from"../WriteReviewLink";import*as styles from"./style";/**
|
|
2
|
+
* @return {JSX}
|
|
3
|
+
*/var NoReviews=function NoReviews(_ref){var productId=_ref.productId;return React.createElement("div",{className:styles.container,"aria-hidden":true},React.createElement(AverageRating,{productId:productId}),React.createElement("div",{className:styles.noReviews},appConfig.showWriteReview&&React.createElement(Fragment,null,React.createElement(I18n.Text,{string:"reviews.no_reviews"}),React.createElement(WriteReviewLink,{productId:productId}))));};NoReviews.defaultProps={productId:null};export default NoReviews;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{css}from'glamor';import{themeConfig}from'@shopgate/pwa-common/helpers/config';var variables=themeConfig.variables;export var container=css({fontWeight:500,margin:0});export var noReviews=css({display:'flex',justifyContent:'space-between',flexDirection:'column',alignItems:'center',marginTop:variables.gap.small,padding:"0 ".concat(variables.gap.small,"px"),textAlign:'center'});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import React from'react';import PropTypes from'prop-types';import classNames from'classnames';import appConfig from'@shopgate/pwa-common/helpers/config';import I18n from'@shopgate/pwa-common/components/I18n';import RatingNumber from'@shopgate/pwa-ui-shared/RatingNumber';import AverageRating from"../AverageRating";import WriteReviewLink from"../WriteReviewLink";import*as styles from"./style";/* eslint-disable jsx-a11y/aria-role */ /**
|
|
2
|
+
* @param {Object} props The component props.
|
|
3
|
+
* @returns {JSX}
|
|
4
|
+
*/var ReviewsExcerpt=function ReviewsExcerpt(_ref){var _classNames;var productId=_ref.productId,average=_ref.average,count=_ref.count,withTopGap=_ref.withTopGap;return React.createElement("div",{className:classNames('engage__reviews__reviews-excerpt',(_classNames={},_defineProperty(_classNames,styles.withTopGapContainer,withTopGap),_defineProperty(_classNames,styles.container,!withTopGap),_classNames)),id:"reviewsExcerpt"},React.createElement(AverageRating,{productId:productId,average:average,count:count}),React.createElement("div",{className:styles.reviewsLine,role:"text"},React.createElement(I18n.Text,{string:"reviews.rating",className:styles.averageRatingText},React.createElement(RatingNumber,{rating:average,className:styles.averageRatingNumber})),appConfig.showWriteReview&&React.createElement(WriteReviewLink,{productId:productId})));};/* eslint-enable jsx-a11y/aria-role */ReviewsExcerpt.defaultProps={average:0,count:0,productId:null,withTopGap:false};export default ReviewsExcerpt;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{css}from'glamor';import{themeConfig}from'@shopgate/pwa-common/helpers/config';var colors=themeConfig.colors,variables=themeConfig.variables;export var container=css({fontWeight:500,margin:0});export var withTopGapContainer=css(container,{marginTop:variables.gap.xbig});export var reviewsLine=css({display:'flex',justifyContent:'space-between',alignItems:'baseline',padding:"0 0 ".concat(variables.gap.small,"px"),marginBottom:-2});export var averageRatingNumber=css({// Before the custom properties the primary color was used for this class.
|
|
2
|
+
color:"var(--color-secondary, ".concat(colors.primary,")"),marginLeft:variables.gap.small}).toString();export var averageRatingText=css({marginLeft:variables.gap.big}).toString();
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import I18n from'@shopgate/pwa-common/components/I18n';import{i18n}from'@shopgate/engage/core';import{ITEM_PATH}from'@shopgate/pwa-common-commerce/product/constants';import{bin2hex}from'@shopgate/pwa-common/helpers/data';import ButtonLink from'@shopgate/pwa-ui-shared/ButtonLink';/**
|
|
2
|
+
* Link to add a review.
|
|
3
|
+
* @returns {JSX|null}
|
|
4
|
+
*/var WriteReviewLink=function WriteReviewLink(_ref){var productId=_ref.productId;return React.createElement("div",{"data-test-id":"writeReview","aria-hidden":true,className:"engage__reviews__write-review-link"},React.createElement(ButtonLink,{href:"".concat(ITEM_PATH,"/").concat(bin2hex(productId),"/write_review"),noGap:true,"aria-label":i18n.text('reviews.button_add')},React.createElement(I18n.Text,{string:"reviews.button_add"})));};export default WriteReviewLink;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from'react';import{Provider}from'react-redux';import configureStore from'redux-mock-store';import{mount}from'enzyme';import{mockedStateWithAll}from'@shopgate/pwa-common-commerce/reviews/mock';import WriteReviewLink from"./index";var mockedStore=configureStore();/**
|
|
2
|
+
* Creates component with provided store state.
|
|
3
|
+
* @param {Object} mockedState Mocked stage.
|
|
4
|
+
* @return {ReactWrapper}
|
|
5
|
+
*/var createComponent=function createComponent(mockedState){var Component=React.createElement(Provider,{store:mockedStore(mockedState)},React.createElement(WriteReviewLink,{productId:"foo"}));return mount(Component);};describe('<WriteReviewLink>',function(){var component=null;beforeEach(function(){jest.resetModules();});it('should render when current product is set',function(){component=createComponent(mockedStateWithAll);expect(component).toMatchSnapshot();expect(component.find('span').exists()).toBe(true);});});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{connect}from'react-redux';import{getBaseProductId,getProductRating}from'@shopgate/pwa-common-commerce/product/selectors/product';/**
|
|
2
|
+
* Maps the contents of the state to the component props.
|
|
3
|
+
* @param {Object} state The current application state.
|
|
4
|
+
* @param {Object} props The component props.
|
|
5
|
+
* @return {Object} The extended component props.
|
|
6
|
+
*/var mapStateToProps=function mapStateToProps(state,props){return{productId:getBaseProductId(state,props),rating:getProductRating(state,props)};};export default connect(mapStateToProps);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import NoReviews from"./components/NoReviews";import ReviewsExcerpt from"./components/ReviewsExcerpt";import connect from"./connector";/**
|
|
2
|
+
* The header of the reviews component
|
|
3
|
+
* @param {Object} rating The rating values
|
|
4
|
+
* @param {bool} withTopGap Adds additional top gap when true.
|
|
5
|
+
* @returns {JSX}
|
|
6
|
+
*/var Header=function Header(_ref){var productId=_ref.productId,rating=_ref.rating,withTopGap=_ref.withTopGap;if(!rating){return null;}var _rating$average=rating.average,average=_rating$average===void 0?0:_rating$average,_rating$count=rating.count,count=_rating$count===void 0?0:_rating$count;if(!average){return React.createElement(NoReviews,{productId:productId});}return React.createElement(ReviewsExcerpt,{productId:productId,average:average,count:count,withTopGap:withTopGap});};Header.defaultProps={productId:null,rating:null,withTopGap:false};export default connect(Header);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from'react';import{Provider}from'react-redux';import{mount}from'enzyme';import configureStore from'redux-mock-store';import mockRenderOptions from'@shopgate/pwa-common/helpers/mocks/mockRenderOptions';import{mockProductId,mockedStateWithoutReview,mockedStateWithAll}from'@shopgate/pwa-common-commerce/reviews/mock';import Header from"./index";var mockedStore=configureStore();/**
|
|
2
|
+
* Creates component with provided store state.
|
|
3
|
+
* @param {Object} mockedState Mocked stage.
|
|
4
|
+
* @param {Object|null} props Rating prop.
|
|
5
|
+
* @return {ReactWrapper}
|
|
6
|
+
*/var createComponent=function createComponent(mockedState){var props=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return mount(React.createElement(Provider,{store:mockedStore(mockedState)},React.createElement(Header,props)),mockRenderOptions);};describe('<Header />',function(){var header=null;it('should render empty',function(){var productId=mockProductId;var rating=mockedStateWithoutReview.product.productsById[productId].productData.rating;header=createComponent(mockedStateWithoutReview,{productId:productId,rating:rating});expect(header.find('Header').exists()).toBe(true);expect(header).toMatchSnapshot();expect(header.find('RatingStars').prop('value')).toEqual(0);expect(header.find('RatingCount').html()).toBe(null);});it('should render rating summary',function(){var productId=mockProductId;var rating=mockedStateWithAll.product.productsById[productId].productData.rating;header=createComponent(mockedStateWithAll,{productId:productId,rating:rating});expect(header.find('Header').exists()).toBe(true);expect(header).toMatchSnapshot();expect(header.find('RatingStars').prop('value')).toEqual(rating.average);expect(header.find('RatingCount').prop('count')).toEqual(rating.count);});it('should render null when no review is provided',function(){header=createComponent(mockedStateWithAll,{productId:'some-id'});expect(header.html()).toBe(null);});});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import I18n from'@shopgate/pwa-common/components/I18n';/**
|
|
2
|
+
* Review Author Component.
|
|
3
|
+
* @param {string} author The author's name.
|
|
4
|
+
* @returns {JSX|null}
|
|
5
|
+
*/var Author=function Author(_ref){var author=_ref.author;if(!author){return null;}return React.createElement(I18n.Text,{string:"reviews.author",params:{author:author}});};Author.defaultProps={author:null};export default Author;
|
package/reviews/components/Reviews/components/List/components/Info/components/ReviewDate/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import I18n from'@shopgate/pwa-common/components/I18n';/**
|
|
2
|
+
* Review Date Component.
|
|
3
|
+
* @param {string} date The date of a review.
|
|
4
|
+
* @returns {JSX}
|
|
5
|
+
*/var ReviewDate=function ReviewDate(_ref){var date=_ref.date;return React.createElement(I18n.Date,{timestamp:new Date(date).getTime(),format:"long"});};ReviewDate.defaultProps={date:null};export default ReviewDate;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import styles from"./style";import ReviewDate from"./components/ReviewDate";import Author from"./components/Author";/**
|
|
2
|
+
* Review Info Component.
|
|
3
|
+
* @param {Object} props The props.
|
|
4
|
+
* @returns {JSX}
|
|
5
|
+
*/var Info=function Info(_ref){var review=_ref.review;return(// eslint-disable-next-line jsx-a11y/aria-role
|
|
6
|
+
React.createElement("div",{className:styles,role:"text"},React.createElement(ReviewDate,{date:review.date}),' ',React.createElement(Author,{author:review.author})));};Info.defaultProps={review:null};export default Info;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{css}from'glamor';import{themeConfig}from'@shopgate/pwa-common/helpers/config';var colors=themeConfig.colors;export default css({color:"var(--color-text-medium-emphasis, ".concat(colors.shade3,")"),fontSize:14}).toString();
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import RatingStars from'@shopgate/pwa-ui-shared/RatingStars';import styles from"./style";/**
|
|
2
|
+
* Review Rating Component.
|
|
3
|
+
* @param {number} rate The rating value.
|
|
4
|
+
* @returns {JSX}
|
|
5
|
+
*/var Rating=function Rating(_ref){var rate=_ref.rate;return React.createElement("div",{className:styles.container},React.createElement(RatingStars,{value:rate,className:styles.stars}));};Rating.defaultProps={rate:0};export default Rating;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{css}from'glamor';var container=css({alignItems:'center',display:'flex',margin:'4px 0'}).toString();var stars=css({display:'inline-block',lineHeight:1}).toString();export default{container:container,stars:stars};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import Title from"../Title";import Rating from"../Rating";import Text from"../Text";import Info from"../Info";/**
|
|
2
|
+
* Single Review Component.
|
|
3
|
+
* @param {Object} props The component props.
|
|
4
|
+
* @returns {JSX}
|
|
5
|
+
*/var Review=function Review(_ref){var review=_ref.review;return React.createElement("div",{"data-test-id":"reviewTitle: ".concat(review.title)},React.createElement(Title,{title:review.title}),React.createElement(Rating,{rate:review.rate}),React.createElement(Text,{review:review.review}),React.createElement(Info,{review:review}));};export default Review;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import styles from"./style";/**
|
|
2
|
+
* Review Text Component
|
|
3
|
+
* @param {string} review The review text
|
|
4
|
+
* @returns {JSX|null}
|
|
5
|
+
*/var Text=function Text(_ref){var review=_ref.review;if(!review){return null;}return React.createElement("div",{className:styles},"\"".concat(review,"\""));};Text.defaultProps={review:null};export default Text;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{css}from'glamor';export default css({fontSize:14,fontStyle:'italic',whiteSpace:'pre-line'}).toString();
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import styles from"./style";/**
|
|
2
|
+
* Review Title Component.
|
|
3
|
+
* @param {string} title The title of the review.
|
|
4
|
+
* @returns {JSX}
|
|
5
|
+
*/var Title=function Title(_ref){var title=_ref.title;return React.createElement("div",{className:styles},title);};Title.defaultProps={title:null};export default Title;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{css}from'glamor';export default css({fontWeight:500,lineHeight:'20px'}).toString();
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import React,{PureComponent}from'react';import PropTypes from'prop-types';import{SurroundPortals}from'@shopgate/engage/components';import{PRODUCT_REVIEWS_ENTRY}from'@shopgate/engage/product';import Title from"./components/Title";import Rating from"./components/Rating";import Text from"./components/Text";import Info from"./components/Info";import styles from"./style";/**
|
|
2
|
+
* Review List Component.
|
|
3
|
+
*/var List=/*#__PURE__*/function(_PureComponent){_inherits(List,_PureComponent);function List(){_classCallCheck(this,List);return _possibleConstructorReturn(this,_getPrototypeOf(List).apply(this,arguments));}_createClass(List,[{key:"render",/**
|
|
4
|
+
* @returns {JSX}
|
|
5
|
+
*/value:function render(){var reviews=this.props.reviews;if(!reviews||reviews.length===0){return null;}return React.createElement("ul",{className:"engage__reviews__list"},reviews.map(function(review){return React.createElement("li",{key:review.id,className:styles,"data-test-id":"reviewTitle: ".concat(review.title)},React.createElement(SurroundPortals,{portalName:PRODUCT_REVIEWS_ENTRY,portalProps:{review:review}},React.createElement(Title,{title:review.title}),React.createElement(Rating,{rate:review.rate}),React.createElement(Text,{review:review.review}),React.createElement(Info,{review:review})));}));}}]);return List;}(PureComponent);_defineProperty(List,"defaultProps",{reviews:null});export default List;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React from'react';import{mount}from'enzyme';import mockRenderOptions from'@shopgate/pwa-common/helpers/mocks/mockRenderOptions';import List from"./index";describe('<List />',function(){var list=null;var reviews=[{id:'a',author:'',date:'2017-09-06T12:38:51.000Z',rate:100,title:'',review:'No Name and Title Lorem ipsum dolor sit amet, con… takimata sanctus est Lorem ipsum dolor sit amet.'},{id:'b',author:'username123',date:'2017-09-06T12:37:40.000Z',rate:40,title:'Test review 2 ',review:'Lorem ipsum dolor sit amet, consetetur sadipscing … takimata sanctus est Lorem ipsum dolor sit amet.'},{id:'c',author:'Carina Hoffmann',date:'2017-09-06T12:30:23.000Z',rate:60,title:'',review:'Test review'},{id:'d',author:'',date:'2017-09-06T12:30:23.000Z',rate:20,title:'',review:''}];beforeEach(function(){list=mount(React.createElement(List,{reviews:[]}),mockRenderOptions);});it('should not render when no reviews given',function(){expect(list).toMatchSnapshot();expect(list.find('Review').exists()).toBe(false);});it('should render list with reviews',function(){list.setProps({reviews:reviews});expect(list).toMatchSnapshot();expect(list.find('List > ul').exists()).toBe(true);list.find('Review').forEach(function(node,i){var ratingNode=node.find('Rating');expect(ratingNode.prop('rate')).toEqual(reviews[i].rate);expect(ratingNode.find('RatingStars').prop('value')).toEqual(reviews[i].rate);expect(node.find('Info').prop('review').date).toEqual(reviews[i].date);if(reviews[i].author){expect(node.find('Info').prop('review').author).toEqual(reviews[i].author);}if(reviews[i].title){expect(node.find('Title').prop('title')).toEqual(reviews[i].title);}if(reviews[i].review){expect(node.find('Text').prop('review')).toEqual(reviews[i].review);}});});});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{css}from'glamor';import{themeConfig}from'@shopgate/pwa-common/helpers/config';var colors=themeConfig.colors,variables=themeConfig.variables;export default css({marginLeft:variables.gap.big,padding:"".concat(variables.gap.big,"px ").concat(variables.gap.big,"px ").concat(variables.gap.big,"px 0"),borderTop:"1px solid ".concat(colors.shade7)}).toString();
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import React from'react';import PropTypes from'prop-types';import classNames from'classnames';import I18n from'@shopgate/pwa-common/components/I18n';import{greyStyle,prominentStyle}from"./style";/**
|
|
2
|
+
* @param {Object} props The component props.
|
|
3
|
+
* @returns {JSX}
|
|
4
|
+
*/var RatingCount=function RatingCount(props){var _classNames;if(!props.count){return null;}return React.createElement(I18n.Text,{string:"reviews.review_count",params:props,className:classNames((_classNames={},_defineProperty(_classNames,greyStyle,true),_defineProperty(_classNames,prominentStyle,props.prominent),_classNames),'engage__reviews__rating-count')});};RatingCount.defaultProps={count:null,prominent:false};export default RatingCount;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React from'react';import{mount}from'enzyme';import RatingCount from"./index";describe('<RatingCount>',function(){it('should render nothing when count is 0',function(){var rating=mount(React.createElement(RatingCount,{count:0}));expect(rating.find('span').exists()).toBe(false);});it('should render text when count is more than 0',function(){var rating=mount(React.createElement(RatingCount,{count:1}));expect(rating.find('span').exists()).toBe(true);});});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import{css}from'glamor';import{themeConfig}from'@shopgate/pwa-common/helpers/config';var colors=themeConfig.colors;var main={fontSize:12,margin:'0 0.5em',lineHeight:'2em'};var greyStyle=css(_extends({},main,{color:colors.shade3,fontSize:12})).toString();var prominentStyle=css(_extends({},main,{// Before the custom properties the primary color was used for this class.
|
|
2
|
+
color:"var(--color-secondary, ".concat(colors.primary,")")})).toString();export{greyStyle,prominentStyle};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from'react';import{css}from'glamor';import classNames from'classnames';import appConfig from'@shopgate/pwa-common/helpers/config';import{Link}from'@shopgate/engage/components';var styles={root:css({textAlign:'center',fontSize:'.875rem',fontWeight:300,lineHeight:1.5,padding:'0.8125rem 1rem 1rem'}).toString(),link:css({textAlign:'center',fontWeight:600,marginTop:8}).toString()};var _appConfig$reviewsInf=appConfig.reviewsInfo;_appConfig$reviewsInf=_appConfig$reviewsInf===void 0?{}:_appConfig$reviewsInf;var text=_appConfig$reviewsInf.text,linkText=_appConfig$reviewsInf.linkText,linkUrl=_appConfig$reviewsInf.linkUrl;/**
|
|
2
|
+
* The ReviewsInfo component
|
|
3
|
+
* @param {Object} props The component props
|
|
4
|
+
* @param {Array} [props.reviews] The reviews shown inside the Reviews component
|
|
5
|
+
* @returns {JSX}
|
|
6
|
+
*/var ReviewsInfo=function ReviewsInfo(){if(!text){return null;}return React.createElement("div",{className:classNames(styles.root,'engage__reviews__review_info_text')},React.createElement("div",null,text,linkText&&linkUrl&&React.createElement(Link,{href:linkUrl,className:styles.link},linkText)));};export default ReviewsInfo;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{connect}from'react-redux';import{getProductReviewsExcerpt}from'@shopgate/pwa-common-commerce/reviews/selectors';import{makeIsBaseProductActive}from'@shopgate/engage/product';/**
|
|
2
|
+
* Maps the contents of the state to the component props.
|
|
3
|
+
* @param {Object} state The current application state.
|
|
4
|
+
* @param {Object} props The component props.
|
|
5
|
+
* @return {Object} The extended component props.
|
|
6
|
+
*/var makeMapStateToProps=function makeMapStateToProps(){var isBaseProductActive=makeIsBaseProductActive();return function(state,props){return{reviews:getProductReviewsExcerpt(state,props),productActive:isBaseProductActive(state,props)};};};export default connect(makeMapStateToProps);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from'react';import PropTypes from'prop-types';import appConfig from'@shopgate/pwa-common/helpers/config';import{SurroundPortals}from'@shopgate/engage/components';import{PRODUCT_REVIEWS}from'@shopgate/engage/product';import List from"./components/List";import Header from"./components/Header";import AllReviewsLink from"./components/AllReviewsLink";import ReviewsInfo from"./components/ReviewsInfo";import styles from"./style";import connect from"./connector";/**
|
|
2
|
+
* @param {Object} props The component props.
|
|
3
|
+
* @param {Object} props.productId The id of the product, the review belongs to.
|
|
4
|
+
* @param {Array} props.reviews Reviews which should be shown in the product page.
|
|
5
|
+
* @returns {JSX}
|
|
6
|
+
*/function Reviews(_ref){var productId=_ref.productId,productActive=_ref.productActive,reviews=_ref.reviews;return React.createElement(SurroundPortals,{portalName:PRODUCT_REVIEWS,portalProps:{productId:productId}},appConfig.hasReviews&&productActive&&React.createElement("div",{className:"".concat(styles.container," engage__reviews__reviews"),"data-test-id":"reviewSection"},React.createElement(Header,{productId:productId}),React.createElement(List,{productId:productId,reviews:reviews}),React.createElement(AllReviewsLink,{productId:productId}),React.createElement(ReviewsInfo,null)));}Reviews.defaultProps={productId:null,productActive:true,reviews:null};export default connect(Reviews);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import{themeConfig as mockedConfig}from'@shopgate/pwa-common/helpers/config/mock';var mockedProduct={productId:'foo',rating:{average:0,count:0}};var mockedProductWithRating={productId:'foo',rating:{average:50,count:4}};/**
|
|
2
|
+
* Creates mocked review object.
|
|
3
|
+
* @param {string|number} id Anything that can be an id.
|
|
4
|
+
* @return {Object}
|
|
5
|
+
*/export var mockReview=function mockReview(id){return{id:id,author:'',date:'2017-09-06T12:38:51.000Z',rate:100,title:'',review:'No Name and Title Lorem ipsum dolor sit amet, con… takimata sanctus est Lorem ipsum dolor sit amet.'};};/**
|
|
6
|
+
* Mocked state with 4 reviews.
|
|
7
|
+
* @type {Object}
|
|
8
|
+
*/export var mockedStateWithAll={product:{productsById:{foo:{productData:mockedProductWithRating}}},reviews:{reviewsById:{1:mockReview(1),2:mockReview(2),3:mockReview(3),4:mockReview(4)},reviewsByProductId:{foo:{reviews:[1,2,3,4],totalReviewCount:4}}}};/**
|
|
9
|
+
* Similar to mockedStateWithAll, but contains only two reviews.
|
|
10
|
+
* @type {Object}
|
|
11
|
+
*/export var mockedStateWithTwoReviews=function(){// Must do deep clone here.
|
|
12
|
+
var mockedState=JSON.parse(JSON.stringify(mockedStateWithAll));mockedState.reviews.reviewsByProductId.foo.reviews=mockedState.reviews.reviewsByProductId.foo.reviews.slice(0,2);mockedState.reviews.reviewsByProductId.foo.totalReviewCount=2;return mockedState;}();/**
|
|
13
|
+
* Mocked state with product only. Reviews not fetched.
|
|
14
|
+
* @type {Object}
|
|
15
|
+
*/export var mockedStateWithoutReview={product:{productsById:{foo:{productData:mockedProduct}}},reviews:{reviewsById:{},reviewsByProductId:{}}};/**
|
|
16
|
+
* Mocked state without data.
|
|
17
|
+
* @type {{product: {productsById: {}}}}
|
|
18
|
+
*/export var mockedStateProductEmpty={product:{productsById:{}}};/**
|
|
19
|
+
* Sets up mocks.
|
|
20
|
+
* @param {bool} mockReviewsAvailable A feature flag "hasReviews" value.
|
|
21
|
+
* @type {Function}
|
|
22
|
+
*/export var setMocks=function setMocks(){var mockReviewsAvailable=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;jest.doMock('@shopgate/pwa-common/helpers/config',function(){return{get hasReviews(){return mockReviewsAvailable;},get showWriteReview(){return true;},themeConfig:mockedConfig};});};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from'react';import{Provider}from'react-redux';import configureStore from'redux-mock-store';import{mount}from'enzyme';import mockRenderOptions from'@shopgate/pwa-common/helpers/mocks/mockRenderOptions';import{mockedStateWithAll,mockedStateWithoutReview,mockedStateWithTwoReviews,setMocks}from'@shopgate/pwa-common-commerce/reviews/mock';var mockedStore=configureStore();/**
|
|
2
|
+
* @returns {JSX}
|
|
3
|
+
*/var Header=function Header(){return React.createElement("div",null);};var mock=Header;jest.mock("./components/Header",function(){return mock;});jest.mock('@shopgate/engage/product',function(){return{PRODUCT_REVIEWS:'product.reviews',makeIsBaseProductActive:jest.fn(function(){return function(){return true;};})};});jest.mock('@shopgate/engage/components');beforeEach(function(){jest.resetModules();});/**
|
|
4
|
+
* Creates component with provided store state.
|
|
5
|
+
* @param {Object} mockedState Mocked stage.
|
|
6
|
+
* @return {ReactWrapper}
|
|
7
|
+
*/var createComponent=function createComponent(mockedState){/* eslint-disable global-require */var Reviews=require("./index")["default"];/* eslint-enable global-require */return mount(React.createElement(Provider,{store:mockedStore(mockedState)},React.createElement(Reviews,{productId:"foo"})),mockRenderOptions);};describe('<Reviews />',function(){var component=null;it('should render when no reviews and rating given',function(){setMocks();component=createComponent(mockedStateWithoutReview);expect(component).toMatchSnapshot();expect(component.find('Header').exists()).toBe(true);expect(component.find('List').exists()).toBe(true);expect(component.find('AllReviewsLink').exists()).toBe(true);});it('should render reviews, header and all reviews link',function(){setMocks();component=createComponent(mockedStateWithAll);expect(component).toMatchSnapshot();expect(component.find('Header').exists()).toBe(true);expect(component.find('List').exists()).toBe(true);expect(component.find('AllReviewsLink').find('div').exists()).toBe(true);});it('should render reviews, header, but no all reviews link',function(){setMocks();component=createComponent(mockedStateWithTwoReviews);expect(component).toMatchSnapshot();expect(component.find('Header').exists()).toBe(true);expect(component.find('List').exists()).toBe(true);expect(component.find('AllReviewsLink').find('div').exists()).toBe(false);});it('should not render when feature flag is off',function(){setMocks(false);component=createComponent(mockedStateWithAll);expect(component).toMatchSnapshot();expect(component.find('Header').exists()).toBe(false);expect(component.find('List').exists()).toBe(false);expect(component.find('AllReviewsLink').exists()).toBe(false);});});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{css}from'glamor';import{themeConfig}from'@shopgate/pwa-common/helpers/config';var variables=themeConfig.variables;var container=css({marginBottom:variables.gap.small});export default{container:container};
|
package/reviews/index.js
CHANGED
|
@@ -3,4 +3,5 @@ export{default as fetchProductReviews}from'@shopgate/pwa-common-commerce/reviews
|
|
|
3
3
|
export*from'@shopgate/pwa-common-commerce/reviews/constants/index';export*from'@shopgate/pwa-common-commerce/reviews/constants/Pipelines';export*from'@shopgate/pwa-common-commerce/reviews/constants/Portals';// SELECTORS
|
|
4
4
|
export*from'@shopgate/pwa-common-commerce/reviews/selectors';// STREAMS
|
|
5
5
|
export*from'@shopgate/pwa-common-commerce/reviews/streams';// MOCKS
|
|
6
|
-
export*from'@shopgate/pwa-common-commerce/reviews/mock'
|
|
6
|
+
export*from'@shopgate/pwa-common-commerce/reviews/mock';// COMPONENTS
|
|
7
|
+
export{default as Reviews}from"./components/Reviews";
|