diff --git a/backend/Makefile b/backend/Makefile
index 67d33c7..82ff654 100644
--- a/backend/Makefile
+++ b/backend/Makefile
@@ -157,7 +157,7 @@ create-site: instance/etc/zope.ini ## Create a new site from scratch
.PHONY: start
start: ## Start a Plone instance on localhost:8080
- PYTHONWARNINGS=ignore ./bin/runwsgi instance/etc/zope.ini
+ ENABLE_PRINTING_MAILHOST=True PYTHONWARNINGS=ignore ./bin/runwsgi instance/etc/zope.ini
.PHONY: debug
debug: instance/etc/zope.ini ## Run debug console
@@ -178,4 +178,4 @@ create-tag: # Create a new tag using git
commit-and-release: # Commit new version change and create tag
@echo "Commiting changes"
@git commit -am "Tag release as $(PROJECT_VERSION) to deploy"
- make create-tag
\ No newline at end of file
+ make create-tag
diff --git a/backend/src/ploneorg/setup.py b/backend/src/ploneorg/setup.py
index 8598990..4d38977 100644
--- a/backend/src/ploneorg/setup.py
+++ b/backend/src/ploneorg/setup.py
@@ -66,6 +66,7 @@
"plone.app.testing[robot]>=7.0.0a3",
"plone.restapi[test]",
"collective.MockMailHost",
+ "Products.PrintingMailHost",
"pytest",
],
},
diff --git a/backend/src/ploneorg/src/ploneorg/configure.zcml b/backend/src/ploneorg/src/ploneorg/configure.zcml
index ee223aa..e78f4c2 100644
--- a/backend/src/ploneorg/src/ploneorg/configure.zcml
+++ b/backend/src/ploneorg/src/ploneorg/configure.zcml
@@ -27,5 +27,6 @@
+
diff --git a/backend/src/ploneorg/src/ploneorg/interpolators/__init__.py b/backend/src/ploneorg/src/ploneorg/interpolators/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/src/ploneorg/src/ploneorg/interpolators/configure.zcml b/backend/src/ploneorg/src/ploneorg/interpolators/configure.zcml
new file mode 100644
index 0000000..a3494f6
--- /dev/null
+++ b/backend/src/ploneorg/src/ploneorg/interpolators/configure.zcml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/backend/src/ploneorg/src/ploneorg/interpolators/member.py b/backend/src/ploneorg/src/ploneorg/interpolators/member.py
new file mode 100644
index 0000000..47f3071
--- /dev/null
+++ b/backend/src/ploneorg/src/ploneorg/interpolators/member.py
@@ -0,0 +1,26 @@
+from plone.stringinterp.adapters import BaseSubstitution
+from ploneorg import _
+from ploneorg.content.member import IFoundationMember
+from zope.component import adapter
+
+
+@adapter(IFoundationMember)
+class EmailSubstitution(BaseSubstitution):
+ category = _("Foundation Member")
+ description = _("Member E-mail")
+
+ def safe_call(self):
+ name = self.context.title
+ email = self.context.email
+ if name and email:
+ return f"{name}<{email}>"
+
+
+@adapter(IFoundationMember)
+class RenewURLSubstitution(BaseSubstitution):
+ category = _("Foundation Member")
+ description = _("Renew URL")
+
+ def safe_call(self):
+ url = self.context.absolute_url()
+ return f"{url}?mtm_campaign=PFM&mtm_kwd=Renew"
diff --git a/backend/src/ploneorg/src/ploneorg/profiles/default/contentrules.xml b/backend/src/ploneorg/src/ploneorg/profiles/default/contentrules.xml
new file mode 100644
index 0000000..1370412
--- /dev/null
+++ b/backend/src/ploneorg/src/ploneorg/profiles/default/contentrules.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+ FoundationMember
+
+
+
+
+ suspend
+
+
+
+
+
+ Reminder: Time to Renew Your Plone Foundation Membership
+ Plone Foundation<ploneorg@mg.plone.org>
+ ${pf_member_email}
+ True
+ Dear ${title},
+
+As we approach another exciting year for the Plone Foundation, it's time to renew your membership to maintain your active status and continue enjoying the benefits that come with it. As an active member, you have the privilege to:
+
+ 1. Vote for the Plone Foundation Board of Directors
+ 2. Participate in selecting the location for the next Plone Conference
+ 3. Approve the minutes of the annual meeting
+ 4. Exercise all other rights and privileges granted to Plone Foundation members
+
+How to Renew Your Membership
+
+ 1. Log in to your account at https://plone.org/login using your GitHub credentials.
+ 2. Navigate to ${pf_renew_url} and click on the Renew Membership button.
+
+If you no longer wish to maintain an active membership, you may choose to retire it by clicking on the Retire Membership button.
+
+Need Assistance?
+
+Should you encounter any issues or have questions regarding the renewal process, please don't hesitate to reach out to us at board@plone.org. We are here to assist you.
+
+We look forward to another year of collaboration and growth with you as part of the Plone Foundation.
+
+Best regards,
+Plone Foundation Board
+board@plone.org
+
+
+
+
+
diff --git a/backend/src/ploneorg/src/ploneorg/profiles/default/metadata.xml b/backend/src/ploneorg/src/ploneorg/profiles/default/metadata.xml
index fc7455b..8ce443b 100644
--- a/backend/src/ploneorg/src/ploneorg/profiles/default/metadata.xml
+++ b/backend/src/ploneorg/src/ploneorg/profiles/default/metadata.xml
@@ -1,6 +1,6 @@
- 20230904001
+ 20230907001profile-plone.volto:defaultprofile-plone.app.vulnerabilities:default
diff --git a/backend/src/ploneorg/src/ploneorg/upgrades/configure.zcml b/backend/src/ploneorg/src/ploneorg/upgrades/configure.zcml
index 5ab33ae..783381d 100644
--- a/backend/src/ploneorg/src/ploneorg/upgrades/configure.zcml
+++ b/backend/src/ploneorg/src/ploneorg/upgrades/configure.zcml
@@ -153,4 +153,14 @@
/>
+
+
+
diff --git a/backend/src/ploneorg/tests/test_setup.py b/backend/src/ploneorg/tests/test_setup.py
index a35c942..e11952e 100644
--- a/backend/src/ploneorg/tests/test_setup.py
+++ b/backend/src/ploneorg/tests/test_setup.py
@@ -34,7 +34,7 @@ def test_latest_version(self):
"""Test latest version of default profile."""
self.assertEqual(
self.setup.getLastVersionForProfile("ploneorg:default")[0],
- "20230904001",
+ "20230907001",
)
diff --git a/backend/src/ploneorg/tests/test_upgrades.py b/backend/src/ploneorg/tests/test_upgrades.py
index b321a39..e862197 100644
--- a/backend/src/ploneorg/tests/test_upgrades.py
+++ b/backend/src/ploneorg/tests/test_upgrades.py
@@ -40,6 +40,7 @@ def available_steps(self, src, dst) -> list:
("20230412001", "20230528001", 1),
("20230528001", "20230530001", 1),
("20230530001", "20230904001", 1),
+ ("20230904001", "20230907001", 1),
]
)
diff --git a/frontend/src/components/Views/FoundationMember.jsx b/frontend/src/components/Views/FoundationMember.jsx
index 79ee62a..ca8613e 100644
--- a/frontend/src/components/Views/FoundationMember.jsx
+++ b/frontend/src/components/Views/FoundationMember.jsx
@@ -3,10 +3,14 @@
* @module components/View/FoundationMemberView
*/
-import React from 'react';
+import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
-import { Container, Table } from 'semantic-ui-react';
-import { flattenHTMLToAppURL } from '@plone/volto/helpers';
+import { Container, Table, Button } from 'semantic-ui-react';
+import { flattenHTMLToAppURL, flattenToAppURL } from '@plone/volto/helpers';
+import { useSelector, useDispatch } from 'react-redux';
+import { getWorkflow, transitionWorkflow } from '@plone/volto/actions';
+
+import './member.less';
/**
* FoundationMemberView view component class.
@@ -14,85 +18,142 @@ import { flattenHTMLToAppURL } from '@plone/volto/helpers';
* @params {object} content Content object.
* @returns {string} Markup of the component.
*/
-const FoundationMemberView = ({ content }) => (
-
- {content.title &&