diff --git a/all/pom.xml b/all/pom.xml
index 7214e3ace8..f357f5734d 100644
--- a/all/pom.xml
+++ b/all/pom.xml
@@ -21,7 +21,7 @@
com.adobe.commerce.cif
core-cif-components-parent
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
../parent/pom.xml
@@ -29,7 +29,7 @@
core-cif-components-all
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
content-package
AEM CIF Core Components - All
diff --git a/bundles/core/pom.xml b/bundles/core/pom.xml
index 05ddf856dc..2407426af0 100644
--- a/bundles/core/pom.xml
+++ b/bundles/core/pom.xml
@@ -20,7 +20,7 @@
com.adobe.commerce.cif
core-cif-components-parent
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
../../parent/pom.xml
@@ -28,7 +28,7 @@
core-cif-components-core
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
bundle
AEM CIF Core Components - Core Bundle
diff --git a/bundles/core/src/main/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImpl.java b/bundles/core/src/main/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImpl.java
index 617818c02c..43a09bc67b 100644
--- a/bundles/core/src/main/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImpl.java
+++ b/bundles/core/src/main/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImpl.java
@@ -50,7 +50,9 @@ public class ProductListImpl implements ProductList {
private static final Logger LOGGER = LoggerFactory.getLogger(ProductListImpl.class);
private static final boolean SHOW_TITLE_DEFAULT = true;
+ private static final boolean SHOW_IMAGE_DEFAULT = true;
private static final int PAGE_SIZE_DEFAULT = 6;
+ private static final String CATEGORY_IMAGE_FOLDER = "catalog/category/";
@Self
private SlingHttpServletRequest request;
@@ -70,8 +72,11 @@ public class ProductListImpl implements ProductList {
private Page productPage;
private CategoryInterface category;
private boolean showTitle;
+ private boolean showImage;
private MagentoGraphqlClient magentoGraphqlClient;
+ private String mediaBaseUrl;
+
private int navPageCursor = 1;
private int navPagePrev;
private int navPageNext;
@@ -82,6 +87,7 @@ public class ProductListImpl implements ProductList {
private void initModel() {
// read properties
showTitle = properties.get(PN_SHOW_TITLE, currentStyle.get(PN_SHOW_TITLE, SHOW_TITLE_DEFAULT));
+ showImage = properties.get(PN_SHOW_IMAGE, currentStyle.get(PN_SHOW_IMAGE, SHOW_IMAGE_DEFAULT));
navPageSize = properties.get(PN_PAGE_SIZE, currentStyle.get(PN_PAGE_SIZE, PAGE_SIZE_DEFAULT));
setNavPageCursor();
@@ -142,6 +148,19 @@ public int getNextNavPage() {
return this.navPageNext;
}
+ @Override
+ public String getImage() {
+ if (StringUtils.isEmpty(category.getImage())) {
+ return StringUtils.EMPTY;
+ }
+ return mediaBaseUrl + CATEGORY_IMAGE_FOLDER + category.getImage();
+ }
+
+ @Override
+ public boolean showImage() {
+ return showImage;
+ }
+
@Override
public int getPreviousNavPage() {
return this.navPagePrev;
@@ -203,11 +222,16 @@ private CategoryTreeQueryDefinition generateProductListQuery() {
.id()
.description()
.name()
+ .image()
.productCount()
.products(pArgs, categoryProductsQuery -> categoryProductsQuery.items(generateProductQuery()).totalCount());
return categoryTreeQueryDefinition;
}
+ private StoreConfigQueryDefinition generateStoreConfigQuery() {
+ return q -> q.secureBaseMediaUrl();
+ }
+
/* --- Utility methods --- */
/**
@@ -223,13 +247,20 @@ private CategoryInterface fetchCategory(int categoryId) {
QueryQuery.CategoryArgumentsDefinition searchArgs = q -> q.id(categoryId);
CategoryTreeQueryDefinition queryArgs = generateProductListQuery();
- String queryString = Operations.query(query -> query.category(searchArgs, queryArgs)).toString();
+ String queryString = Operations.query(query -> query
+ .category(searchArgs, queryArgs)
+ .storeConfig(generateStoreConfigQuery())).toString();
// Send GraphQL request
GraphqlResponse response = magentoGraphqlClient.execute(queryString);
// Get category & product list from response
Query rootQuery = response.getData();
+
+ // GraphQL API provides only file name of the category image, but not the full url. We need the mediaBaseUrl to construct the full
+ // path.
+ mediaBaseUrl = rootQuery.getStoreConfig().getSecureBaseMediaUrl();
+
return rootQuery.getCategory();
}
diff --git a/bundles/core/src/main/java/com/adobe/cq/commerce/core/components/models/productlist/ProductList.java b/bundles/core/src/main/java/com/adobe/cq/commerce/core/components/models/productlist/ProductList.java
index 944badda50..906a758435 100644
--- a/bundles/core/src/main/java/com/adobe/cq/commerce/core/components/models/productlist/ProductList.java
+++ b/bundles/core/src/main/java/com/adobe/cq/commerce/core/components/models/productlist/ProductList.java
@@ -29,6 +29,11 @@ public interface ProductList {
*/
String PN_SHOW_TITLE = "showTitle";
+ /**
+ * Name of the boolean resource property indicating if the product list should render the category image.
+ */
+ String PN_SHOW_IMAGE = "showImage";
+
/**
* Name of the String resource property indicating number of products to render on front-end.
*/
@@ -75,6 +80,14 @@ default int getNextNavPage() {
throw new UnsupportedOperationException();
}
+ default String getImage() {
+ throw new UnsupportedOperationException();
+ }
+
+ default boolean showImage() {
+ throw new UnsupportedOperationException();
+ }
+
default int getPreviousNavPage() {
throw new UnsupportedOperationException();
}
diff --git a/bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImplTest.java b/bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImplTest.java
index 2824a535cd..6d26977543 100644
--- a/bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImplTest.java
+++ b/bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImplTest.java
@@ -31,6 +31,7 @@
import com.adobe.cq.commerce.core.components.models.productlist.ProductList;
import com.adobe.cq.commerce.core.components.models.productlist.ProductListItem;
import com.adobe.cq.commerce.magento.graphql.CategoryInterface;
+import com.adobe.cq.commerce.magento.graphql.CategoryTree;
import com.adobe.cq.commerce.magento.graphql.ProductInterface;
import com.adobe.cq.commerce.magento.graphql.Query;
import com.adobe.cq.commerce.magento.graphql.gson.QueryDeserializer;
@@ -59,6 +60,9 @@ public void setUp() throws Exception {
categoryQueryResult = rootQuery.getCategory();
Whitebox.setInternalState(this.slingModel, "category", categoryQueryResult);
+ String mediaBaseUrl = rootQuery.getStoreConfig().getSecureBaseMediaUrl();
+ Whitebox.setInternalState(this.slingModel, "mediaBaseUrl", mediaBaseUrl);
+
// AEM page
productPage = mock(Page.class);
when(productPage.getLanguage(false)).thenReturn(Locale.US);
@@ -80,6 +84,24 @@ public void getTitle() {
Assert.assertEquals(categoryQueryResult.getName(), title);
}
+ @Test
+ public void getImage() {
+ String image = this.slingModel.getImage();
+
+ Assert.assertEquals("https://my-magento.hostname/media/catalog/category/timeless.jpg", image);
+ }
+
+ @Test
+ public void getImageWhenMissingInResponse() {
+ ProductList list = new ProductListImpl();
+ CategoryTree category = mock(CategoryTree.class);
+ when(category.getImage()).thenReturn("");
+ Whitebox.setInternalState(list, "category", category);
+
+ String image = list.getImage();
+ Assert.assertEquals("", image);
+ }
+
@Test
public void getProducts() {
Collection products = this.slingModel.getProducts();
diff --git a/bundles/core/src/test/resources/graphql/magento-graphql-category-result.json b/bundles/core/src/test/resources/graphql/magento-graphql-category-result.json
index d8e7c1a062..71152c17a5 100644
--- a/bundles/core/src/test/resources/graphql/magento-graphql-category-result.json
+++ b/bundles/core/src/test/resources/graphql/magento-graphql-category-result.json
@@ -3,6 +3,7 @@
"id": 6,
"name": "Running",
"product_count": 8,
+ "image": "timeless.jpg",
"products": {
"items": [
{
@@ -98,5 +99,8 @@
],
"total_count": 13
}
+ },
+ "storeConfig": {
+ "secure_base_media_url": "https://my-magento.hostname/media/"
}
}
\ No newline at end of file
diff --git a/parent/pom.xml b/parent/pom.xml
index 732cb2a6c7..944f73f87e 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -21,7 +21,7 @@
com.adobe.commerce.cif
core-cif-components-parent
pom
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
AEM CIF Core Components - Parent
Parent POM for AEM CIF Core Components
diff --git a/pom.xml b/pom.xml
index 5bca66b6ff..6ba95d2ff4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
com.adobe.commerce.cif
core-cif-components-reactor
pom
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
AEM CIF Core Components Reactor
Reactor POM for AEM CIF Core Components
@@ -33,7 +33,7 @@
com.adobe.commerce.cif
core-cif-components-parent
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
parent/pom.xml
diff --git a/ui.apps/pom.xml b/ui.apps/pom.xml
index daa46f4caf..6cf7df92f0 100644
--- a/ui.apps/pom.xml
+++ b/ui.apps/pom.xml
@@ -20,14 +20,14 @@
com.adobe.commerce.cif
core-cif-components-parent
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
../parent/pom.xml
core-cif-components-apps
- 0.1.1-SNAPSHOT
+ 0.2.0-SNAPSHOT
content-package
AEM CIF Core Components - Content Package for apps
diff --git a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/README.md b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/README.md
index e505f3df1f..5a871fb4aa 100644
--- a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/README.md
+++ b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/README.md
@@ -23,6 +23,7 @@ for a category are retrieved from Magento via GraphQL. The main usage of this co
* Support for pagination
* Configurable number of products on one page
* Configurable category title display
+* Displays category image, if set in Magento and enabled in design dialog
* Client-side loaded prices using GraphQL
### Use Object
@@ -37,6 +38,7 @@ This component is targeted for a category page listing products of a category.
The following configuration properties are used:
1. `./showTitle` - controls the visibility of the product category title
+2. `./showImage` - controls the visibility of the product category image
### Edit Dialog Properties
@@ -53,6 +55,7 @@ BLOCK category
ELEMENT category__pagination
ELEMENT category__placeholder
ELEMENT category__categoryTitle
+ ELEMENT category__image
BLOCK gallery
ELEMENT gallery__root
diff --git a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/_cq_design_dialog/.content.xml b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/_cq_design_dialog/.content.xml
index 05a49b353f..b22d6a8340 100644
--- a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/_cq_design_dialog/.content.xml
+++ b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/_cq_design_dialog/.content.xml
@@ -26,6 +26,14 @@
text="Show title"
uncheckedValue="false"
value="true"/>
+
diff --git a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/clientlibs/dist/css/productlist-aem.css b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/clientlibs/dist/css/productlist-aem.css
index 4b042601b5..094d22bb10 100644
--- a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/clientlibs/dist/css/productlist-aem.css
+++ b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/clientlibs/dist/css/productlist-aem.css
@@ -68,3 +68,13 @@
cursor: default;
touch-action: none;
}
+
+.category__image {
+ min-height: 460px;
+ padding: 20px 0;
+ margin-bottom: 40px;
+ background: rgb(var(--venia-grey)) 50% no-repeat;
+ background-size: cover;
+ position: relative;
+ text-align: center;
+}
diff --git a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/image.html b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/image.html
new file mode 100644
index 0000000000..bdc4c17590
--- /dev/null
+++ b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/image.html
@@ -0,0 +1,18 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/productlist.html b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/productlist.html
index 163d8571a7..9f6e27a4f5 100644
--- a/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/productlist.html
+++ b/ui.apps/src/main/content/jcr_root/apps/core/cif/components/commerce/productlist/v1/productlist/productlist.html
@@ -13,6 +13,7 @@
-->
+
+