+
+
+
+
+
\ No newline at end of file
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/location-details/v2/location-details/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/location-details/v2/location-details/README.md
index 0fdb51edb..2be64a401 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/location-details/v2/location-details/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/location-details/v2/location-details/README.md
@@ -10,7 +10,7 @@ Component for adding content metadata to a Location and Badge config info which
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: review
* **Showcase**: [/content/aemdesign-showcase/en/component/details/location-details](/content/aemdesign-showcase/en/component/details/location-details.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/details/location-details/v2/location-details](/crx/de/#/apps/aemdesign/components/details/location-details/v2/location-details)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/news-details/v2/news-details/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/news-details/v2/news-details/README.md
index 65314f966..ed8882ce8 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/news-details/v2/news-details/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/news-details/v2/news-details/README.md
@@ -10,7 +10,7 @@ Component for adding content metadata to a News and Badge config info which is u
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v1
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/details/news-details](/content/aemdesign-showcase/en/component/details/news-details.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/details/news-details/v2/news-details](/crx/de/#/apps/aemdesign/components/details/news-details/v2/news-details)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/news-details/v2/news-details/badge.cardImageTitleCategoryActionDate.js b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/news-details/v2/news-details/badge.cardImageTitleCategoryActionDate.js
deleted file mode 100644
index 7aca672db..000000000
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/news-details/v2/news-details/badge.cardImageTitleCategoryActionDate.js
+++ /dev/null
@@ -1,17 +0,0 @@
-use(function () {
- return {
- fields: [
- {'title': { }},
- {'taglist': { }},
- {'action': { }},
- {
- 'date': {
- 'config': {
- fieldKeyValue: 'newsDateStatusText',
- fieldKeyContent: 'newsDateStatusText'
- }
- }
- }
- ]
- };
-});
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/page-details/v2/page-details/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/page-details/v2/page-details/README.md
index b5f1a3c72..00235e302 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/page-details/v2/page-details/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/details/page-details/v2/page-details/README.md
@@ -10,7 +10,7 @@ Component for adding content metadata to a page and Badge config info which is u
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/details/page-details](/content/aemdesign-showcase/en/component/details/page-details.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/details/page-details/v2/page-details](/crx/de/#/apps/aemdesign/components/details/page-details/v2/page-details)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/article/v2/article/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/article/v2/article/README.md
index f4b7e8ca6..0ac4015c7 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/article/v2/article/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/article/v2/article/README.md
@@ -10,7 +10,7 @@ Component for adding a article section to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/article](/content/aemdesign-showcase/en/component/layout/article.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/article/v2/article](/crx/de/#/apps/aemdesign/components/layout/article/v2/article)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/aside/v2/aside/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/aside/v2/aside/README.md
index 8b3c8e1de..ffd7dd0e3 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/aside/v2/aside/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/aside/v2/aside/README.md
@@ -10,7 +10,7 @@ Component for adding a Aside to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/aside](/content/aemdesign-showcase/en/component/layout/aside.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/aside/v2/aside](/crx/de/#/apps/aemdesign/components/layout/aside/v2/aside)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/.content.xml
index 38c45a90b..f184db425 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/.content.xml
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/.content.xml
@@ -3,6 +3,6 @@
cq:isContainer="{Boolean}false"
jcr:primaryType="cq:Component"
jcr:title="Breadcrumb"
- cq:icon="menu"
+ cq:icon="breadcrumbNavigation"
sling:resourceSuperType="aemdesign/components/layout/breadcrumb/v2/breadcrumb"
componentGroup="AEM.Design - Layout"/>
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb/.content.xml
index f984582f4..d6c8d191c 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb/.content.xml
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb/.content.xml
@@ -3,5 +3,5 @@
cq:isContainer="{Boolean}false"
jcr:primaryType="cq:Component"
jcr:title="Breadcrumb (v2)"
- cq:icon="menu"
+ cq:icon="breadcrumbNavigation"
componentGroup="hidden"/>
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb/README.md
index 89e0db906..c4712cbc9 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb/README.md
@@ -10,7 +10,7 @@ Component for adding a Breadcrumb to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/breadcrumb](/content/aemdesign-showcase/en/component/layout/breadcrumb.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb](/crx/de/#/apps/aemdesign/components/layout/breadcrumb/v2/breadcrumb)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/colctrl/v2/colctrl/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/colctrl/v2/colctrl/README.md
index b93652f84..5142ac198 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/colctrl/v2/colctrl/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/colctrl/v2/colctrl/README.md
@@ -10,7 +10,7 @@ Component for adding a Columns to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v1
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/colctrl](/content/aemdesign-showcase/en/component/layout/colctrl.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/colctrl/v2/colctrl](/crx/de/#/apps/aemdesign/components/layout/colctrl/v2/colctrl)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblock/v2/contentblock/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblock/v2/contentblock/README.md
index d31897d76..01995da89 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblock/v2/contentblock/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblock/v2/contentblock/README.md
@@ -10,7 +10,7 @@ Component for adding a Content Block section to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/contentblock](/content/aemdesign-showcase/en/component/layout/contentblock.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/contentblock/v2/contentblock](/crx/de/#/apps/aemdesign/components/layout/contentblock/v2/contentblock)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblocklock/v2/contentblocklock/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblocklock/v2/contentblocklock/README.md
index 8cd6f7b2e..c74dde592 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblocklock/v2/contentblocklock/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblocklock/v2/contentblocklock/README.md
@@ -10,7 +10,7 @@ Component for adding a Content Block that is locked to admin to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/contentblocklock](/content/aemdesign-showcase/en/component/layout/contentblocklock.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/contentblocklock/v2/contentblocklock](/crx/de/#/apps/aemdesign/components/layout/contentblocklock/v2/contentblocklock)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblockmenu/v2/contentblockmenu/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblockmenu/v2/contentblockmenu/README.md
index 98e5fbcbc..eb7dcc466 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblockmenu/v2/contentblockmenu/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contentblockmenu/v2/contentblockmenu/README.md
@@ -10,7 +10,7 @@ Component for adding a Content Block Menu section to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/contentblockmenu](/content/aemdesign-showcase/en/component/layout/contentblockmenu.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/contentblockmenu/v2/contentblockmenu](/crx/de/#/apps/aemdesign/components/layout/contentblockmenu/v2/contentblockmenu)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contenttabs/v2/contenttabs/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contenttabs/v2/contenttabs/README.md
index 42562019f..fc21a4ab2 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contenttabs/v2/contenttabs/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/contenttabs/v2/contenttabs/README.md
@@ -10,7 +10,7 @@ Component for adding a Content Tabs section to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/contenttabs](/content/aemdesign-showcase/en/component/layout/contenttabs.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/contenttabs/v2/contenttabs](/crx/de/#/apps/aemdesign/components/layout/contenttabs/v2/contenttabs)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/footer/v2/footer/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/footer/v2/footer/README.md
index 301a7cd7c..3f56d060a 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/footer/v2/footer/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/footer/v2/footer/README.md
@@ -10,7 +10,7 @@ Component for adding a footer section to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/footer](/content/aemdesign-showcase/en/component/layout/footer.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/footer/v2/footer](/crx/de/#/apps/aemdesign/components/layout/footer/v2/footer)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/header/v2/header/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/header/v2/header/README.md
index e109a5f19..c64086324 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/header/v2/header/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/header/v2/header/README.md
@@ -10,7 +10,7 @@ Component for adding a header section to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/header](/content/aemdesign-showcase/en/component/layout/header.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/header/v2/header](/crx/de/#/apps/aemdesign/components/layout/header/v2/header)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/navbar/v2/navbar/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/navbar/v2/navbar/README.md
index feaa155c5..b81f0d1a6 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/navbar/v2/navbar/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/layout/navbar/v2/navbar/README.md
@@ -10,7 +10,7 @@ Component for adding a Navbar section to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/layout/navbar](/content/aemdesign-showcase/en/component/layout/navbar.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/layout/navbar/v2/navbar](/crx/de/#/apps/aemdesign/components/layout/navbar/v2/navbar)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/assetlist/v2/assetlist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/assetlist/v2/assetlist/README.md
index 21acd69df..ae4981b2e 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/assetlist/v2/assetlist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/assetlist/v2/assetlist/README.md
@@ -10,7 +10,7 @@ User for creating list of assets
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/assetlist/v2/assetlist](/content/aemdesign-showcase/en/component/lists/assetlist.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/assetlist/v2/assetlist](/crx/de/#/apps/aemdesign/components/lists/assetlist/v2/assetlist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/contactlist/v2/contactlist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/contactlist/v2/contactlist/README.md
index 1f78a0249..066ad1d3d 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/contactlist/v2/contactlist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/contactlist/v2/contactlist/README.md
@@ -10,7 +10,7 @@ User for creating list of contacts
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/contactlist/v2/contactlist](/content/aemdesign-showcase/en/component/lists/contactlist.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/contactlist/v2/contactlist](/crx/de/#/apps/aemdesign/components/lists/contactlist/v2/contactlist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/eventlist/v2/eventlist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/eventlist/v2/eventlist/README.md
index 4a90cde4a..d24284c12 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/eventlist/v2/eventlist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/eventlist/v2/eventlist/README.md
@@ -10,7 +10,7 @@ Used to create list of events
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/eventlist/v2/eventlist](/content/aemdesign-showcase/en/component/lists/newslist.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/eventlist/v2/eventlist](/crx/de/#/apps/aemdesign/components/lists/eventlist/v2/eventlist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/list/v2/list/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/list/v2/list/README.md
index 870192020..edee4f6db 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/list/v2/list/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/list/v2/list/README.md
@@ -10,7 +10,7 @@ User as a super resource type by all other lists
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/list/v2/list](/content/aemdesign-showcase/en/component/lists/list.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/list/v2/list](/crx/de/#/apps/aemdesign/components/lists/list/v2/list)
@@ -19,6 +19,11 @@ User as a super resource type by all other lists
## Features
* Allows creation of Previous and Next page on a Page that is part of a collection of pages.
+* Allow creating custom Badges by selecting:
+ * a custom template
+ * field to display
+ * pre-configured template which takes priority over other config fields
+* Allow selecting to output feed RSS or ATOM link to current list contents
# Authoring
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/listnav/v2/listnav/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/listnav/v2/listnav/README.md
index 496ae0f30..289b1033e 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/listnav/v2/listnav/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/listnav/v2/listnav/README.md
@@ -10,7 +10,7 @@ User for creating Previous and Next navigation on a page based on specified sear
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/listnav/v2/listnav](/content/aemdesign-showcase/en/component/lists/listnav.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/listnav/v2/listnav](/crx/de/#/apps/aemdesign/components/lists/listnav/v2/listnav)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/locationlist/v2/locationlist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/locationlist/v2/locationlist/README.md
index 67cdddffd..a5241343d 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/locationlist/v2/locationlist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/locationlist/v2/locationlist/README.md
@@ -10,7 +10,7 @@ Component to create List of locations, used for making maps.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/locationlist](/content/aemdesign-showcase/en/component/lists/locationlist.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/locationlist/v2/locationlist](/crx/de/#/apps/aemdesign/components/lists/locationlist/v2/locationlist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/navlist/v2/navlist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/navlist/v2/navlist/README.md
index 4c2423b41..cc455a5e3 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/navlist/v2/navlist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/navlist/v2/navlist/README.md
@@ -10,7 +10,7 @@ Component to create List navigation on page that is part of a collection of page
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/navlist](/content/aemdesign-showcase/en/component/lists/navlist.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/navlist/v2/navlist](/crx/de/#/apps/aemdesign/components/lists/navlist/v2/navlist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/newslist/v2/newslist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/newslist/v2/newslist/README.md
index 067e05382..d6d5d93ea 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/newslist/v2/newslist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/newslist/v2/newslist/README.md
@@ -10,7 +10,7 @@ Used for creating list of News Articles.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/newslist/v2/newslist](/content/aemdesign-showcase/en/component/lists/newslist.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/newslist/v2/newslist](/crx/de/#/apps/aemdesign/components/lists/newslist/v2/newslist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/pagelist/v2/pagelist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/pagelist/v2/pagelist/README.md
index 446a166cc..f3f57d980 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/pagelist/v2/pagelist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/pagelist/v2/pagelist/README.md
@@ -10,7 +10,7 @@ Used for creating list of Pages.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/pagelist/v2/pagelist](/content/aemdesign-showcase/en/component/lists/page-list.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/pagelist/v2/pagelist](/crx/de/index.jsp#/apps/aemdesign/components/lists/pagelist/v2/pagelist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/searchlist/v2/searchlist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/searchlist/v2/searchlist/README.md
index 64c911559..9acbf87e7 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/searchlist/v2/searchlist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/searchlist/v2/searchlist/README.md
@@ -10,7 +10,7 @@ Allows adding Search Results list to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/searchlist/v2/searchlist](/content/aemdesign-showcase/en/component/lists/searchlist.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/searchlist/v2/searchlist](/crx/de/#/apps/aemdesign/components/lists/searchlist/v2/searchlist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/taglist/v2/taglist/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/taglist/v2/taglist/README.md
index b35cdfe8c..c317b1806 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/taglist/v2/taglist/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/lists/taglist/v2/taglist/README.md
@@ -10,7 +10,7 @@ Allow ability to create lists made of tags, for display or filtering of lists an
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/lists/taglist/v2/taglist](/content/aemdesign-showcase/en/component/lists/page-list.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/lists/taglist/v2/taglist](/crx/de/index.jsp#/apps/aemdesign/components/lists/taglist/v2/taglist)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/audio/v2/audio/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/audio/v2/audio/README.md
index e32888404..a8c556490 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/audio/v2/audio/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/audio/v2/audio/README.md
@@ -10,7 +10,7 @@ Component for Audio controls to a page to play Audio or Video audio.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v1
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/media/audio](/content/aemdesign-showcase/en/component/media/audio.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/media/audio](/crx/de/#/apps/aemdesign/components/media/audio)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/image/v2/image/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/image/v2/image/README.md
index 8db9e7e89..0ca1a3b6e 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/image/v2/image/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/image/v2/image/README.md
@@ -10,7 +10,7 @@ Component for Images to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/media/image](/content/aemdesign-showcase/en/component/media/image.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/media/image](/crx/de/#/apps/aemdesign/components/media/image)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/video/v2/video/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/video/v2/video/README.md
index 7eaf0c0ce..5132fc341 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/video/v2/video/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/media/video/v2/video/README.md
@@ -10,7 +10,7 @@ Component for adding Assets from DAM to a page to allow playing as a video.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/media/video](/content/aemdesign-showcase/en/component/media/video.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/media/video](/crx/de/#/apps/aemdesign/components/media/video)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/addthis/sharebutton/v2/sharebutton/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/addthis/sharebutton/v2/sharebutton/README.md
index 8942d3d83..40205d8f2 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/addthis/sharebutton/v2/sharebutton/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/addthis/sharebutton/v2/sharebutton/README.md
@@ -10,7 +10,7 @@ Component for adding Online Media widgets to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/widgets/sharebutton/v2/sharebutton](/content/aemdesign-showcase/en/component/widgets/sharebutton.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/widgets/addthis/sharebutton/v2/sharebutton](/crx/de/index.jsp#/apps/aemdesign/components/widgets/addthis/sharebutton/v2/sharebutton)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/onlinemedia/v2/onlinemedia/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/onlinemedia/v2/onlinemedia/README.md
index f92e1febb..65d2890e9 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/onlinemedia/v2/onlinemedia/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/onlinemedia/v2/onlinemedia/README.md
@@ -10,7 +10,7 @@ Component for adding Online Media widgets to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v2
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/widgets/onlinemedia/v2/onlinemedia](/content/aemdesign-showcase/en/component/widgets/onlinemedia.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/widgets/onlinemedia/v2/onlinemedia](/crx/de/index.jsp#/apps/aemdesign/components/widgets/onlinemedia/v2/onlinemedia)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/search/v2/search/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/search/v2/search/README.md
index 0f6399ccc..bd9bb33e8 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/search/v2/search/README.md
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/search/v2/search/README.md
@@ -10,7 +10,7 @@ Component for adding search and quick search bar to a page.
## Information
* **Vendor**: [AEM.Design](http://aem.design)
* **Version**: v1
-* **Compatibility**: AEM 6.4
+* **Compatibility**: AEM 6.4+
* **Status**: production-ready
* **Showcase**: [/content/aemdesign-showcase/en/component/widgets/search](/content/aemdesign-showcase/en/component/widgets/search.html?wcmmode=disabled)
* **Local Code**: [/apps/aemdesign/components/widgets/search/v2/search](/crx/de/#/apps/aemdesign/components/widgets/search/v2/search)
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/.content.xml
new file mode 100755
index 000000000..cecff20f4
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/.content.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/.content.xml
new file mode 100644
index 000000000..b4f2ddd5b
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/.content.xml
@@ -0,0 +1,7 @@
+
+
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/README.md b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/README.md
new file mode 100644
index 000000000..29b07fed7
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/README.md
@@ -0,0 +1,146 @@
+Vue
+============
+
+Search component
+
+# Overview
+
+Component for adding search and quick search bar to a page.
+
+## Information
+* **Vendor**: [AEM.Design](http://aem.design)
+* **Version**: v1
+* **Compatibility**: AEM 6.4+
+* **Status**: production-ready
+* **Showcase**: [/content/aemdesign-showcase/en/component/widgets/search](/content/aemdesign-showcase/en/component/widgets/search.html?wcmmode=disabled)
+* **Local Code**: [/apps/aemdesign/components/widgets/search/v2/search](/crx/de/#/apps/aemdesign/components/widgets/search/v2/search)
+* **Source**: [github/aem-design](https://github.com/aem-design/aemdesign-aem-common/tree/master/src/main/content/jcr_root/apps/aemdesign/components/widgets/search/v2/search)
+* **Readme**: [/apps/aemdesign/components/widgets/search/v2/search](/mnt/overlay/wcm/core/content/sites/components/details.html/apps/aemdesign/components/widgets/search/v2/search)
+
+# Authoring
+
+Following section covers authoring features
+
+## Edit Dialog properties
+
+These fields are available for input by the authors. These fields are used in templates
+
+
+
+
+ Tab |
+ Field Title |
+ Field Name |
+ Default Value |
+ Description |
+
+
+
+
+ |
+ Variant |
+ variant |
+ anchor |
+ defines which variant to use |
+
+
+ Style |
+ Include: Global Style Tab |
+ |
+ |
+ common style options |
+
+
+ Accessibility |
+ Include: Global Accessibility Tab |
+ |
+ |
+ common accessibility options |
+
+
+ Link Attributes |
+ Include: Global Link Attributes Tab |
+ |
+ |
+ common link attributes |
+
+
+ Analytics |
+ Include: Global Analytics Tab |
+ |
+ |
+ common analytics options |
+
+
+
+
+
+## Design Dialog Tabs
+
+This enables creating of default values for components to be use in templates
+
+
+
+
+ Tab |
+ Field Title |
+ Field Name |
+ Default Value |
+ Description |
+
+
+
+
+ Content |
+ Includes: Content |
+ |
+ |
+ includes Content tab form Edit Dialog |
+
+
+ Style |
+ Include: Global Style Tab |
+ |
+ |
+ common style options |
+
+
+ Accessibility |
+ Include: Global Accessibility Tab |
+ |
+ |
+ common accessibility options |
+
+
+ Analytics |
+ Include: Global Analytics Tab |
+ |
+ |
+ common analytics options |
+
+
+
+
+# Variants
+
+This component has the following variants
+
+
+
+
+ Name |
+ Description |
+
+
+
+
+ Default |
+ a tag with component attributes |
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/_cq_design_dialog/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/_cq_design_dialog/.content.xml
new file mode 100644
index 000000000..dbddbc9d9
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/_cq_design_dialog/.content.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/_cq_dialog/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/_cq_dialog/.content.xml
new file mode 100644
index 000000000..d757eb401
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/_cq_dialog/.content.xml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/.content.xml
new file mode 100755
index 000000000..1c0faccaf
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/.content.xml
@@ -0,0 +1,4 @@
+
+
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/css.txt b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/css.txt
new file mode 100644
index 000000000..84edd2ef5
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/css.txt
@@ -0,0 +1,3 @@
+#base=css
+
+dialog.css
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/css/dialog.css b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/css/dialog.css
new file mode 100644
index 000000000..2647f621e
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/css/dialog.css
@@ -0,0 +1,25 @@
+.vue-dynamics {
+ padding-top: 30px;
+}
+
+.vue-dynamics-form-field:not(:last-child) {
+ margin-bottom: 20px;
+}
+
+.vue-loading {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 50px;
+ position: static;
+}
+
+.cq-RichText-editable.is-invalid {
+ border-color: #e14132;
+ box-shadow: 0 0 3px #e14132;
+ color: #e14132;
+}
+
+input[type='text'].u-coral-screenReaderOnly {
+ top: 0;
+}
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js.txt b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js.txt
new file mode 100644
index 000000000..45519ca45
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js.txt
@@ -0,0 +1,4 @@
+#base=js
+
+functions.js
+behaviour.js
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js/behaviour.js b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js/behaviour.js
new file mode 100644
index 000000000..7728409c8
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js/behaviour.js
@@ -0,0 +1,45 @@
+window.AEMDESIGN = window.AEMDESIGN || {};
+window.AEMDESIGN.components = AEMDESIGN.components || {};
+window.AEMDESIGN.components.authoring = AEMDESIGN.components.authoring || {};
+window.AEMDESIGN.components.authoring.vue = AEMDESIGN.components.authoring.vue || {};
+
+(($, Coral, ns, window, undefined) => { // NOSONAR convention for wrapping all modules
+
+ $(document).on('dialog-ready', () => {
+ const componentSelect = document.querySelector('[name="./vueComponentName"]');
+ const dialogMarker = document.querySelector('[name="./configurationMarker"]');
+
+ if (!(componentSelect || dialogMarker)) {
+ console.error('[Vue Component] Unable to find one or more required dialog elements!', componentSelect, dialogMarker);
+ return;
+ }
+
+ // Set some basic configuration values
+ const componentPath = $(dialogMarker).closest('form').attr('action');
+ const tagPath = dialogMarker.value;
+
+ componentSelect.addEventListener('change', (event) => {
+ const component = event.target.selectedItem.value;
+
+ if (component.length) {
+ ns.processComponent(component, componentPath, tagPath, dialogMarker);
+ } else {
+ ns.handleDynamicFieldsWrapper(dialogMarker);
+ }
+ });
+
+ // Set the default state of the configuration tab
+ ns.handleDynamicFieldsWrapper(dialogMarker);
+
+ // Process the dialog immediately so the configuration fields appear
+ const componentName = componentSelect.selectedItem.value;
+
+ if (componentName.length) {
+ ns.processComponent(componentName, componentPath, tagPath, dialogMarker);
+ }
+
+ // Bind any custom validation handlers
+ ns.bindCustomValidationHandlers();
+ });
+
+})($, Coral, AEMDESIGN.components.authoring.vue, window);
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js/functions.js b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js/functions.js
new file mode 100644
index 000000000..fb52fff95
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/clientlibs-author/js/functions.js
@@ -0,0 +1,593 @@
+window.AEMDESIGN = window.AEMDESIGN || {};
+window.AEMDESIGN.components = AEMDESIGN.components || {};
+window.AEMDESIGN.components.authoring = AEMDESIGN.components.authoring || {};
+window.AEMDESIGN.components.authoring.vue = AEMDESIGN.components.authoring.vue || {};
+
+(($, Coral, ns, window, undefined) => { // NOSONAR convention for wrapping all modules
+ const _version = '0.1';
+
+ // Create the loading element
+ const waitingElement = new Coral.Wait().set({ size: 'M' });
+ waitingElement.classList.add('vue-loading');
+
+ // Get the Foundation Registry instance
+ const foundationRegistry = $(window).adaptTo('foundation-registry');
+
+ // Define some core namespace values
+ ns.name = 'aemdesign.components.widgets.vue';
+ ns.version = () => _version;
+
+ let formFields = {};
+
+ /**
+ * Loads and parses a given tag to retrieve the fields and their configurations.
+ *
+ * @param {String} [path=null] Path to the tag
+ * @return {Promise
}
+ */
+ ns.getFieldsConfigurationFromTag = (path = null) => {
+ return new Promise((resolve, reject) => {
+ fetch(path, { credentials: 'include' })
+ .then((r) => r.json())
+ .then((r) => {
+ const fields = {};
+
+ for (const key of Object.keys(r)) {
+ const field = r[key];
+
+ if (typeof field === 'object') {
+ fields[key] = {
+ config : JSON.parse(atob(field.value)),
+ title : field['jcr:title'],
+ }
+ }
+ }
+
+ resolve(fields);
+ })
+ .catch(reject);
+ });
+ };
+
+ /**
+ * Retrieves the component level field configuration.
+ *
+ * @param {String} componentPath JCR location to the component
+ * @param {String} componentName Name of the selected component
+ * @param {Function} callback A callback to run after a successful response
+ */
+ ns.getComponentConfiguration = (componentPath, componentName, callback) => {
+ fetch(`${componentPath}/dynamic/${componentName}.2.json`, { credentials: 'include' })
+ .then(r => r.json())
+ .then(callback)
+ .catch(err => {
+ console.warn('[Vue Component] Failed to retrieve the saved configuration data for:', componentName, err);
+ callback({});
+ })
+ };
+
+ /**
+ * Updates and maintains the dynamic form fields and waiting state.
+ *
+ * @param {Element} dialogMarker Position in the dialog to add dynamic nodes
+ * @return {Element}
+ */
+ ns.handleDynamicFieldsWrapper = (dialogMarker) => {
+ const parentElement = dialogMarker.parentNode;
+
+ let dynamicFields = parentElement.querySelector('.vue-dynamics');
+
+ if (!dynamicFields) {
+ dynamicFields = document.createElement('div');
+ dynamicFields.setAttribute('class', 'vue-dynamics');
+
+ parentElement.appendChild(waitingElement);
+ parentElement.appendChild(dynamicFields);
+ }
+
+ // Empty out the dynamic fields wrapper
+ dynamicFields.innerHTML = '';
+
+ // Show the waiting element
+ waitingElement.show();
+
+ return dynamicFields;
+ };
+
+ /**
+ * Retrieves the component level configuration for both fields and saved data and constucts
+ *
+ * @param {String} componentName Name of the selected component
+ * @param {String} componentPath JCR location to the component
+ * @param {String} tagPath JCR location of the site tags
+ * @param {Element} dialogMarker Position in the dialog to add dynamic nodes
+ */
+ ns.processComponent = (componentName, componentPath, tagPath, dialogMarker) => {
+ ns.getFieldsConfigurationFromTag(`${tagPath}/component-dialog/vue-widgets/${componentName}.1.json`)
+ .then((fields) => {
+ const dynamicFields = ns.handleDynamicFieldsWrapper(dialogMarker);
+
+ // Attempt to retrieve the component config and parse the fields
+ ns.getComponentConfiguration(componentPath, componentName, (config) => {
+ formFields = {};
+
+ // Hide the waiting element
+ waitingElement.hide();
+
+ for (const field of Object.keys(fields)) {
+ try {
+ ns.processField(field, fields[field], config[field], componentName, tagPath, componentPath);
+ } catch (e) {
+ console.warn('[Vue Component] Failed to create form field!', e);
+ }
+ }
+
+ // Add the form fields in their original order
+ for (let i = 1; i <= Object.keys(formFields).length; i++) {
+ dynamicFields.appendChild(formFields[i]);
+ }
+
+ // Tell Coral to load all the new form elements
+ $(document).trigger('cui-contentloaded');
+ });
+ })
+ .catch(() => {
+ console.error('[Vue Component] Failed to retrieve the fields for:', componentName);
+ const dynamicFields = ns.handleDynamicFieldsWrapper(dialogMarker);
+ const fieldlessPrompt = document.createElement('p');
+ fieldlessPrompt.innerHTML = `The ${componentName} component has no configurable fields.`;
+ dynamicFields.appendChild(fieldlessPrompt);
+ waitingElement.hide();
+ });
+ };
+
+ /**
+ * Escapes the input text to prevent XSS injection in dialog fields.
+ *
+ * @param {String} text Input to escape
+ * @return {String}
+ */
+ ns.escapeHtml = (text) => {
+ const map = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ };
+
+ return text.replace(/[&<>"']/g, (m) => map[m]);
+ };
+
+ /**
+ * Generates and sets up the field required for the dialog.
+ *
+ * @param {String} field Name of the field
+ * @param {Object} data Field configuration
+ * @param {Object|String} savedValue JCR value that was saved previously
+ * @param {String} componentName Name of the selected component
+ * @param {String} tagPath JCR location of the site tags
+ * @param {String} componentPath JCR location of the Vue component
+ */
+ ns.processField = (field, data, savedValue, componentName, tagPath, componentPath) => {
+ const config = data.config;
+
+ const fieldLabel = Coral.i18n.get(data.title);
+ const fieldIdentifier = field;
+ const fieldPath = `./dynamic/${componentName}/${fieldIdentifier}`;
+ const fieldPathBase = `dynamic/${componentName}/${fieldIdentifier}`;
+ const fieldPlaceholder = config.placeholder || '';
+ const fieldTooltip = config.tooltip || false;
+ const isRequired = config.required !== undefined ? config.required : true;
+ const labelledBy = `vue_label_${fieldIdentifier}`;
+
+ let fieldConstructor = false;
+
+ switch (config.field) {
+ case 'autocomplete':
+ fieldConstructor = () => {
+ const autocompleteElement = document.createElement('div');
+ const needsMultiple = config.multiple === true;
+ const pickerSource = encodeURIComponent(`${tagPath}/${config.source}`);
+
+ autocompleteElement.innerHTML = `
+
+
+
+
+ ${savedValue && ns.generateAutocompleteTags(savedValue)}
+
+
+
+
+
+
+
+ `;
+
+ const autocomplete = autocompleteElement.children[0];
+
+ autocomplete.invalid = !savedValue || false;
+ autocomplete.multiple = needsMultiple;
+
+ return autocomplete;
+ };
+ break;
+
+ case 'fileUpload':
+ fieldConstructor = () => {
+ const fileUploadElement = document.createElement('div');
+ const hasSelectedImage = savedValue && savedValue['fileReference'];
+
+ fileUploadElement.innerHTML = `
+
+
+
+ ${hasSelectedImage ?
+ `
`
+ : ''
+ }
+
+
+
+
+
+
+ Drop an asset here.
+
+
+
+
+
+
+
+
+
+
+ `;
+
+ if (hasSelectedImage) {
+ fileUploadElement.children[0].classList.add('is-filled')
+ }
+
+ //if (isRequired) {
+ // fileUploadElement.children[0].setAttribute('required', 'required')
+ //}
+
+ return fileUploadElement;
+ };
+ break;
+
+ case 'textfield':
+ fieldConstructor = () => {
+ return new Coral.Textfield().set({
+ invalid : (!savedValue && isRequired) || false,
+ labelledBy : labelledBy,
+ name : fieldPath,
+ placeholder : fieldPlaceholder,
+ required : isRequired,
+ value : savedValue || '',
+ });
+ };
+ break;
+
+ case 'textarea':
+ fieldConstructor = () => {
+ return new Coral.Textarea().set({
+ invalid : (!savedValue && isRequired) || false,
+ labelledBy : labelledBy,
+ name : fieldPath,
+ required : isRequired,
+ value : savedValue || '',
+ });
+ };
+ break;
+
+ case 'richtext':
+ fieldConstructor = () => {
+ const escapedValue = ns.escapeHtml(savedValue || '');
+
+ const richTextElement = `
+
+
+
+
+
+
+ `;
+
+ const richText = document.createElement('div');
+ richText.setAttribute('class', 'cq-RichText richtext-container coral-DecoratedTextfield');
+
+ richText.innerHTML = richTextElement;
+
+ // Bind a change listener to the hidden input field
+ ns.bindRichTextValidation(richText);
+
+ return richText;
+ };
+ break;
+
+ case 'select':
+ fieldConstructor = () => {
+ const selectElement = new Coral.Select().set({
+ invalid : (!savedValue && isRequired) || false,
+ labelledBy : labelledBy,
+ name : fieldPath,
+ placeholder : fieldPlaceholder,
+ required : isRequired,
+ });
+
+ if (config.items) {
+ for (const item of config.items) {
+ selectElement.items.add({
+ content: {
+ innerHTML: item.label,
+ },
+
+ disabled : false,
+ selected : savedValue === item.value,
+ value : item.value,
+ });
+ }
+ }
+
+ return selectElement;
+ };
+ break;
+
+ case 'checkbox':
+ fieldConstructor = () => {
+ return new Coral.Checkbox().set({
+ invalid : (!savedValue && isRequired) || false,
+ labelledBy : labelledBy,
+ name : fieldPath,
+ required : isRequired,
+ value : savedValue || '',
+ });
+ };
+ break;
+
+ default:
+ console.warn("[Vue Component] '%s' is not a valid field type!", config.field);
+ return;
+ }
+
+ ns.createFormField(
+ fieldLabel,
+ fieldIdentifier,
+ fieldTooltip,
+ fieldConstructor,
+ config.order || false,
+ labelledBy
+ );
+ };
+
+ /**
+ * Generates any autocompletion tags needed for the picker component.
+ *
+ * @param {Array|String} values Saved JCR values or a single value
+ * @return {String}
+ */
+ ns.generateAutocompleteTags = (values) => {
+ values = values instanceof Array ? values : [values];
+
+ return values.map((value) => (
+ `${value}`
+ )).join('');
+ };
+
+ /**
+ * Generates the form field wrapper and all associated elements required for the field to work.
+ *
+ * @param {String} label Title/name of the field
+ * @param {String} identifier Unique identifier used for the field
+ * @param {Boolean|String} tooltip A small message to display
+ * @param {Function} fieldConstructor Callback to run that contains the newly generated form input
+ * @param {Number|Boolean} order Order by which the field should be added
+ * @param {String} labelIdentifier Unique identifier for the field label
+ */
+ ns.createFormField = (label, identifier, tooltip, fieldConstructor, order, labelIdentifier) => {
+ const wrapperElement = document.createElement('div');
+ wrapperElement.classList.add('coral-Form-fieldwrapper');
+ wrapperElement.classList.add('vue-dynamics-form-field');
+
+ const labelElement = document.createElement('label');
+ labelElement.setAttribute('id', labelIdentifier);
+ labelElement.classList.add('coral-Form-fieldlabel');
+ labelElement.innerText = label;
+
+ wrapperElement.appendChild(labelElement);
+
+ if (typeof fieldConstructor === 'function') {
+ const newField = fieldConstructor();
+ newField.classList.add('coral-Form-field');
+
+ wrapperElement.appendChild(newField);
+ }
+
+ if (tooltip !== false) {
+ ns.generateTooltip('infoCircle', Coral.Icon.size.SMALL, tooltip, false, wrapperElement);
+ }
+
+ // Add the form field back in order
+ const fieldsTotal = Object.keys(formFields).length + 1;
+
+ if (formFields[order]) {
+ formFields[fieldsTotal] = formFields[order];
+ }
+
+ formFields[order ? order : fieldsTotal] = wrapperElement;
+ };
+
+ /**
+ * Generates a tooltip component.
+ *
+ * @param {String} icon
+ * @param iconSize
+ * @param text
+ * @param error
+ * @param target
+ * @param bindTo
+ */
+ ns.generateTooltip = (icon, iconSize, text, error, target, bindTo) => {
+ const tooltipIcon = new Coral.Icon().set({
+ icon: icon,
+ size: iconSize,
+ });
+
+ tooltipIcon.classList.add(error ? 'coral-Form-fielderror': 'coral-Form-fieldinfo');
+
+ const tooltipElement = new Coral.Tooltip().set({
+ content: {
+ innerHTML: text,
+ },
+
+ placement : 'left',
+ target : tooltipIcon,
+ variant : Coral.Tooltip.variant[error ? 'ERROR' : 'INFO'],
+ });
+
+ target.appendChild(tooltipIcon);
+ target.appendChild(tooltipElement);
+
+ if (!bindTo) {
+ bindTo = target
+ }
+
+ bindTo.icon = tooltipIcon;
+ bindTo.tooltip = tooltipElement;
+ };
+
+ /**
+ * Binds custom validation logic to the RichText form component.
+ *
+ * @param {Element} richText Parent element
+ */
+ ns.bindRichTextValidation = (richText) => {
+ const hiddenText = richText.querySelector('input[type="hidden"]');
+ const invisibleText = richText.querySelector('input[type="text"]');
+ const richTextElement = richText.querySelector('.coral-RichText');
+
+ richTextElement.addEventListener('keyup', () => {
+ invisibleText.value = hiddenText.value;
+
+ $(invisibleText).checkValidity();
+ });
+ };
+
+ //
+ ns.bindCustomValidationHandlers = () => {
+ foundationRegistry.register('foundation.validation.validator', {
+ selector: '.richtext-container > input:text',
+
+ validate(el) {
+ const $el = $(el);
+ const $hidden = $el.parent().find('input[type=hidden]');
+ const fieldWrapper = $el.closest('.coral-Form-fieldwrapper').get(0);
+ const isRequired = $hidden.attr('required') === 'required' || $hidden.attr('aria-required') === 'true';
+
+ // Hide the field icon and tooltip
+ if (el.icon && el.tooltip) {
+ el.icon.hide();
+ el.tooltip.hide();
+ }
+
+ // Show the main icon and tooltip
+ fieldWrapper.icon.show();
+ fieldWrapper.tooltip.show();
+
+ if (isRequired && !$el.val().trim().length) {
+ return $el.message('validation.required') || Coral.i18n.get('Please fill out this field');
+ }
+
+ return null;
+ },
+
+ show(el, message) {
+ const $el = $(el);
+ const fieldWrapper = $el.closest('.coral-Form-fieldwrapper').get(0);
+
+ ns.clearValidationState($el.siblings('.coral-RichText'), el, fieldWrapper);
+
+ if (!(el.icon && el.tooltip)) {
+ ns.generateTooltip(
+ 'alert',
+ Coral.Icon.size.SMALL,
+ message,
+ true,
+ fieldWrapper,
+ el
+ );
+ } else {
+ el.icon.show();
+ el.tooltip.show();
+ }
+
+ // Hide the main icon and tooltip
+ fieldWrapper.icon.hide();
+ fieldWrapper.tooltip.hide();
+
+ $el.siblings('.coral-RichText')
+ .attr('aria-invalid', true)
+ .addClass('is-invalid', true);
+ },
+ });
+ };
+
+ //
+ ns.clearValidationState = ($el) => {
+ $el.siblings('.coral-RichText')
+ .removeAttr('aria-invalid')
+ .removeClass('is-invalid');
+ };
+
+})($, Coral, AEMDESIGN.components.authoring.vue, window);
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/variant.default.html b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/variant.default.html
new file mode 100644
index 000000000..8a31c68e9
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/variant.default.html
@@ -0,0 +1,32 @@
+
+
+
+
+ ${componentHTML @ context = 'unsafe'}
+
+
+
+
+
Vue Component Configuration
+
+
+ Name: |
+ ${componentProperties.vueComponentName} |
+
+
+
+ ${item}: |
+ ${componentProperties.configOutput[item]} |
+
+
+
+
+
+
+
Invalid component state, no Vue component has been configured yet!
+
+
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/vue.html b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/vue.html
new file mode 100644
index 000000000..0b75dcf8f
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/components/widgets/vue/v2/vue/vue.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/badge/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/badge/.content.xml
index b06d68895..7d5af521f 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/badge/.content.xml
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/badge/.content.xml
@@ -498,6 +498,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/dataSource/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/dataSource/.content.xml
new file mode 100644
index 000000000..faa526bdb
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/dataSource/.content.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/dataSource_design/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/dataSource_design/.content.xml
new file mode 100644
index 000000000..eb746d9c5
--- /dev/null
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/dataSource_design/.content.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/table/.content.xml b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/table/.content.xml
index 180d040d2..3f611ca10 100644
--- a/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/table/.content.xml
+++ b/aemdesign-aem-common/src/main/content/jcr_root/apps/aemdesign/global/dialog/touch/table/.content.xml
@@ -30,6 +30,7 @@
-
-
-
diff --git a/aemdesign-aem-core-deploy/pom.xml b/aemdesign-aem-core-deploy/pom.xml
index 1a4071602..056a77f80 100644
--- a/aemdesign-aem-core-deploy/pom.xml
+++ b/aemdesign-aem-core-deploy/pom.xml
@@ -8,7 +8,7 @@
design.aem
aemdesign-aem-core
- 2.0.420
+ 2.0.508
../pom.xml
@@ -20,7 +20,7 @@
content-package
AEM Design - Core - Deployment Package
AEM package for deploying all packages as one
- 2.0.420
+ 2.0.508
${parent.url}
diff --git a/aemdesign-aem-services/pom.xml b/aemdesign-aem-services/pom.xml
index 2c843c886..007a710b3 100755
--- a/aemdesign-aem-services/pom.xml
+++ b/aemdesign-aem-services/pom.xml
@@ -8,7 +8,7 @@
design.aem
aemdesign-aem-core
- 2.0.420
+ 2.0.508
../pom.xml
@@ -17,7 +17,7 @@
aemdesign-aem-services
- 2.0.420
+ 2.0.508
bundle
AEM Design - Core - AEM Services
Project for all AEM and OSGI Services
@@ -641,7 +641,7 @@
com.adobe.cq
core.wcm.components.core
provided
- 2.3.2
+ 2.5.0
com.adobe.cq
@@ -649,5 +649,10 @@
provided
2.3.2
+
+ org.jetbrains
+ annotations
+ 17.0.0
+
diff --git a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/ContactDetails.java b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/ContactDetails.java
index d21ce09ab..3c12a31a9 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/ContactDetails.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/ContactDetails.java
@@ -126,6 +126,7 @@ protected void ready() {
* @param sling sling instance
* @return returns map with new values
*/
+ @Override
@SuppressWarnings("Duplicates")
public Map processComponentFields(ComponentProperties componentProperties, com.day.cq.i18n.I18n i18n, SlingScriptHelper sling){
Map newFields = new HashMap();
diff --git a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/EventDetails.java b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/EventDetails.java
index 1c2dc5078..e72cde899 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/EventDetails.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/EventDetails.java
@@ -117,6 +117,7 @@ protected void ready() {
* @param sling sling instance
* @return returns map with new values
*/
+ @Override
@SuppressWarnings("Duplicates")
public Map processComponentFields(ComponentProperties componentProperties, I18n i18n, SlingScriptHelper sling) {
Map newFields = new HashMap<>();
diff --git a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/GenericDetails.java b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/GenericDetails.java
index 5d90cff48..e14291b95 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/GenericDetails.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/GenericDetails.java
@@ -1,44 +1,235 @@
package design.aem.models.v2.details;
+import com.day.cq.i18n.I18n;
+import com.day.cq.tagging.TagConstants;
+import com.day.cq.tagging.TagManager;
import com.day.cq.wcm.api.Page;
+import com.google.common.base.Throwables;
import design.aem.components.ComponentProperties;
import design.aem.models.ModelProxy;
+import design.aem.services.ContentAccess;
+import design.aem.utils.components.ComponentsUtil;
+import design.aem.utils.components.ContentFragmentUtil;
+import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
-import static design.aem.utils.components.CommonUtil.getBadgeFromSelectors;
-import static design.aem.utils.components.CommonUtil.getPageRedirect;
+import static design.aem.utils.components.CommonUtil.*;
import static design.aem.utils.components.ComponentDetailsUtil.processBadgeRequestConfig;
import static design.aem.utils.components.ComponentsUtil.*;
import static design.aem.utils.components.ConstantsUtil.*;
+import static design.aem.utils.components.ContentFragmentUtil.DEFAULT_CONTENTFRAGMENT_VARIATION;
+import static design.aem.utils.components.I18nUtil.getDefaultLabelIfEmpty;
import static design.aem.utils.components.ImagesUtil.*;
import static design.aem.utils.components.ResolverUtil.mappedUrl;
+import static design.aem.utils.components.TagUtil.getTagsAsAdmin;
+import static design.aem.utils.components.TenantUtil.resolveTenantIdFromPath;
import static java.text.MessageFormat.format;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
+
public class GenericDetails extends ModelProxy {
protected static final Logger LOGGER = LoggerFactory.getLogger(GenericDetails.class);
+ private static final String COMPONENT_DETAILS_NAME = "generic-details";
+
private static final String PAGE_META_PROPERTY_FIELDS = "metaPropertyFields";
+ private static final String DEFAULT_FORMAT_TITLE = "${title}";
+ private static final String FIELD_FORMAT_TITLE = "titleFormat";
+ private static final String FIELD_FORMATTED_TITLE = "titleFormatted";
+ private static final String FIELD_FORMATTED_TITLE_TEXT = "titleFormattedText";
+ private static final String FIELD_SUBCATEGORY = "subCategory";
+ private static final String FIELD_CATEGORY = "category";
+ private static final String FIELD_LEGACY_BADGE_CONFIG = "legacyBadgeConfig";
+ private static final String FIELD_LEGACY_BADGE_SELECTED = "legacyBadgeSelected";
+ private static final String FIELD_LEGACY_BADGE = "legacyBadge";
+ private static final String FIELD_LEGACY_BADGE_LIST = "legacyBadgeList";
+ private static final String FIELD_LEGACY_BADGE_LIST_MAPPING = "legacyBadgeListMapping";
+ private static final String FIELD_LEGACY_BADGE_CNNFIG_TAGS = "legacyBadgeConfigTags";
+ private static final String DEFAULT_TAG_LEGACY_BADGE_CONFIG = ":component-dialog/components/details/generic-details/legacy";
+
+ private static final String FIELD_CONTENTFRAGMENT_VARIATION = "variationName";
+ private static final String FIELD_CONTENTFRAGMENT_FRAGMENTPATH = "fragmentPath";
+
+ //used for backwards compatibility of details components
+ private static final String[] legacyBadgeList = new String[] {
+ "badge.cardActionIconDescription",
+ "badge.cardActionIconTitleCategoryDescription",
+ "badge.cardActionIconTitleDescription",
+ "badge.cardActionImageTitle",
+ "badge.cardActionImageTitleCategoryDescription",
+ "badge.cardActionImageTitleDescription",
+ "badge.cardHorizontalIconTitleCategoryDescriptionAction",
+ "badge.cardIcon",
+ "badge.cardIconDescription",
+ "badge.cardIconTitle",
+ "badge.cardIconTitleAction",
+ "badge.cardIconTitleCategoryDescription",
+ "badge.cardIconTitleCategoryDescriptionAction",
+ "badge.cardIconTitleDateAction",
+ "badge.cardIconTitleDateDescriptionAction",
+ "badge.cardIconTitleDescription",
+ "badge.cardIconTitleDescriptionAction",
+ "badge.cardIconTitleSubtitleDate",
+ "badge.cardIconTitleSubtitleDateDescriptionAction",
+ "badge.cardIconTitleSubtitleDescriptionAction",
+ "badge.cardImageSubtitleTitleCategoryDescriptionAction",
+ "badge.cardImageSubtitleTitleDescriptionAction",
+ "badge.cardImageTagTitleAction",
+ "badge.cardImageTitleAction",
+ "badge.cardImageTitleCategoryActionDate",
+ "badge.cardImageTitleCategoryDescription",
+ "badge.cardImageTitleCategoryDescriptionAction",
+ "badge.cardImageTitleDescription",
+ "badge.cardImageTitleDescriptionAction",
+ "badge.cardImageTitleSubtitleDescriptionAction",
+ "badge.cardTitleDescriptionAction",
+ "badge.data",
+ "badge.default",
+ "badge.icon",
+ "badge.image",
+ "badge.metadata"
+ };
+
+ //used for backwards compatibility of details components
+ private static final String[][] legacyBadgeListMapping = new String[][] {
+ new String[] {"action-icon","description"},
+ new String[] {"action-icon","title", "taglist", "description"},
+ new String[] {"action-icon","title", "description"},
+ new String[] {"action-image","title"},
+ new String[] {"action-image","title", "taglist", "description"},
+ new String[] {"action-image","title", "description"},
+ new String[] {"horizontal-icon","title", "taglist", "description", "action"},
+ new String[] {"card-icon"},
+ new String[] {"card-icon","description"},
+ new String[] {"card-icon","title"},
+ new String[] {"card-icon","title", "action"},
+ new String[] {"card-icon","title", "taglist", "description"},
+ new String[] {"card-icon","title", "taglist", "description", "action"},
+ new String[] {"card-icon","title", "startdate", "action"},
+ new String[] {"card-icon","title", "startdate", "description"},
+ new String[] {"card-icon","title", "description"},
+ new String[] {"card-icon","title", "description", "action"},
+ new String[] {"card-icon","title", "subtitle", "startdate"},
+ new String[] {"card-icon","title", "subtitle", "startdate", "description", "action"},
+ new String[] {"card-icon","title", "subtitle", "description", "action"},
+ new String[] {"card-image","subtitle", "title", "taglist", "description", "action"},
+ new String[] {"card-image","subtitle", "title", "description", "action"},
+ new String[] {"card-image","taglist", "title", "action"},
+ new String[] {"card-image","title", "action"},
+ new String[] {"card-image","title", "taglist", "action", "startdate"},
+ new String[] {"card-image","title", "taglist", "description"},
+ new String[] {"card-image","title", "taglist", "description", "action"},
+ new String[] {"card-image","title", "description"},
+ new String[] {"card-image","title", "description", "action"},
+ new String[] {"card-image","title", "subtitle", "description", "action"},
+ new String[] {"card","title", "description", "action"},
+ new String[] {"simple-data"},
+ new String[] {"default"},
+ new String[] {"simple-icon"},
+ new String[] {"simple-image"},
+ new String[] {"simple-metadata"},
+ };
protected ComponentProperties componentProperties = null;
public ComponentProperties getComponentProperties() {
return this.componentProperties;
}
+ /***
+ * main activate entry point.
+ */
@SuppressWarnings("Duplicates")
protected void ready() {
- processCommonFields();
+ com.day.cq.i18n.I18n i18n = new I18n(getRequest());
+
+ final String DEFAULT_ARIA_ROLE = "banner";
+ final String DEFAULT_TITLE_TAG_TYPE = "h1";
+ final String DEFAULT_I18N_CATEGORY = "page-detail";
+ final String DEFAULT_I18N_LABEL = "variantHiddenLabel";
+
+ // default values for the component
+ final String DEFAULT_TITLE = getPageTitle(getResourcePage(), getResource());
+ final String DEFAULT_DESCRIPTION = getResourcePage().getDescription();
+ final String DEFAULT_SUBTITLE = getResourcePage().getProperties().get(FIELD_PAGE_TITLE_SUBTITLE,"");
+ final Boolean DEFAULT_HIDE_TITLE = false;
+ final Boolean DEFAULT_HIDE_DESCRIPTION = false;
+ final Boolean DEFAULT_SHOW_BREADCRUMB = true;
+ final Boolean DEFAULT_SHOW_TOOLBAR = true;
+ final Boolean DEFAULT_SHOW_PAGE_DATE = true;
+ final Boolean DEFAULT_SHOW_PARSYS = true;
+
+ this.componentProperties = ComponentsUtil.getNewComponentProperties(this);
+
+ setComponentFields(new Object[][]{
+ {FIELD_VARIANT, DEFAULT_VARIANT},
+ {"title", DEFAULT_TITLE},
+ {FIELD_FORMAT_TITLE,""}, //tag path, will be resolved to value in processComponentFields
+ {"description", DEFAULT_DESCRIPTION},
+ {"hideDescription", DEFAULT_HIDE_DESCRIPTION},
+ {"hideTitle", DEFAULT_HIDE_TITLE},
+ {"showBreadcrumb", DEFAULT_SHOW_BREADCRUMB},
+ {"showToolbar", DEFAULT_SHOW_TOOLBAR},
+ {"showPageDate", DEFAULT_SHOW_PAGE_DATE},
+ {"showParsys", DEFAULT_SHOW_PARSYS},
+ {FIELD_LINK_TARGET, StringUtils.EMPTY, FIELD_TARGET},
+ {FIELD_PAGE_URL, getPageUrl(getResourcePage())},
+ {FIELD_PAGE_TITLE, DEFAULT_TITLE},
+ {FIELD_PAGE_TITLE_NAV, getPageNavTitle(getResourcePage())},
+ {FIELD_PAGE_TITLE_SUBTITLE, DEFAULT_SUBTITLE},
+ {TagConstants.PN_TAGS, new String[]{}},
+ {FIELD_SUBCATEGORY, new String[]{}},
+ {FIELD_ARIA_ROLE,DEFAULT_ARIA_ROLE, FIELD_ARIA_DATA_ATTRIBUTE_ROLE},
+ {FIELD_TITLE_TAG_TYPE, DEFAULT_TITLE_TAG_TYPE},
+ {"variantHiddenLabel", getDefaultLabelIfEmpty("",DEFAULT_I18N_CATEGORY,DEFAULT_I18N_LABEL,DEFAULT_I18N_CATEGORY,i18n)},
+ {FIELD_LEGACY_BADGE_LIST, legacyBadgeList},
+ {FIELD_LEGACY_BADGE_LIST_MAPPING, legacyBadgeListMapping},
+ {FIELD_LEGACY_BADGE_CNNFIG_TAGS, resolveTenantIdFromPath(getCurrentPage().getPath()).concat(DEFAULT_TAG_LEGACY_BADGE_CONFIG)},
+ {FIELD_VARIANT_FIELDS, new String[]{}},
+ {FIELD_VARIANT_FIELDS_TEMPLATE, new String[]{}},
+ {FIELD_CONTENTFRAGMENT_VARIATION, DEFAULT_CONTENTFRAGMENT_VARIATION},
+ {FIELD_CONTENTFRAGMENT_FRAGMENTPATH, ""},
+ });
+
+ componentProperties = ComponentsUtil.getComponentProperties(
+ this,
+ componentFields,
+ DEFAULT_FIELDS_STYLE,
+ DEFAULT_FIELDS_ACCESSIBILITY,
+ DEFAULT_FIELDS_ANALYTICS,
+ DEFAULT_FIELDS_DETAILS_OPTIONS);
+
+ //process content fragment content if its used
+ String fragmentPath = componentProperties.get(FIELD_CONTENTFRAGMENT_FRAGMENTPATH, "");
+ String variationName = componentProperties.get(FIELD_CONTENTFRAGMENT_VARIATION, DEFAULT_CONTENTFRAGMENT_VARIATION);
+
+ componentProperties.putAll(ContentFragmentUtil.getComponentFragmentMap(fragmentPath,variationName, getResourceResolver()));
+
+ String[] tags = componentProperties.get(TagConstants.PN_TAGS, new String[]{});
+ componentProperties.put(FIELD_CATEGORY,getTagsAsAdmin(getSlingScriptHelper(), tags, getRequest().getLocale()));
+
+ String[] subCategory = componentProperties.get(FIELD_SUBCATEGORY, new String[]{});
+ componentProperties.put(FIELD_SUBCATEGORY,getTagsAsAdmin(getSlingScriptHelper(), subCategory, getRequest().getLocale()));
+
+ processCommonFields();
+
+ //format fields
+ componentProperties.putAll(processComponentFields(componentProperties,i18n,getSlingScriptHelper()), false);
}
+ /***
+ * process common fields that details supports.
+ */
@SuppressWarnings("Duplicates")
protected void processCommonFields() {
try {
@@ -96,6 +287,7 @@ protected void processCommonFields() {
//process badge selection
String componentBadge = getBadgeFromSelectors(getRequest().getRequestPathInfo().getSelectorString());
+ Boolean badgeWasRequested = isNotEmpty(componentBadge);
String requestedBadgeTemplate = format(COMPONENT_BADGE_TEMPLATE_FORMAT, componentBadge);
if (isEmpty(componentBadge)) {
@@ -114,7 +306,9 @@ protected void processCommonFields() {
//check if component has the badge and reset if it does not
if (isEmpty(badgePath)) {
- LOGGER.error("BADGE NOT FOUND badgePath={},requestedBadgeTemplate={}",badgePath,requestedBadgeTemplate);
+ if (badgeWasRequested && !ArrayUtils.contains(legacyBadgeList,componentBadge)) {
+ LOGGER.error("LEGACY BADGE WAS REQUESTED BUT NOT FOUND IN COMPONENT AND LEGACY MAPPING NOT FOUND requestedBadgeTemplate={}",requestedBadgeTemplate);
+ }
componentBadge = DEFAULT_BADGE;
requestedBadgeTemplate = defaultBadgeTemplate;
}
@@ -128,7 +322,16 @@ protected void processCommonFields() {
componentProperties.put(DEFAULT_BACKGROUND_IMAGE_NODE_NAME, getBackgroundImageRenditions(this));
//update component properties overrides possibly from list component
- componentProperties.putAll(processBadgeRequestConfig(componentProperties, getResourceResolver(), getRequest()), true);
+ ComponentProperties badgeOverrides = processBadgeRequestConfig(componentProperties, getResourceResolver(), getRequest());
+ //if override badgeCustom is set to false remove related fields from overrides
+ if (!badgeOverrides.get(DETAILS_BADGE_CUSTOM, false)) {
+ badgeOverrides.remove(DETAILS_BADGE_CUSTOM);
+ badgeOverrides.remove(DETAILS_BADGE_FIELDS);
+ badgeOverrides.remove(DETAILS_BADGE_FIELDS_TEMPLATE);
+ badgeOverrides.remove(DETAILS_BADGE_TEMPLATE);
+ }
+ //add updated overrides
+ componentProperties.putAll(badgeOverrides, true);
//evaluate fields after badge overrides have been applied
componentProperties.evaluateExpressionFields();
@@ -136,16 +339,38 @@ protected void processCommonFields() {
//process badge config
componentProperties.putAll(processBadgeConfig(getResourcePage(), componentProperties));
+ //if custom badge being used process its config
+ if (componentProperties.get(DETAILS_BADGE_CUSTOM, false)) {
+ String badge = componentProperties.get(DETAILS_BADGE_TEMPLATE, StringUtils.EMPTY);
+
+ //get badge config
+ if (isNotEmpty(badge)) {
+ ContentAccess contentAccess = getSlingScriptHelper().getService(ContentAccess.class);
+ try (ResourceResolver adminResourceResolver = contentAccess.getAdminResourceResolver()) {
- String variant = componentProperties.get(FIELD_VARIANT, DEFAULT_VARIANT);
- //process variant selection
- if (isEmpty(variant)) {
- variant = DEFAULT_VARIANT;
+ ComponentProperties badgeConfig = getTemplateConfig(getContextObjects(this), badge, adminResourceResolver, adminResourceResolver.adaptTo(TagManager.class), DETAILS_BADGE_FIELDS_TEMPLATE, DETAILS_BADGE_FIELDS, "detailsBadge");
+ componentProperties.putAll(badgeConfig);
+
+ } catch (Exception ex) {
+ LOGGER.error(Throwables.getStackTraceAsString(ex));
+ }
+ }
}
- String variantTemplate = format(COMPONENT_VARIANT_TEMPLATE_FORMAT, variant);
- //compile variantTemplate param
- componentProperties.put(COMPONENT_VARIANT_TEMPLATE, variantTemplate);
+ //if COMPONENT_VARIANT_TEMPLATE has not been set do it now
+ if (isEmpty(componentProperties.get(COMPONENT_VARIANT_TEMPLATE, ""))) {
+
+ //only process variantTemplate if its not been set already
+ String variant = componentProperties.get(FIELD_VARIANT, DEFAULT_VARIANT);
+
+ if (isEmpty(variant)) {
+ variant = DEFAULT_VARIANT;
+ }
+
+ //compile variantTemplate param
+ String variantTemplate = getComponentVariantTemplate(getComponent(), format(COMPONENT_VARIANT_TEMPLATE_FORMAT, variant), getSlingScriptHelper());
+ componentProperties.put(COMPONENT_VARIANT_TEMPLATE, variantTemplate);
+ }
//get page metadata fields
componentProperties.put(PAGE_META_PROPERTY_FIELDS, processPageMetaProperties(getResourcePage(), getResourceResolver(), getRequest(), componentProperties));
@@ -153,13 +378,27 @@ protected void processCommonFields() {
//set canonical url
componentProperties.put(FIELD_CANONICAL_URL, mappedUrl(getResourceResolver(), getRequest(), getResourcePage().getPath()).concat(DEFAULT_EXTENTION));
+ //get legacy badge configs from tags
+ String legacyBadgeConfigTags = componentProperties.get(FIELD_LEGACY_BADGE_CNNFIG_TAGS,"");
+ if (isNotEmpty(legacyBadgeConfigTags)) {
+ Map legacyBadgeConfig = getTagsAsAdmin(
+ getSlingScriptHelper(),
+ new String[]{legacyBadgeConfigTags},
+ getRequest().getLocale(),
+ new String[]{FIELD_TAG_TEMPLATE_CONFIG_TEMPLATES,FIELD_TAG_TEMPLATE_CONFIG_FIELDS},
+ true);
+ componentProperties.put(FIELD_LEGACY_BADGE_CONFIG,legacyBadgeConfig);
+ }
+
+
+
} catch (Exception ex) {
LOGGER.error("processCommonFields: could not process fields componentProperties={}, ex={}", componentProperties, ex);
}
}
/**
- * get field template in component
+ * get field template in component.
* @return list of field resources
*/
public Map getFields() {
@@ -167,15 +406,84 @@ public Map getFields() {
}
/**
- * get template in component
+ * get template in component.
* @return list of template resources
*/
public Map getTemplates() {
return getLocalSubResourcesInSuperComponent(getComponent(), "template", getSlingScriptHelper());
}
+ /**
+ * return list of selectors if not using legacy badge convention.
+ * @return list of template resources
+ */
+ public String[] getRequestedFields() {
+ String legacyComponentBadge = getBadgeFromSelectors(getRequest().getRequestPathInfo().getSelectorString());
+
+ if (isNotEmpty(legacyComponentBadge) ) {
+ if (this.componentProperties != null) {
+ //check if config from tags being used
+ LinkedHashMap legacyBadgeConfig = componentProperties.get(FIELD_LEGACY_BADGE_CONFIG, LinkedHashMap.class);
+ if (legacyBadgeConfig != null) {
+ //check if config exist
+ for (Map.Entry entry : legacyBadgeConfig.entrySet())
+ {
+ Map config = entry.getValue();
+ if (config.containsKey("value") && config.get("value").equals(legacyComponentBadge)) {
+
+ String[] fields = new String[0];
+ String[] templates = new String[0];
+ //get config fields from tag
+ if (config.containsKey(FIELD_TAG_TEMPLATE_CONFIG_FIELDS)) {
+ Object value = config.get(FIELD_TAG_TEMPLATE_CONFIG_FIELDS);
+ if (value !=null && value.getClass().isArray()) {
+ fields = (String[]) config.get(FIELD_TAG_TEMPLATE_CONFIG_FIELDS);
+ }
+ }
+ if (config.containsKey(FIELD_TAG_TEMPLATE_CONFIG_TEMPLATES)) {
+ Object value = config.get(FIELD_TAG_TEMPLATE_CONFIG_TEMPLATES);
+ if (value !=null && value.getClass().isArray()) {
+ templates = (String[]) config.get(FIELD_TAG_TEMPLATE_CONFIG_TEMPLATES);
+ }
+ }
+ this.componentProperties.put(FIELD_LEGACY_BADGE_SELECTED, true);
+ return ArrayUtils.addAll(templates,fields);
+
+ }
+ };
+
+
+ } else {
+ String[][] legacyBadgeMapping = this.componentProperties.get(FIELD_LEGACY_BADGE_LIST_MAPPING, legacyBadgeListMapping);
+ String[] legacyBadges = this.componentProperties.get(FIELD_LEGACY_BADGE, legacyBadgeList);
+ int badgeMapIndex = ArrayUtils.indexOf(legacyBadges, legacyComponentBadge);
+ if (legacyBadgeMapping.length > badgeMapIndex) {
+ this.componentProperties.put(FIELD_LEGACY_BADGE_SELECTED, true);
+ return legacyBadgeMapping[badgeMapIndex];
+ }
+ }
+ }
+
+ }
+
+ //selectors selection overrides config
+ String[] fields = this.getSlingScriptHelper().getRequest().getRequestPathInfo().getSelectors();
+
+ if (fields.length > 0) {
+ return fields;
+ }
+
+ //use configured fields
+ fields = componentProperties.get(FIELD_VARIANT_FIELDS, new String[]{});
+ if (fields.length > 0) {
+ return fields;
+ }
+
+ return new String[]{};
+ }
+
/***
- * get and format badge config
+ * get and format badge config.
* @param page resource page
* @param componentProperties current componentProperties
* @return badge config map to be added to componentProperties
@@ -275,6 +583,14 @@ public static Map processBadgeConfig(Page page, ComponentPropert
}
+ /***
+ * process page metadata that has been configures in the page properties.
+ * @param page page to check
+ * @param resourceResolver resolver instance
+ * @param request request instance
+ * @param componentProperties components properties to use for content
+ * @return returns map with page metadata
+ */
public static Map processPageMetaProperties(Page page, ResourceResolver resourceResolver, SlingHttpServletRequest request, ComponentProperties componentProperties) {
Map newFields = new HashMap<>();
@@ -310,4 +626,36 @@ public static Map processPageMetaProperties(Page page, ResourceR
return newFields;
}
+
+
+ /***
+ * substitute formatted field template with fields from component.
+ * @param componentProperties source map with fields
+ * @param i18n i18n
+ * @param sling sling helper
+ * @return returns map with new values
+ */
+ @SuppressWarnings("Duplicates")
+ public Map processComponentFields(ComponentProperties componentProperties, com.day.cq.i18n.I18n i18n, SlingScriptHelper sling){
+ Map newFields = new HashMap<>();
+
+ try {
+
+ String formattedTitle = compileComponentMessage(FIELD_FORMAT_TITLE, DEFAULT_FORMAT_TITLE, componentProperties, sling);
+ Document fragment = Jsoup.parse(formattedTitle);
+ String formattedTitleText = fragment.text();
+
+ newFields.put(FIELD_FORMATTED_TITLE,
+ formattedTitle.trim()
+ );
+ newFields.put(FIELD_FORMATTED_TITLE_TEXT,
+ formattedTitleText.trim()
+ );
+
+ } catch (Exception ex) {
+ LOGGER.error("Could not process component fields in {}", COMPONENT_DETAILS_NAME);
+ }
+ return newFields;
+ }
+
}
diff --git a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/NewsDetails.java b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/NewsDetails.java
index c8a3e77fe..4f5b5e911 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/NewsDetails.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/NewsDetails.java
@@ -129,6 +129,7 @@ protected void ready() {
* @param sling sling helper
* @return returns map with new values
*/
+ @Override
@SuppressWarnings("Duplicates")
public Map processComponentFields(ComponentProperties componentProperties, I18n i18n, SlingScriptHelper sling){
Map newFields = new HashMap<>();
diff --git a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/PageDetails.java b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/PageDetails.java
index 534b46e9e..1772b3e23 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/PageDetails.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/models/v2/details/PageDetails.java
@@ -104,8 +104,9 @@ protected void ready() {
* @param sling sling helper
* @return returns map with new values
*/
+ @Override
@SuppressWarnings("Duplicates")
- public static Map processComponentFields(ComponentProperties componentProperties, com.day.cq.i18n.I18n i18n, SlingScriptHelper sling){
+ public Map processComponentFields(ComponentProperties componentProperties, com.day.cq.i18n.I18n i18n, SlingScriptHelper sling){
Map newFields = new HashMap<>();
try {
diff --git a/aemdesign-aem-services/src/main/java/design/aem/models/v2/lists/List.java b/aemdesign-aem-services/src/main/java/design/aem/models/v2/lists/List.java
index f8343140b..80a143225 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/models/v2/lists/List.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/models/v2/lists/List.java
@@ -283,6 +283,7 @@ protected void loadConfig() {
//prepare request parms to pass to badges
ComponentProperties badgeRequestAttributes = ComponentsUtil.getComponentProperties(
this,
+ false,
badgeComponentFields,
DEFAULT_FIELDS_DETAILS_OPTIONS_OVERRIDE);
@@ -556,9 +557,9 @@ private void populateStaticListItems() {
if (includePageInList(page,showInvalid,showHidden)) {
item.put("page", page);
item.putAll(getPageBadgeInfo(page));
+ listItems.add(item);
}
}
- listItems.add(item);
}
}
@@ -908,10 +909,10 @@ private void collectSearchResults(SearchResult result) throws RepositoryExceptio
if (includePageInList(containingPage,showInvalid,showHidden)) {
item.put("page", containingPage);
item.putAll(getPageBadgeInfo(containingPage));
+ listItems.add(item);
}
}
- listItems.add(item);
}
}
diff --git a/aemdesign-aem-services/src/main/java/design/aem/models/v2/lists/LocationList.java b/aemdesign-aem-services/src/main/java/design/aem/models/v2/lists/LocationList.java
index 8e1e2a583..22ad94fdf 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/models/v2/lists/LocationList.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/models/v2/lists/LocationList.java
@@ -8,6 +8,8 @@
import org.slf4j.LoggerFactory;
import static design.aem.utils.components.ComponentsUtil.*;
+import static design.aem.utils.components.ConstantsUtil.DEFAULT_CLOUDCONFIG_GOOGLEMAP;
+import static design.aem.utils.components.ConstantsUtil.DEFAULT_CLOUDCONFIG_GOOGLEMAP_API_KEY;
import static design.aem.utils.components.I18nUtil.*;
import static design.aem.utils.components.ImagesUtil.getMetadataStringForKey;
import static design.aem.utils.components.ImagesUtil.getResourceImagePath;
@@ -18,9 +20,6 @@ public class LocationList extends List {
private final String DEFAULT_I18N_CATEGORY = "newslist";
- final String DEFAULT_CLOUDCONFIG_GOOGLEMAP = "googlemap";
- final String DEFAULT_CLOUDCONFIG_GOOGLEMAP_API_KEY = "googleApiKey";
-
@Override
@SuppressWarnings("Duplicates")
protected void ready() {
diff --git a/aemdesign-aem-services/src/main/java/design/aem/models/v2/widgets/Vue.java b/aemdesign-aem-services/src/main/java/design/aem/models/v2/widgets/Vue.java
new file mode 100644
index 000000000..1d3fd0aef
--- /dev/null
+++ b/aemdesign-aem-services/src/main/java/design/aem/models/v2/widgets/Vue.java
@@ -0,0 +1,223 @@
+package design.aem.models.v2.widgets;
+
+import com.adobe.cq.sightly.SightlyWCMMode;
+import com.adobe.cq.sightly.WCMUsePojo;
+import com.adobe.granite.ui.components.AttrBuilder;
+import com.day.cq.commons.inherit.InheritanceValueMap;
+import com.day.cq.wcm.api.NameConstants;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import design.aem.components.ComponentProperties;
+import design.aem.utils.components.ComponentsUtil;
+import design.aem.utils.components.TagUtil;
+import design.aem.utils.components.TenantUtil;
+import org.apache.commons.lang.StringUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.*;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+import static design.aem.utils.components.ComponentsUtil.*;
+import static design.aem.utils.components.ConstantsUtil.DEFAULT_CLOUDCONFIG_GOOGLEMAP;
+import static design.aem.utils.components.ConstantsUtil.DEFAULT_CLOUDCONFIG_GOOGLEMAP_API_KEY;
+
+public class Vue extends WCMUsePojo {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Vue.class);
+
+ public ComponentProperties componentProperties = null;
+
+ private AttrBuilder attrs = null;
+ private StringBuilder componentHTML = new StringBuilder();
+ private Map configOutput = new HashMap<>();
+ private Map slots = new HashMap<>();
+
+ @Override
+ public void activate() {
+
+ Object[][] componentFields = {
+ {FIELD_VARIANT, DEFAULT_VARIANT},
+ {"vueComponentName", StringUtils.EMPTY},
+ {"analyticsName", StringUtils.EMPTY},
+ {"analyticsLocation", StringUtils.EMPTY},
+ };
+
+ attrs = new AttrBuilder(getRequest(), getXSSAPI());
+ componentProperties = ComponentsUtil.getComponentProperties(this, componentFields);
+
+ String componentName = componentProperties.get("vueComponentName", StringUtils.EMPTY);
+
+ // Retrieve the dynamic configuration for the component
+ retrieveComponentConfigurationAndSlots(componentName);
+
+ String googleMapApiKey = getCloudConfigProperty((InheritanceValueMap)getPageProperties(),DEFAULT_CLOUDCONFIG_GOOGLEMAP,DEFAULT_CLOUDCONFIG_GOOGLEMAP_API_KEY,getSlingScriptHelper());
+ attrs.add("google-maps-key", googleMapApiKey);
+
+ // Add any analytics attributes to the Vue component
+ setAnalyticsAttributes();
+
+ // Construct the component HTML
+ constructComponentHTML(componentName);
+
+ // Debugging output for authors & devs
+ componentProperties.put("configOutput", configOutput);
+ }
+
+ private void setAnalyticsAttributes() {
+ Map analyticsAttrs = new HashMap<>();
+ analyticsAttrs.put("analytics-name", "analyticsName");
+ analyticsAttrs.put("analytics-location", "analyticsLocation");
+
+ for (Map.Entry attr : analyticsAttrs.entrySet()) {
+ String value = componentProperties.get(attr.getValue(), StringUtils.EMPTY);
+
+ if (StringUtils.isNotEmpty(value)) {
+ attrs.add(attr.getKey(), value);
+ }
+ }
+ }
+
+ private void retrieveComponentConfigurationAndSlots(String componentName) {
+ Resource resource = getResource();
+
+ if (resource != null) {
+ Node resourceNode = resource.adaptTo(Node.class);
+
+ try {
+ if (resourceNode != null && resourceNode.hasNode("dynamic")) {
+ Node dynamicNode = resourceNode.getNode("dynamic");
+ Node componentNode = dynamicNode.getNode(componentName);
+
+ if (componentNode != null) {
+ PropertyIterator properties = componentNode.getProperties();
+ NodeIterator nodes = componentNode.getNodes();
+
+ while (nodes.hasNext()) {
+ Node node = (Node) nodes.next();
+
+ if (node == null || node.getName().startsWith("jcr:")) {
+ continue;
+ }
+
+ handleComponentValue(componentName, node.getName(), StringUtils.EMPTY, node.getProperties());
+ }
+
+ while (properties.hasNext()) {
+ Property property = properties.nextProperty();
+ String name = property.getName();
+
+ if (name.startsWith("jcr:")) {
+ continue;
+ }
+
+ handleComponentValue(componentName, name, property.getValue().getString(), null);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ LOGGER.error("[Vue Component] Unable to load all or part of the dynamic configuration for: {}", resource.getPath());
+ LOGGER.error(ex.getMessage());
+ }
+ }
+ }
+
+ private void handleComponentValue(String componentName, String name, String value, PropertyIterator properties) {
+ JsonObject fieldConfig = getFieldConfig(componentName, name);
+ SightlyWCMMode wcmMode = getWcmMode();
+
+ boolean isSlot = false;
+ String slotName = StringUtils.EMPTY;
+
+ if (fieldConfig != null && fieldConfig.has("field")) {
+ String fieldType = fieldConfig.get("field").getAsString();
+
+ // Autocompletion
+ if (fieldType.equals("autocomplete")) {
+ value = TagUtil.getTagValueAsAdmin(value, getSlingScriptHelper());
+ }
+
+ // Image/File upload
+ if (fieldType.equals("fileUpload") && properties != null) {
+ while (properties.hasNext()) {
+ Property property = properties.nextProperty();
+
+ try {
+ if (property.getName().equals("fileReference")) {
+ value = property.getString();
+ break;
+ }
+ } catch (RepositoryException ex) {
+ LOGGER.error("Unable to handle property iterator step!, {}", property);
+ LOGGER.error(ex.getLocalizedMessage());
+ }
+ }
+ }
+
+ // Is this field a slot?
+ isSlot = fieldConfig.has("slot");
+ slotName = isSlot ? fieldConfig.get("slot").getAsString() : slotName;
+ }
+
+ if (isSlot) {
+ slots.put(slotName, value);
+ } else {
+ attrs.add(name, value);
+ }
+
+ // Add the config to some additional output when in the correct WCM Mode
+ if (wcmMode.isEdit() || wcmMode.isPreview()) {
+ configOutput.put(StringUtils.capitalize(name), value);
+ }
+ }
+
+ private JsonObject getFieldConfig(String componentName, String fieldName) {
+ JsonParser parser = new JsonParser();
+ JsonObject jsonObject = null;
+
+ try {
+ String componentPath = "/content/%s/%s/component-dialog/vue-widgets/%s/%s";
+ String tenantName = TenantUtil.resolveTenantIdFromPath(getResource().getPath());
+ String resourcePath = String.format(componentPath, NameConstants.PN_TAGS, tenantName, componentName, fieldName);
+
+ Resource fieldResource = getResourceResolver().getResource(resourcePath);
+
+ if (fieldResource == null) {
+ throw new ResourceNotFoundException("Unable to get resource for: " + resourcePath);
+ }
+
+ String fieldValue = fieldResource.getValueMap().get("value", StringUtils.EMPTY);
+ String json = new String(Base64.getDecoder().decode(fieldValue));
+ JsonElement parsedJson = parser.parse(json);
+
+ if (parsedJson.isJsonObject()) {
+ jsonObject = parsedJson.getAsJsonObject();
+ }
+ } catch (Exception ex) {
+ LOGGER.error("[Vue Component] Unable to parse JSON value for '{}' on component: '{}'", fieldName, componentName);
+ LOGGER.error(ex.getMessage());
+ }
+
+ return jsonObject;
+ }
+
+ private void constructComponentHTML(String componentName) {
+ componentHTML.append(String.format("<%s %s>", componentName, attrs.build()));
+
+ if (slots.size() > 0) {
+ for (Map.Entry slot : slots.entrySet()) {
+ componentHTML.append(String.format("%s", slot.getKey(), slot.getValue()));
+ }
+ }
+
+ componentHTML.append(String.format("%s>", componentName));
+ }
+
+ public String getComponentHTML() {
+ return componentHTML.toString();
+ }
+}
diff --git a/aemdesign-aem-services/src/main/java/design/aem/utils/components/CommonUtil.java b/aemdesign-aem-services/src/main/java/design/aem/utils/components/CommonUtil.java
index 0144f0092..355b1518b 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/utils/components/CommonUtil.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/utils/components/CommonUtil.java
@@ -75,13 +75,12 @@ public class CommonUtil {
public static final String SLING_REDIRECT_TARGET = "sling:redirect";
/**
- * sling resource type property name
+ * sling resource type property name.
*/
public static final String RESOURCE_TYPE = "sling:resourceType";
/**
* This function html4-escapes the provided string/object.
- *
* @param body The string/object to encode.
* @return A properly encoded html4 string.
* @see StringEscapeUtils#escapeHtml4
@@ -93,6 +92,11 @@ public static String escapeBody(Object body) {
return StringEscapeUtils.escapeHtml4(body.toString());
}
+ /**
+ * ger redirect target for a page.
+ * @param page page to check
+ * @return string with redirect value
+ */
public static String getPageRedirect(Page page) {
if (page != null && page.getProperties() != null) {
return page.getProperties().get(PN_REDIRECT_TARGET, page.getProperties().get(SLING_REDIRECT_TARGET, ""));
@@ -102,8 +106,7 @@ public static String getPageRedirect(Page page) {
}
/**
- * Get a page's url
- *
+ * Get a page's url.
* @param page is the page to get the url for
* @return a string with the page url
*/
@@ -136,7 +139,6 @@ public static String getPageUrl(Page page) {
* @param resource resource to use
* @return resource last modified date
*/
-
public static Long getLastModified(Resource resource) {
long lastMod = 0L;
ValueMap values = resource.adaptTo(ValueMap.class);
@@ -158,7 +160,6 @@ public static Long getLastModified(Resource resource) {
* @param pageProperties page properties
* @return resource onTime or jcr:created value
*/
-
public static Long getPageCreated(ValueMap pageProperties) {
long longDate = 0L;
if (pageProperties != null) {
@@ -180,7 +181,6 @@ public static Long getPageCreated(ValueMap pageProperties) {
* @param pageProperties page properties
* @return resource ReplicationStatus.NODE_PROPERTY_LAST_REPLICATED value
*/
-
public static Long getPageLastReplicated(ValueMap pageProperties) {
long longDate = 0L;
if (pageProperties != null) {
@@ -268,8 +268,7 @@ public static String getPageTitle(Page page) {
/**
- * Get a page's navigation title, or normal title
- *
+ * Get a page's navigation title, or normal title.
* @param page is the page to get the title for
* @return a string with the page title
*/
@@ -287,8 +286,7 @@ public static String getPageNavTitle(Page page) {
}
/**
- * get tags for a page
- *
+ * get tags for a page.
* @param page is the page to look for the image
* @return is the relative path to the image
*/
@@ -307,8 +305,7 @@ public static String[] getPageContentTypeTag(Page page) {
}
/**
- * Get a JCR value or, if it's not available, return null
- *
+ * Get a JCR value or, if it's not available, return null.
* @param node is the jcr node to find
* @param property is the property on the node to query
* @return the value in the property, or null if nothing was found
@@ -319,8 +316,7 @@ public static String getProperty(Node node, String property) throws RepositoryEx
}
/**
- * Get a JCR value or, if it's not available, return the defaultValue
- *
+ * Get a JCR value or, if it's not available, return the defaultValue.
* @param node is the jcr node to find
* @param property is the property on the node to query
* @param defaultValue is the default value to return
@@ -338,8 +334,7 @@ public static boolean validDetailComponent(String resourceType) {
}
/**
- * Determine whether named script exists
- *
+ * Determine whether named script exists.
* @param page is the current page (for a reference to the root node)
* @param nodeName is the node name to check for
* @return true if the script exists
@@ -386,8 +381,7 @@ public static boolean nodeExists(Page page, String nodeName) {
/**
- * Determine whether the page is visible
- *
+ * Determine whether the page is visible.
* @param page is the page to determine this for
* @return true if the page is on, otherwise false is returned.
*/
@@ -401,7 +395,6 @@ public static boolean pageIsOn(Page page) {
/**
* Utility function for hashing a string via MD5.
- *
* @param content The string to perform the hash on.
* @return The hash if successful, or the original string if not.
*/
@@ -419,9 +412,8 @@ public static String hashMd5(String content) {
}
/**
- * Protects against the stupid multi-single property bug AEM seems to have. Will get the value off a node property
- * if it exists, or return null if anything goes wrong.
- *
+ * Protects against the stupid multi-single property bug AEM seems to have.
+ * Will get the value off a node property if it exists, or return null if anything goes wrong.
* @param node The node to get the property value from.
* @param key The property key to get the value for.
* @return The value of the property, or null.
@@ -451,7 +443,6 @@ public static Value getSingularProperty(Node node, String key) {
/**
* Convenience method for safely retrieving a String value from a node.
- *
* @param node The node to get the property string from.
* @param key The property key to get the string for.
* @return The string value of the property, or null.
@@ -474,8 +465,7 @@ public static String findComponentInPage(Page inputPage, String[] resourceTypeTa
}
/**
- * find a component in a page root that matches required suffix
- *
+ * find a component in a page root that matches required suffix.
* @param inputPage is the page to look through for component
* @param resourceTypeTail array for suffixes to check as endsWith with sling:resourceType or node name (as failover)
* @param pageRoots use matching page root as a staring point for search
@@ -579,8 +569,7 @@ public static long tryParseLong(String value, long defaultValue) {
/**
- * Return a JCR node for a first found matching path
- *
+ * Return a JCR node for a first found matching path.
* @param thisPage is the page to inspect for newsdetails
* @param nodePaths paths to look for
* @return a JCR node or null when not found
@@ -602,8 +591,7 @@ public static String getComponentNodePath(Page thisPage, String[] nodePaths) {
}
/**
- * Return a JCR node for a first found matching path
- *
+ * Return a JCR node for a first found matching path.
* @param thisPage is the page to inspect for newsdetails
* @param nodePaths paths to look for
* @return a JCR node or null when not found
@@ -626,8 +614,7 @@ public static Node getComponentNode(Page thisPage, String[] nodePaths) {
}
/**
- * Return a JCR node for the component in thisPage
- *
+ * Return a JCR node for the component in thisPage
.
* @param thisPage is the page to inspect for component
* @param componentPath is the path of the component eg par/venuedetails
* @return a JCR node or null when not found
@@ -644,8 +631,7 @@ public static Node getComponentNode(Page thisPage, String componentPath) {
}
/**
- * Return first mediagallery or video node on thisPage
- *
+ * Return first mediagallery or video node on thisPage
.
* @param thisPage is the page to inspect for component
* @return a JCR node or null when not found
*/
@@ -680,7 +666,6 @@ public static Node getFirstMediaNode(Page thisPage) {
* @param map map of attributes to use
* @return formatted string
*/
-
public static String compileMapMessage(String template, Map map) {
//quick fail
if (isEmpty(template) || map == null) {
@@ -693,7 +678,7 @@ public static String compileMapMessage(String template, Map map)
/***
- * render a resource path as HTML to include in components that reuse content in other resources
+ * render a resource path as HTML to include in components that reuse content in other resources.
* @param path path to resources
* @param resourceResolver resource resolver for request
* @param sling sling helper
@@ -756,10 +741,12 @@ public static String resourceRenderAsHtml(String path, ResourceResolver resource
/***
* return badge name from selector string.
+ * @deprecated use generic-details template and field pattern
* @param selectorString _slingRequest.getRequestPathInfo().getSelectorString()
* @return badge name
*/
@SuppressWarnings({"squid:S4784"})
+ @Deprecated
public static String getBadgeFromSelectors(String selectorString) {
String badge = "";
@@ -783,7 +770,7 @@ public static String getBadgeFromSelectors(String selectorString) {
/***
- * disable decoration of component
+ * disable decoration of component.
* @param componentContext current component context
* @param includeOptions include options
*/
@@ -797,7 +784,7 @@ public static void forceNoDecoration(ComponentContext componentContext, IncludeO
}
/***
- * set component decoration
+ * set component decoration.
* @param componentContext current component context
* @param includeOptions include option
* @param defDecoration defaut decoration
diff --git a/aemdesign-aem-services/src/main/java/design/aem/utils/components/ComponentsUtil.java b/aemdesign-aem-services/src/main/java/design/aem/utils/components/ComponentsUtil.java
index adae0499e..8ba69724b 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/utils/components/ComponentsUtil.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/utils/components/ComponentsUtil.java
@@ -57,6 +57,7 @@
import static design.aem.components.ComponentField.FIELD_VALUES_ARE_ATTRIBUTES;
import static design.aem.utils.components.CommonUtil.*;
import static design.aem.utils.components.ConstantsUtil.*;
+import static design.aem.utils.components.TagUtil.getTag;
import static java.text.MessageFormat.format;
import static org.apache.commons.lang3.StringUtils.*;
@@ -67,6 +68,7 @@ public class ComponentsUtil {
public static final String DEFAULT_PATH_TAGS = "/content/cq:tags";
public static final String FIELD_VARIANT = "variant";
+ public static final String FIELD_VARIANT_LEGACY = "legacyVariant"; // specify that variant field is derived from config / tag
public static final String DEFAULT_VARIANT = "default";
public static final String DEFAULT_VARIANT_TEMPLATE = "variant.default.html";
public static final String DEFAULT_BADGE = "default";
@@ -121,6 +123,22 @@ public class ComponentsUtil {
public static final String DETAILS_BADGE_IMAGE_ATTR = "badgeImageAttr";
public static final String DETAILS_BADGE_LINK_ATTR = "badgeLinkAttr";
+ //badge custom badge
+ public static final String DETAILS_BADGE_FIELDS_TEMPLATE = "badgeFieldsTemplate";
+ public static final String DETAILS_BADGE_FIELDS = "badgeFields";
+ public static final String DETAILS_BADGE_TEMPLATE = "badgeTemplate";
+ public static final String DETAILS_BADGE_CUSTOM = "badgeCustom";
+
+ //variant templates
+ public static final String FIELD_VARIANT_FIELDS = "variantFields";
+ public static final String FIELD_VARIANT_FIELDS_TEMPLATE = "variantFieldsTemplate";
+
+ //config attributes for templates used for both custom badges and variants
+ public static final String FIELD_TAG_TEMPLATE_CONFIG_TEMPLATES = "templates";
+ public static final String FIELD_TAG_TEMPLATE_CONFIG_FIELDS = "fields";
+ public static final String FIELD_TAG_TEMPLATE_CONFIG_VALUE = "value";
+ public static final String FIELD_TAG_TEMPLATE_CONFIG_VALUEALT = "valuealt"; //used in dropdowns to show same options in dialogs
+
//badge analytics
public static final String DETAILS_BADGE_ANALYTICS_EVENT_TYPE = "badgeAnalyticsEventType"; //NOSONAR
public static final String DETAILS_BADGE_ANALYTICS_TRACK = "badgeAnalyticsTrack";
@@ -301,19 +319,19 @@ public class ComponentsUtil {
* 4 optional - canonical name of class for handling multivalues, String or Tag
*/
public static final Object[][] DEFAULT_FIELDS_STYLE = { //NOSONAR used by classes
- {FIELD_STYLE_COMPONENT_ID, "", "id"},
+ {FIELD_STYLE_COMPONENT_ID, StringUtils.EMPTY, "id"},
{FIELD_STYLE_COMPONENT_THEME, new String[]{}, "class", Tag.class.getCanonicalName()},
{FIELD_STYLE_COMPONENT_MODIFIERS, new String[]{}, "class", Tag.class.getCanonicalName()},
{FIELD_STYLE_COMPONENT_MODULES, new String[]{}, "data-modules", Tag.class.getCanonicalName()},
{FIELD_STYLE_COMPONENT_CHEVRON, new String[]{}, "class", Tag.class.getCanonicalName()},
{FIELD_STYLE_COMPONENT_ICON, new String[]{}, "class", Tag.class.getCanonicalName()},
- {FIELD_STYLE_COMPONENT_POSITIONX, "", "x"},
- {FIELD_STYLE_COMPONENT_POSITIONY, "", "y"},
+ {FIELD_STYLE_COMPONENT_POSITIONX, StringUtils.EMPTY, "x"},
+ {FIELD_STYLE_COMPONENT_POSITIONY, StringUtils.EMPTY, "y"},
{FIELD_STYLE_COMPONENT_WIDTH, "${value ? 'width:' + value + 'px;' : ''}", "style"},
{FIELD_STYLE_COMPONENT_HEIGHT, "${value ? 'height:' + value + 'px;' : ''}", "style"},
- {FIELD_STYLE_COMPONENT_SITETHEMECATEGORY, ""},
- {FIELD_STYLE_COMPONENT_SITETHEMECOLOR, ""},
- {FIELD_STYLE_COMPONENT_SITETITLECOLOR, ""},
+ {FIELD_STYLE_COMPONENT_SITETHEMECATEGORY, StringUtils.EMPTY},
+ {FIELD_STYLE_COMPONENT_SITETHEMECOLOR, StringUtils.EMPTY},
+ {FIELD_STYLE_COMPONENT_SITETITLECOLOR, StringUtils.EMPTY},
{FIELD_STYLE_COMPONENT_BOOLEANATTR, new String[]{}, FIELD_VALUES_ARE_ATTRIBUTES, Tag.class.getCanonicalName()},
};
@@ -327,15 +345,15 @@ public class ComponentsUtil {
* 4 optional - canonical name of class for handling multivalues, String or Tag
*/
public static final Object[][] DEFAULT_FIELDS_ACCESSIBILITY = { //NOSONAR used by classes
- {FIELD_ARIA_ROLE, "", DEFAULT_ARIA_ROLE_ATTRIBUTE},
- {FIELD_ARIA_LABEL, "", "aria-label"},
- {FIELD_ARIA_DESCRIBEDBY, "", "aria-describedby"},
- {FIELD_ARIA_LABELLEDBY, "", "aria-labelledby"},
- {FIELD_ARIA_CONTROLS, "", "aria-controls"},
- {FIELD_ARIA_LIVE, "", "aria-live"},
- {FIELD_ARIA_HIDDEN, "", "aria-hidden"},
- {FIELD_ARIA_HASPOPUP, "", "aria-haspopup"},
- {FIELD_ARIA_ACCESSKEY, "", "accesskey"},
+ {FIELD_ARIA_ROLE, StringUtils.EMPTY, DEFAULT_ARIA_ROLE_ATTRIBUTE},
+ {FIELD_ARIA_LABEL, StringUtils.EMPTY, "aria-label"},
+ {FIELD_ARIA_DESCRIBEDBY, StringUtils.EMPTY, "aria-describedby"},
+ {FIELD_ARIA_LABELLEDBY, StringUtils.EMPTY, "aria-labelledby"},
+ {FIELD_ARIA_CONTROLS, StringUtils.EMPTY, "aria-controls"},
+ {FIELD_ARIA_LIVE, StringUtils.EMPTY, "aria-live"},
+ {FIELD_ARIA_HIDDEN, StringUtils.EMPTY, "aria-hidden"},
+ {FIELD_ARIA_HASPOPUP, StringUtils.EMPTY, "aria-haspopup"},
+ {FIELD_ARIA_ACCESSKEY, StringUtils.EMPTY, "accesskey"},
};
/**
@@ -348,11 +366,11 @@ public class ComponentsUtil {
* 4 optional - canonical name of class for handling multivalues, String or Tag
*/
public static final Object[][] DEFAULT_FIELDS_METADATA = { //NOSONAR used by classes
- {"metadataContentType", ""},
- {NameConstants.PN_PAGE_LAST_MOD, ""},
- {JcrConstants.JCR_LASTMODIFIED, ""},
- {JcrConstants.JCR_CREATED, ""},
- {NameConstants.PN_PAGE_LAST_REPLICATED, ""},
+ {"metadataContentType", StringUtils.EMPTY},
+ {NameConstants.PN_PAGE_LAST_MOD, StringUtils.EMPTY},
+ {JcrConstants.JCR_LASTMODIFIED, StringUtils.EMPTY},
+ {JcrConstants.JCR_CREATED, StringUtils.EMPTY},
+ {NameConstants.PN_PAGE_LAST_REPLICATED, StringUtils.EMPTY},
};
/**
@@ -365,18 +383,18 @@ public class ComponentsUtil {
* 4 optional - canonical name of class for handling multivalues, String or Tag
*/
public static final Object[][] DEFAULT_FIELDS_DETAILS_OPTIONS = { //NOSONAR used by classes
- {DETAILS_MENU_COLOR, ""},
+ {DETAILS_MENU_COLOR, StringUtils.EMPTY},
{DETAILS_MENU_ICONSHOW, false},
- {DETAILS_MENU_ICON, new String[]{}, "", Tag.class.getCanonicalName()},
- {DETAILS_MENU_ACCESS_KEY, ""},
- {DETAILS_CARD_STYLE, new String[]{}, "", Tag.class.getCanonicalName()},
+ {DETAILS_MENU_ICON, new String[]{}, StringUtils.EMPTY, Tag.class.getCanonicalName()},
+ {DETAILS_MENU_ACCESS_KEY, StringUtils.EMPTY},
+ {DETAILS_CARD_STYLE, new String[]{}, StringUtils.EMPTY, Tag.class.getCanonicalName()},
{DETAILS_CARD_ICONSHOW, false},
- {DETAILS_CARD_ICON, new String[]{}, "", Tag.class.getCanonicalName()},
+ {DETAILS_CARD_ICON, new String[]{}, StringUtils.EMPTY, Tag.class.getCanonicalName()},
{DETAILS_LINK_TARGET, "_blank"},
{DETAILS_LINK_TEXT, "${value ? value : (" + FIELD_PAGE_TITLE_NAV + " ? " + FIELD_PAGE_TITLE_NAV + " : '')}"},
{DETAILS_LINK_TITLE, "${value ? value : (" + FIELD_PAGE_TITLE + " ? " + FIELD_PAGE_TITLE + " : '')}"},
- {DETAILS_LINK_STYLE, new String[]{}, "", Tag.class.getCanonicalName()},
- {DETAILS_LINK_FORMATTED, "${value ? value : pageUrl}", "", Tag.class.getCanonicalName()},
+ {DETAILS_LINK_STYLE, new String[]{}, StringUtils.EMPTY, Tag.class.getCanonicalName()},
+ {DETAILS_LINK_FORMATTED, "${value ? value : pageUrl}", StringUtils.EMPTY, Tag.class.getCanonicalName()},
{DETAILS_TITLE_TRIM, false},
{DETAILS_TITLE_TRIM_LENGTH_MAX, ConstantsUtil.DEFAULT_SUMMARY_TRIM_LENGTH},
{DETAILS_TITLE_TRIM_LENGTH_MAX_SUFFIX, ConstantsUtil.DEFAULT_SUMMARY_TRIM_SUFFIX},
@@ -384,24 +402,27 @@ public class ComponentsUtil {
{DETAILS_SUMMARY_TRIM_LENGTH_MAX, ConstantsUtil.DEFAULT_SUMMARY_TRIM_LENGTH},
{DETAILS_SUMMARY_TRIM_LENGTH_MAX_SUFFIX, ConstantsUtil.DEFAULT_SUMMARY_TRIM_SUFFIX},
{DETAILS_TAB_ICONSHOW, false},
- {DETAILS_TAB_ICON, new String[]{}, "", Tag.class.getCanonicalName()},
+ {DETAILS_TAB_ICON, new String[]{}, StringUtils.EMPTY, Tag.class.getCanonicalName()},
{DETAILS_TITLE_ICONSHOW, false},
- {DETAILS_TITLE_ICON, new String[]{}, "", Tag.class.getCanonicalName()},
+ {DETAILS_TITLE_ICON, new String[]{}, StringUtils.EMPTY, Tag.class.getCanonicalName()},
{DETAILS_OVERLAY_ICONSHOW, false},
- {DETAILS_OVERLAY_ICON, new String[]{}, "", Tag.class.getCanonicalName()},
+ {DETAILS_OVERLAY_ICON, new String[]{}, StringUtils.EMPTY, Tag.class.getCanonicalName()},
{DETAILS_THUMBNAIL_WIDTH, ConstantsUtil.DEFAULT_THUMB_WIDTH_SM},
- {DETAILS_THUMBNAIL_HEIGHT, ""},
+ {DETAILS_THUMBNAIL_HEIGHT, StringUtils.EMPTY},
{DETAILS_THUMBNAIL_TYPE, ConstantsUtil.IMAGE_OPTION_RENDITION},
{DETAILS_TITLE_TAG_TYPE, ConstantsUtil.DEFAULT_TITLE_TAG_TYPE_BADGE},
- {DETAILS_THUMBNAIL_ID, ""},
- {DETAILS_THUMBNAIL_LICENSE_INFO, ""},
- {DETAILS_THUMBNAIL, ""},
+ {DETAILS_THUMBNAIL_ID, StringUtils.EMPTY},
+ {DETAILS_THUMBNAIL_LICENSE_INFO, StringUtils.EMPTY},
+ {DETAILS_THUMBNAIL, StringUtils.EMPTY},
{DETAILS_BADGE_ANALYTICS_TRACK, StringUtils.EMPTY,DETAILS_DATA_ANALYTICS_TRACK},
{DETAILS_BADGE_ANALYTICS_LOCATION, StringUtils.EMPTY,DETAILS_DATA_ANALYTICS_LOCATION},
{DETAILS_BADGE_ANALYTICS_LABEL, "${value ? value : " + DETAILS_LINK_TEXT + "}",DETAILS_DATA_ANALYTICS_LABEL},
{DETAILS_PAGE_METADATA_PROPERTY, new String[]{}},
{DETAILS_PAGE_METADATA_PROPERTY_CONTENT, new String[]{}},
-
+ {DETAILS_BADGE_CUSTOM, false},
+ {DETAILS_BADGE_FIELDS_TEMPLATE, new String[]{}},
+ {DETAILS_BADGE_FIELDS, new String[]{}},
+ {DETAILS_BADGE_TEMPLATE, StringUtils.EMPTY}, //after DETAILS_BADGE_FIELDS_TEMPLATE and DETAILS_BADGE_FIELDS as it will override them
};
/**
@@ -448,6 +469,10 @@ public class ComponentsUtil {
{DETAILS_BADGE_ANALYTICS_TRACK, StringUtils.EMPTY,DETAILS_DATA_ANALYTICS_TRACK}, //basic
{DETAILS_BADGE_ANALYTICS_LOCATION, StringUtils.EMPTY,DETAILS_DATA_ANALYTICS_LOCATION}, //basic
{DETAILS_BADGE_ANALYTICS_LABEL, StringUtils.EMPTY,DETAILS_DATA_ANALYTICS_LABEL}, //basic
+ {DETAILS_BADGE_CUSTOM, false},
+ {DETAILS_BADGE_FIELDS_TEMPLATE, new String[]{}},
+ {DETAILS_BADGE_FIELDS, new String[]{}},
+ {DETAILS_BADGE_TEMPLATE, StringUtils.EMPTY}, //after DETAILS_BADGE_FIELDS_TEMPLATE and DETAILS_BADGE_FIELDS as it will override them
};
@@ -483,9 +508,9 @@ public class ComponentsUtil {
* 4 optional - canonical name of class for handling multivalues, String or Tag
*/
public static final Object[][] DEFAULT_FIELDS_ATTRIBUTES = { //NOSONAR used by classes
- {"dataType", "", "type"},
- {"dataTarget", "", "data-target"},
- {"dataToggle", "", "data-toggle"},
+ {"dataType", StringUtils.EMPTY, "type"},
+ {"dataTarget", StringUtils.EMPTY, "data-target"},
+ {"dataToggle", StringUtils.EMPTY, "data-toggle"},
};
/**
@@ -561,11 +586,11 @@ public class ComponentsUtil {
* 4 optional - canonical name of class for handling multivalues, String or Tag
*/
public static final Object[][] DEFAULT_FIELDS_PAGE_THEME = { //NOSONAR used by classes
- {"themeStyle", ""},
- {"faviconsPath", ""},
- {"favicon", ""},
- {"siteThemeColor", ""},
- {"siteTileColor", ""},
+ {"themeStyle", StringUtils.EMPTY},
+ {"faviconsPath", StringUtils.EMPTY},
+ {"favicon", StringUtils.EMPTY},
+ {"siteThemeColor", StringUtils.EMPTY},
+ {"siteTileColor", StringUtils.EMPTY},
};
/**
@@ -579,7 +604,7 @@ public class ComponentsUtil {
*/
public static final Object[][] DEFAULT_COMMON_COMPONENT_LAYOUT_FIELDS = { //NOSONAR used by classes
{FIELD_VARIANT, DEFAULT_VARIANT},
- {FIELD_TITLE_TAG_TYPE, ""},
+ {FIELD_TITLE_TAG_TYPE, StringUtils.EMPTY},
{FIELD_HIDE_TITLE, false},
{FIELD_HIDE_DESCRIPTION, false},
{FIELD_SHOW_BREADCRUMB, true},
@@ -597,7 +622,7 @@ public class ComponentsUtil {
* @return a string with the file contents
*/
public static String getResourceContent(ResourceResolver resourceResolver, String[] paths, String separator) {
- String returnValue = "";
+ String returnValue = StringUtils.EMPTY;
for (String path : paths) {
Resource resource = resourceResolver.getResource(path);
@@ -619,7 +644,7 @@ public static String getResourceContent(ResourceResolver resourceResolver, Strin
* @return a string with the file contents
*/
public static String getResourceContent(Resource resource) {
- String returnValue = "";
+ String returnValue = StringUtils.EMPTY;
if (resource != null) {
@@ -677,7 +702,7 @@ public static Object getComponentProperty(ValueMap componentProperties, ValueMap
//quick fail
if (componentProperties == null) {
LOGGER.warn("getComponentProperty, componentProperties is ({0})", componentProperties);
- return "";
+ return StringUtils.EMPTY;
}
if (useStyle && (contentPolicy == null || contentPolicy.isEmpty())) {
@@ -705,11 +730,11 @@ public static Object getComponentProperty(ValueMap componentProperties, Style pa
//quick fail
if (componentProperties == null) {
LOGGER.warn("getComponentProperty, componentProperties is ({0})", componentProperties);
- return "";
+ return StringUtils.EMPTY;
}
if (useStyle && pageStyle == null) {
LOGGER.warn("getComponentProperty, useStyle is ({0}) but pageStyle is {1}", useStyle, pageStyle);
- return "";
+ return StringUtils.EMPTY;
}
if (useStyle) {
@@ -794,6 +819,17 @@ public static ComponentProperties getNewComponentProperties(Map
}
+ /**
+ * returns component values with defaults from pageContent Properties.
+ * @param wcmUsePojoModel component model pojo
+ * @param includeComponentAttributes include attributes specific to this component instance
+ * @param fieldLists list of fields definition Object{{name, defaultValue, attributeName, valueTypeClass},...}
+ * @return map of attributes
+ */
+ public static ComponentProperties getComponentProperties(WCMUsePojo wcmUsePojoModel, Boolean includeComponentAttributes, Object[][]... fieldLists) {
+ return getComponentProperties(wcmUsePojoModel, null, includeComponentAttributes, fieldLists);
+ }
+
/**
* returns component values with defaults from pageContent Properties.
* @param wcmUsePojoModel component model pojo
@@ -1025,7 +1061,7 @@ public static ComponentProperties getComponentProperties(Map pag
boolean addMoreAttributes = includeComponentAttributes;
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) pageContext.get("slingRequest");
- ResourceResolver resourceResolver = (ResourceResolver) pageContext.get("resourceResolver");
+ //ResourceResolver resourceResolver = (ResourceResolver) pageContext.get("resourceResolver");
SlingScriptHelper sling = (SlingScriptHelper) pageContext.get("sling");
@@ -1058,7 +1094,7 @@ public static ComponentProperties getComponentProperties(Map pag
// if targetResource == null get defaults
ValueMap properties = (ValueMap) pageContext.get("properties"); //NOSONAR getting properties from pagecontext
- ValueMap currentPolicy = getContentPolicyProperties(componentContext.getResource(), resourceResolver);
+ ValueMap currentPolicy = getContentPolicyProperties(componentContext.getResource(), adminResourceResolver);
//if targetResource != null get the appropriate objects
if (targetResource != null && targetResource.getClass().getCanonicalName().equals(CLASS_TYPE_ASSET)) {
@@ -1088,7 +1124,7 @@ public static ComponentProperties getComponentProperties(Map pag
properties = contentResource.adaptTo(ValueMap.class);
- currentPolicy = getContentPolicyProperties(contentResource, resourceResolver);
+ currentPolicy = getContentPolicyProperties(contentResource, adminResourceResolver);
ComponentManager componentManager = contentResource.getResourceResolver().adaptTo(ComponentManager.class);
Component resourceComponent = componentManager.getComponentOfResource(contentResource);
@@ -1145,11 +1181,11 @@ public static ComponentProperties getComponentProperties(Map pag
Object fieldDefaultValue = field[1];
//set default value to empty string if default value is null
if (isNull(fieldDefaultValue)) {
- fieldDefaultValue = "";
+ fieldDefaultValue = StringUtils.EMPTY;
}
//read third field - get data attribute name
- String fieldDataName= "";
+ String fieldDataName= StringUtils.EMPTY;
if (field.length > 2) {
fieldDataName = field[2].toString();
}
@@ -1216,7 +1252,7 @@ public static ComponentProperties getComponentProperties(Map pag
//Empty array with empty string will set the default value
if (fieldValue instanceof String && StringUtils.isEmpty(fieldValue.toString())) {
fieldValue = fieldDefaultValue;
- } else if (fieldValue instanceof String[] && fieldValue != null && (StringUtils.isEmpty(StringUtils.join((String[]) fieldValue, "")))) {
+ } else if (fieldValue instanceof String[] && fieldValue != null && (StringUtils.isEmpty(StringUtils.join((String[]) fieldValue, StringUtils.EMPTY)))) {
fieldValue = fieldDefaultValue;
}
@@ -1231,7 +1267,7 @@ public static ComponentProperties getComponentProperties(Map pag
}
if (field.length > 2) {
- String fieldValueString = "";
+ String fieldValueString = StringUtils.EMPTY;
if (fieldValue.getClass().isArray()) {
if (ArrayUtils.isNotEmpty((String[]) fieldValue)) {
@@ -1260,7 +1296,7 @@ public static ComponentProperties getComponentProperties(Map pag
} else {
//if data-attribute not specified return empty if values array is empty
if (isEmpty(fieldDataName)) {
- fieldValue = "";
+ fieldValue = StringUtils.EMPTY;
}
}
} else {
@@ -1310,7 +1346,34 @@ public static ComponentProperties getComponentProperties(Map pag
}
//get current variant value
- String variant = componentProperties.get(FIELD_VARIANT, "");
+ String variant = componentProperties.get(FIELD_VARIANT, StringUtils.EMPTY);
+ //get current badge template value
+ String badge = componentProperties.get(DETAILS_BADGE_TEMPLATE, StringUtils.EMPTY);
+
+ if (addMoreAttributes) {
+
+ //use default variant if variant value not set
+ if (isEmpty(variant)) {
+ variant = DEFAULT_VARIANT;
+ //mark current variant selection as legacy
+ componentProperties.put(FIELD_VARIANT_LEGACY, true);
+ } else {
+ //get variant config
+ ComponentProperties variantConfig = getTemplateConfig(pageContext, variant, adminResourceResolver, tagManager, FIELD_VARIANT_FIELDS_TEMPLATE, FIELD_VARIANT_FIELDS, FIELD_VARIANT);
+ componentProperties.putAll(variantConfig);
+ //get updated version of variant
+ variant = componentProperties.get(FIELD_VARIANT, StringUtils.EMPTY);
+ }
+ //get badge config
+ if (isNotEmpty(badge)) {
+ ComponentProperties badgeConfig = getTemplateConfig(pageContext, badge, adminResourceResolver, tagManager, DETAILS_BADGE_FIELDS_TEMPLATE, DETAILS_BADGE_FIELDS, "detailsBadge");
+ componentProperties.putAll(badgeConfig);
+ }
+
+ //compile variantTemplate param
+ String variantTemplate = getComponentVariantTemplate(component, format(COMPONENT_VARIANT_TEMPLATE_FORMAT, variant), sling);
+ componentProperties.put(COMPONENT_VARIANT_TEMPLATE, variantTemplate);
+ }
//add variant to the end of class string
if (!componentProperties.attr.isEmpty() && addMoreAttributes) {
@@ -1321,17 +1384,6 @@ public static ComponentProperties getComponentProperties(Map pag
componentProperties.put(COMPONENT_ATTRIBUTES, buildAttributesString(componentProperties.attr.getData(), oldXssAPI));
}
- //use default variant if variant value not set
- if (isEmpty(variant)) {
- variant = DEFAULT_VARIANT;
- }
-
- String variantTemplate = getComponentVariantTemplate(component, format(COMPONENT_VARIANT_TEMPLATE_FORMAT, variant), sling);
-
- if (addMoreAttributes) {
- //compile variantTemplate param
- componentProperties.put(COMPONENT_VARIANT_TEMPLATE, variantTemplate);
- }
}
} catch (Exception ex) {
@@ -1344,6 +1396,56 @@ public static ComponentProperties getComponentProperties(Map pag
return componentProperties;
}
+ /**
+ * get template structure config from tags for badge or variant
+ * @param pageContext current page context
+ * @param configTag tag to use for lookup
+ * @param resourceResolver instance of resource resolver
+ * @param tagManager instance of tag manager
+ * @param fieldNameTemplates return field name for templates
+ * @param fieldNameFields return field name for fields
+ * @param fieldNameFirstTemplateName return field name for template name
+ * @return return map of fields with values
+ */
+ public static ComponentProperties getTemplateConfig(Map pageContext, String configTag, ResourceResolver resourceResolver, TagManager tagManager, String fieldNameTemplates, String fieldNameFields, String fieldNameFirstTemplateName) {
+ ComponentProperties componentProperties = getNewComponentProperties(pageContext);
+ if (isNotEmpty(configTag)) {
+ Tag tagConfig = getTag(configTag, resourceResolver, tagManager);
+ if (tagConfig != null) {
+ //mark current variant selection as not legacy
+ componentProperties.put(FIELD_VARIANT_LEGACY, false);
+
+ //get value map of tag
+ Resource tagConfigRS = resourceResolver.getResource(tagConfig.getPath());
+ ValueMap tagConfigVM = tagConfigRS.adaptTo(ValueMap.class);
+ //see if it has templates set and get it
+ if (tagConfigVM.containsKey(FIELD_TAG_TEMPLATE_CONFIG_TEMPLATES)) {
+ String[] template = tagConfigVM.get(FIELD_TAG_TEMPLATE_CONFIG_TEMPLATES, new String[]{});
+ componentProperties.put(fieldNameTemplates, template);
+ if (template.length > 0) {
+ //update the return template name to first entry
+ componentProperties.put(fieldNameFirstTemplateName, template[0]);
+ }
+ } else {
+ //get tag value as variant name
+ if (tagConfigVM.containsKey(FIELD_TAG_TEMPLATE_CONFIG_VALUE)) {
+ String value = tagConfigVM.get(FIELD_TAG_TEMPLATE_CONFIG_VALUE, DEFAULT_VARIANT);
+ componentProperties.put(fieldNameFirstTemplateName, value);
+ }
+
+ }
+ //get fields list
+ if (tagConfigVM.containsKey(FIELD_TAG_TEMPLATE_CONFIG_FIELDS)) {
+ String[] fields = tagConfigVM.get(FIELD_TAG_TEMPLATE_CONFIG_FIELDS, new String[]{});
+ componentProperties.put(fieldNameFields, fields);
+ }
+ } else {
+ //mark current variant selection as legacy
+ componentProperties.put(FIELD_VARIANT_LEGACY, true);
+ }
+ }
+ return componentProperties;
+ }
/**
* return variant template name from component or return default
* @param component component to check for variant template
@@ -1431,7 +1533,7 @@ public static String buildAttributesString(Map data, com.adobe.g
//return string without invalid characters
return out.toString().replaceAll(" ", " ");
} catch (Exception ex) {
- return "";
+ return StringUtils.EMPTY;
}
}
@@ -1447,12 +1549,12 @@ public static String buildAttributesString(Map data, com.adobe.g
*/
@Deprecated
public static String addComponentBackgroundToAttributes(ComponentProperties componentProperties, Resource resource, String imageResourceName) {
- String componentAttributes = componentProperties.get(COMPONENT_ATTRIBUTES, "");
+ String componentAttributes = componentProperties.get(COMPONENT_ATTRIBUTES, StringUtils.EMPTY);
Resource imageResource = resource.getChild(imageResourceName);
if (imageResource != null) {
Resource fileReference = imageResource.getChild(ConstantsUtil.IMAGE_FILEREFERENCE);
if (fileReference != null) {
- String imageSrc = "";
+ String imageSrc = StringUtils.EMPTY;
if (imageResource.getResourceType().equals(DEFAULT_IMAGE_RESOURCETYPE) || imageResource.getResourceType().endsWith(DEFAULT_IMAGE_RESOURCETYPE_SUFFIX)) {
Long lastModified = CommonUtil.getLastModified(imageResource);
imageSrc = format(DEFAULT_IMAGE_GENERATED_FORMAT, imageResource.getPath(), lastModified.toString());
@@ -1475,7 +1577,7 @@ public static String addComponentBackgroundToAttributes(ComponentProperties comp
@Deprecated
public static String addComponentAttributes(ComponentProperties componentProperties, Object[][] keyValue) {
- String componentAttributes = componentProperties.get(COMPONENT_ATTRIBUTES, "");
+ String componentAttributes = componentProperties.get(COMPONENT_ATTRIBUTES, StringUtils.EMPTY);
for (Object[] item : keyValue) {
if (item.length >= 1) {
@@ -1579,7 +1681,7 @@ public static String getComponentId(Node componentNode) {
if (componentNode == null) {
return componentId;
}
- String path = "";
+ String path = StringUtils.EMPTY;
try {
path = componentNode.getPath();
@@ -1610,7 +1712,7 @@ public static String getComponentId(Node componentNode) {
public static String getCloudConfigProperty(InheritanceValueMap pageProperties, String configurationName, String propertyName, SlingScriptHelper sling) {
- String returnValue = "";
+ String returnValue = StringUtils.EMPTY;
ContentAccess contentAccess = sling.getService(ContentAccess.class);
if (contentAccess != null) {
@@ -1623,7 +1725,7 @@ public static String getCloudConfigProperty(InheritanceValueMap pageProperties,
if (cfgMgr != null) {
addthisConfiguration = cfgMgr.getConfiguration(configurationName, services);
if (addthisConfiguration != null) {
- returnValue = addthisConfiguration.get(propertyName, "");
+ returnValue = addthisConfiguration.get(propertyName, StringUtils.EMPTY);
}
}
@@ -1650,7 +1752,7 @@ public static Resource findInheritedResource(Page page, ComponentContext compone
final String pageResourcePath = page.getContentResource().getPath(); // assume that page have resource
final Resource thisResource = componentContext.getResource();
final String nodeResourceType = thisResource.getResourceType();
- final String relativePath = thisResource.getPath().replaceFirst(pageResourcePath.concat(FileSystem.SEPARATOR), "");
+ final String relativePath = thisResource.getPath().replaceFirst(pageResourcePath.concat(FileSystem.SEPARATOR), StringUtils.EMPTY);
// defn of a parent node
// 1. is from parent page
@@ -1684,7 +1786,7 @@ public static Resource findInheritedResource(Page page, ComponentContext compone
curProperties = curResource.adaptTo(ValueMap.class);
if (curProperties != null) {
curResourceTypeMatch = curResource.isResourceType(nodeResourceType);
- curCancelInheritParent = curProperties.get(COMPONENT_CANCEL_INHERIT_PARENT, "").contentEquals("true");
+ curCancelInheritParent = curProperties.get(COMPONENT_CANCEL_INHERIT_PARENT, StringUtils.EMPTY).contentEquals("true");
if (curResourceTypeMatch && curCancelInheritParent) {
String found = format("findInheritedResource: FOUND looking for inherited resource for path=\"{0}\" by relative path=\"{1}\" in parent=\"{2}\"", pageResourcePath, relativePath, curPage.getPath());
@@ -1725,7 +1827,7 @@ public static String getFirstAttributeFromList(LinkedHashMap source
}
}
}
- return "";
+ return StringUtils.EMPTY;
}
/***
@@ -1734,9 +1836,9 @@ public static String getFirstAttributeFromList(LinkedHashMap source
* @return component path relative to {@link JcrConstants#JCR_CONTENT}
*/
public static String getComponentInPagePath(Node componentNode) {
- String componentInPagePath = "";
+ String componentInPagePath = StringUtils.EMPTY;
if (componentNode == null) {
- return "";
+ return StringUtils.EMPTY;
}
try {
@@ -1746,7 +1848,7 @@ public static String getComponentInPagePath(Node componentNode) {
if (parts.length > 0) {
componentInPagePath = parts[1];
if (isNotEmpty(componentInPagePath) && componentInPagePath.startsWith(FileSystem.SEPARATOR)) {
- componentInPagePath = componentInPagePath.replaceFirst(FileSystem.SEPARATOR, "");
+ componentInPagePath = componentInPagePath.replaceFirst(FileSystem.SEPARATOR, StringUtils.EMPTY);
}
}
}
@@ -1870,7 +1972,7 @@ public static String findLocalResourceInSuperComponent(Component component, Stri
superComponent = superComponent.getSuperComponent();
if (superComponent == null) {
- return "";
+ return StringUtils.EMPTY;
}
localresource = superComponent.getLocalResource(resourceName);
@@ -1898,7 +2000,7 @@ public static String findLocalResourceInSuperComponent(Component component, Stri
}
- return "";
+ return StringUtils.EMPTY;
}
@@ -1930,7 +2032,7 @@ public static Map getComponentFieldsAndDialogMap(Resource compon
//walk up the tree of resourceSuperType and get base component
String componentDialogPath = findLocalResourceInSuperComponent(componentOfResource,"cq:dialog", slingScriptHelper);
- String dialogPath = "";
+ String dialogPath = StringUtils.EMPTY;
Document dialogContent = null;
if (isNotEmpty(componentDialogPath)) {
@@ -1957,9 +2059,9 @@ public static Map getComponentFieldsAndDialogMap(Resource compon
Map row = new HashMap<>();
row.put("value", value);
- row.put("fieldDescription", "");
- row.put("fieldLabel", "");
- row.put("type", "");
+ row.put("fieldDescription", StringUtils.EMPTY);
+ row.put("fieldLabel", StringUtils.EMPTY);
+ row.put("type", StringUtils.EMPTY);
if (isNotEmpty(dialogPath) && dialogContent != null) {
String fieldSelection = "[name='./" + name + "']";
@@ -1989,7 +2091,7 @@ public static Map getComponentFieldsAndDialogMap(Resource compon
row.put("fieldLabel", fieldLabelText);
}
- String fieldDescriptionString = "";
+ String fieldDescriptionString = StringUtils.EMPTY;
if (fieldDescription != null) {
fieldDescriptionString = fieldDescription.attr("data-quicktip-content");
@@ -2098,7 +2200,7 @@ public static Object evaluateExpressionWithValue(JxltEngine jxlt, JexlContext jc
public static String removeRegexFromString(String value) {
try {
Pattern valueIsRegexPattern = Pattern.compile("(\\$\\{.*?\\})");
- return value.replaceAll(valueIsRegexPattern.pattern(), "");
+ return value.replaceAll(valueIsRegexPattern.pattern(), StringUtils.EMPTY);
} catch (PatternSyntaxException ex) {
LOGGER.error("removeRegexFromString: could not remove patterns from string, ex={}", ex);
}
@@ -2151,6 +2253,6 @@ public static String getUniquePageIdentifier(Page listPage) {
return hashMd5(uniqueBase);
}
- return "";
+ return StringUtils.EMPTY;
}
}
diff --git a/aemdesign-aem-services/src/main/java/design/aem/utils/components/ConstantsUtil.java b/aemdesign-aem-services/src/main/java/design/aem/utils/components/ConstantsUtil.java
index 740f54946..26c7172f0 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/utils/components/ConstantsUtil.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/utils/components/ConstantsUtil.java
@@ -124,4 +124,8 @@ public class ConstantsUtil {
public static final String DEFAULT_ICS_TIMESTAMP_FORMAT = "yyyyMMdd'T'HHmmssZ";
public static final String DATA_ATTRIBUTE_PREFIX = "data-";
+
+ public static final String DEFAULT_CLOUDCONFIG_GOOGLEMAP = "googlemap";
+ public static final String DEFAULT_CLOUDCONFIG_GOOGLEMAP_API_KEY = "googleApiKey";
+
}
diff --git a/aemdesign-aem-services/src/main/java/design/aem/utils/components/ContentFragmentUtil.java b/aemdesign-aem-services/src/main/java/design/aem/utils/components/ContentFragmentUtil.java
new file mode 100644
index 000000000..7b54e1427
--- /dev/null
+++ b/aemdesign-aem-services/src/main/java/design/aem/utils/components/ContentFragmentUtil.java
@@ -0,0 +1,75 @@
+package design.aem.utils.components;
+
+import com.adobe.cq.dam.cfm.ContentElement;
+import com.adobe.cq.dam.cfm.ContentFragment;
+import com.adobe.cq.dam.cfm.ContentVariation;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+import static org.apache.commons.lang3.StringUtils.isNotEmpty;
+
+public class ContentFragmentUtil {
+ protected static final Logger LOGGER = LoggerFactory.getLogger(ContentFragmentUtil.class);
+ public static final String DEFAULT_CONTENTFRAGMENT_VARIATION = "master";
+
+ /**
+ * get content fragment content in an ordered map
+ * @param contentFragmentPath path to content fragment
+ * @param variationName variation of content fragment
+ * @return ordered map of key value fields
+ */
+ public static Map getComponentFragmentMap(String contentFragmentPath, String variationName, ResourceResolver resourceResolver){
+ LinkedHashMap newFields = new LinkedHashMap<>();
+
+ try {
+ if (isNotEmpty(contentFragmentPath)) {
+ Resource fragmentResource = resourceResolver.getResource(contentFragmentPath);
+ if (!ResourceUtil.isNonExistingResource(fragmentResource) ) {
+
+ ContentFragment contentFragment = fragmentResource.adaptTo(ContentFragment.class);
+ if (contentFragment == null) {
+ LOGGER.error("Content Fragment can not be initialized because '{}' is not a content fragment.", fragmentResource.getPath());
+ } else {
+ //ensure that variation name is set
+ if (isEmpty(variationName)) {
+ variationName = DEFAULT_CONTENTFRAGMENT_VARIATION;
+ }
+ //load all available attributes and values into a map
+ for (Iterator contentElementIterator = contentFragment.getElements(); contentElementIterator.hasNext(); ) {
+ ContentElement contentElement = (ContentElement)contentElementIterator.next();
+ String name = contentElement.getName();
+ Object value = null;
+ //if variant name is specified get that value
+ if (isNotEmpty(variationName) && !DEFAULT_CONTENTFRAGMENT_VARIATION.equals(variationName)) {
+ ContentVariation variation = contentElement.getVariation(variationName);
+ if (variation == null) {
+ LOGGER.warn("Non-existing variation '{}' of element '{}'", variationName, contentElement.getName());
+ } else {
+ value = variation.getContent();
+ }
+ } else {
+ value = contentElement.getContent();
+ }
+ newFields.put(name, value);
+ }
+
+ }
+ }
+ } else {
+ LOGGER.error("Could not process content fragment as with empty path");
+ }
+
+ } catch (Exception ex) {
+ LOGGER.error("Could not process content fragment: {} with variant {}", contentFragmentPath, variationName);
+ }
+ return newFields;
+ }
+
+}
diff --git a/aemdesign-aem-services/src/main/java/design/aem/utils/components/TagUtil.java b/aemdesign-aem-services/src/main/java/design/aem/utils/components/TagUtil.java
index 87aa9a6e7..7b9152697 100644
--- a/aemdesign-aem-services/src/main/java/design/aem/utils/components/TagUtil.java
+++ b/aemdesign-aem-services/src/main/java/design/aem/utils/components/TagUtil.java
@@ -80,7 +80,6 @@ public static String getTagValueAsAdmin(String tagPath, SlingScriptHelper sling)
return tagValue;
}
-
/**
* Get list of Tags from a list of tag paths.
* @param sling sling helper
@@ -89,6 +88,19 @@ public static String getTagValueAsAdmin(String tagPath, SlingScriptHelper sling)
* @return map of tag values
*/
public static LinkedHashMap getTagsAsAdmin(SlingScriptHelper sling, String[] tagPaths, Locale locale) {
+ return getTagsAsAdmin(sling, tagPaths, locale, new String[0], false);
+ }
+
+ /**
+ * Get list of Tags from a list of tag paths.
+ * @param sling sling helper
+ * @param tagPaths list of tags
+ * @param locale locale to yse
+ * @param attributesToRead list of attributes to gather from tag
+ * @param getTagChildren for given paths get children
+ * @return map of tag values
+ */
+ public static LinkedHashMap getTagsAsAdmin(SlingScriptHelper sling, String[] tagPaths, Locale locale, String[] attributesToRead, boolean getTagChildren) {
LinkedHashMap tags = new LinkedHashMap<>();
if (sling == null || tagPaths == null || tagPaths.length == 0) {
@@ -102,7 +114,24 @@ public static LinkedHashMap getTagsAsAdmin(SlingScriptHelper sling,
TagManager tagManager = adminResourceResolver.adaptTo(TagManager.class);
- for (String path : tagPaths) {
+ String[] tagPathsToLoad = tagPaths;
+
+ if (getTagChildren) {
+ ArrayList childList = new ArrayList<>();
+ for (String path : tagPathsToLoad) {
+ Tag tag = getTag(path, adminResourceResolver, tagManager);
+ Resource tagRs = tag.adaptTo(Resource.class);
+ if (tagRs.hasChildren()) {
+ for (Resource child : tagRs.getChildren()) {
+ childList.add(child.getPath());
+ }
+ }
+
+ }
+ tagPathsToLoad = childList.toArray(new String[0]);
+ }
+
+ for (String path : tagPathsToLoad) {
Map tagValues = new HashMap<>();
Tag tag = getTag(path, adminResourceResolver, tagManager);
@@ -139,6 +168,16 @@ public static LinkedHashMap getTagsAsAdmin(SlingScriptHelper sling,
}
tagValues.put(TAG_VALUE, tagValue);
+
+ if (attributesToRead != null) {
+ for (String attribute : attributesToRead) {
+ if (tagVM.containsKey(attribute)) {
+ tagValues.put(attribute, tagVM.get(attribute, null));
+ }
+
+ }
+ }
+
} else {
LOGGER.error("getTagsAsAdmin: could not get convert tag to Resource, tag={}", tag);
}
diff --git a/aemdesign-aem-services/src/test/java/design/aem/utils/components/ResolverUtilTest.java b/aemdesign-aem-services/src/test/java/design/aem/utils/components/ResolverUtilTest.java
index 1aa586f55..1249fd0f0 100644
--- a/aemdesign-aem-services/src/test/java/design/aem/utils/components/ResolverUtilTest.java
+++ b/aemdesign-aem-services/src/test/java/design/aem/utils/components/ResolverUtilTest.java
@@ -54,9 +54,9 @@ public void setUp() throws Exception {
CONTEXT.registerService(Externalizer.class, externalizer,
JcrConstants.JCR_PRIMARYTYPE, "sling:OsgiConfig",
- "externalizer.domains", "[local http://192.168.27.2:4502,author http://192.168.27.2:4502,publish http://192.168.27.2:4503]",
+ "externalizer.domains", "[local http://localhost:4502,author http://localhost:4502,publish http://localhost:4503]",
"externalizer.contextpath", "",
- "externalizer.host", "192.168.27.2",
+ "externalizer.host", "localhost",
"externalizer.encodedpath", false
);
@@ -110,7 +110,7 @@ public void testMappedUrlExternalizerHTTP() {
// Setup
final String path = "/content/externalize-me.html";
final String domain = "local";
- final String expectedResult = "http://192.168.27.2:4502/content/externalize-me.html";
+ final String expectedResult = "http://localhost:4502/content/externalize-me.html";
request.setResource(testResource);
@@ -136,7 +136,7 @@ public void testMappedUrlExternalizerNotSecure() {
// Setup
final String path = "/content/externalize-me.html";
final String domain = "local";
- final String expectedResult = "http://192.168.27.2:4502/content/externalize-me.html";
+ final String expectedResult = "http://localhost:4502/content/externalize-me.html";
request.setResource(testResource);
@@ -162,7 +162,7 @@ public void testMappedUrlExternalizerSecure() {
// Setup
final String path = "/content/externalize-me.html";
final String domain = "local";
- final String expectedResult = "https://192.168.27.2:4502/content/externalize-me.html";
+ final String expectedResult = "https://localhost:4502/content/externalize-me.html";
request.setResource(testResource);
@@ -188,7 +188,7 @@ public void testMappedUrlExternalizerHTTPS() {
// Setup
final String path = "/content/externalize-me.html";
final String domain = "local";
- final String expectedResult = "https://192.168.27.2:4502/content/externalize-me.html";
+ final String expectedResult = "https://localhost:4502/content/externalize-me.html";
request.setResource(testResource);
diff --git a/deploy b/deploy
index b7faca4dd..991f9f8e2 100755
--- a/deploy
+++ b/deploy
@@ -14,6 +14,9 @@ echo " - Deploying Monolith Package: mvn -Dvault.useProxy=false -DskipTests -e -
mvn -Dvault.useProxy=false -DskipTests -e -U -P installdeploymentpackage clean install "$@"
echo " - Deployed"
+echo "- Restarting Docker Container in 5 sec"
+sleep 5
+
#restart aem container
restart_aem_docker
diff --git a/pom.xml b/pom.xml
index 9f751017f..0cd47c209 100755
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
design.aem
aemdesign-aem-core
- 2.0.420
+ 2.0.508
pom
AEM Design - Core Project
@@ -25,14 +25,14 @@
- 192.168.27.2
+ localhost
4502
admin
admin
/etc/packages
- 192.168.27.2
+ localhost
8081
- 192.168.27.2
+ localhost
4503
admin
admin
@@ -63,7 +63,8 @@
6.4.0
${git.closest.tag.name}
${git.closest.tag.commit.count}
- aemdesign-aem-services
+ aemdesign-aem-services
+ design.aem.aemdesign-aem-services
diff --git a/privateregistry.xml b/privateregistry.xml
index 6593faddf..f71be1018 100755
--- a/privateregistry.xml
+++ b/privateregistry.xml
@@ -80,7 +80,7 @@
privateregistry
- http://192.168.27.2:8081/repository/maven-snapshots
+ http://localhost:8081/repository/maven-snapshots
true
@@ -92,7 +92,7 @@
privateregistry
- http://192.168.27.2:8081/repository/maven-snapshots
+ http://localhost:8081/repository/maven-snapshots
true
@@ -108,7 +108,7 @@
aemdesign-mirror
*
- http://192.168.27.2:8081/repository/maven-releases/
+ http://localhost:8081/repository/maven-releases/
@@ -116,9 +116,9 @@
aemdesign-proxy
true
http
- 192.168.27.2:8081
+ localhost:8081
8081
- 192.168.27.2,localhost,127.0.0.1
+ localhost,127.0.0.1
\ No newline at end of file
diff --git a/scripts/functions-aem.sh b/scripts/functions-aem.sh
index 461b99227..969f0de2a 100644
--- a/scripts/functions-aem.sh
+++ b/scripts/functions-aem.sh
@@ -150,6 +150,7 @@ function delete_current_jar() {
PROJECT_VERSION=$(getParamOrDefault "" "version")
BUNDLE_NAME=$(getParamOrDefault "" "bundleName")
+ BUNDLE_FILENAME=$(getParamOrDefault "" "bundleFileName")
PROJECT_ARTIFACTID=$($CAT "$POM_FILE" | $GREP artifactId -A1 | $HEAD -n 2 | $TAIL -n 1 | $SED -e 's/.*>\(.*\)<.*/\1/')
GIT_VERSION=$(getCurrentProjectVersion)
@@ -157,9 +158,13 @@ function delete_current_jar() {
echo "Current Git Version: $GIT_VERSION"
echo "Project Artifact Id Version: $PROJECT_ARTIFACTID"
- PROJECT_JAR="/apps/aemdesign/install/${BUNDLE_NAME}-${PROJECT_VERSION}.jar"
+ PROJECT_JAR="/apps/aemdesign/install/${BUNDLE_FILENAME}-${PROJECT_VERSION}.jar"
echo "Project Jar: $PROJECT_JAR"
+ echo "Uninstall Bundle: ${BUNDLE_NAME}"
+
+ doPostFields "/system/console/bundles/${BUNDLE_NAME}" "-daction=uninstall"
+
JAR_EXIST=$(doCheckPathExist "$PROJECT_JAR")
echo "Check if Jar exists: $JAR_EXIST"