From 328505ee396319b01306b93fed2f4195adc91931 Mon Sep 17 00:00:00 2001
From: Daniele Andreotti
Date: Tue, 21 Nov 2023 17:09:59 +0100
Subject: [PATCH 1/4] Added utility views for Event
---
CHANGES.rst | 3 +-
.../browser/utils/check_eventi.py | 190 ++++++++++++++++++
.../contenttypes/browser/utils/configure.zcml | 14 +-
.../browser/utils/templates/check_eventi.pt | 173 ++++++++++++++++
.../browser/utils/templates/utils.pt | 6 +
5 files changed, 384 insertions(+), 2 deletions(-)
create mode 100644 src/design/plone/contenttypes/browser/utils/check_eventi.py
create mode 100644 src/design/plone/contenttypes/browser/utils/templates/check_eventi.pt
diff --git a/CHANGES.rst b/CHANGES.rst
index ded58c60..0d91a842 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,8 @@ Changelog
6.1.2 (unreleased)
------------------
-- Nothing changed yet.
+- Added utility views: @@check-eventi and @@download-check-eventi.
+ [daniele]
6.1.1 (2023-11-21)
diff --git a/src/design/plone/contenttypes/browser/utils/check_eventi.py b/src/design/plone/contenttypes/browser/utils/check_eventi.py
new file mode 100644
index 00000000..190c42a6
--- /dev/null
+++ b/src/design/plone/contenttypes/browser/utils/check_eventi.py
@@ -0,0 +1,190 @@
+from openpyxl import Workbook
+from openpyxl.styles import Alignment
+from openpyxl.styles import Font
+from openpyxl.styles import PatternFill
+from openpyxl.utils import get_column_letter
+from plone import api
+from Products.Five import BrowserView
+
+import io
+
+
+FLAG = ' '
+
+
+class CheckEventi(BrowserView):
+ cds = None
+
+ def is_anonymous(self):
+ return api.user.is_anonymous()
+
+ def information_dict(self, evento):
+ prezzo = getattr(evento, "prezzo", "")
+ res = [x.get("text", "") for x in prezzo["blocks"].values()]
+ if not [x for x in res if x]:
+ prezzo = ""
+
+ return {
+ "description": getattr(evento, "description", "").strip(),
+ "effective_date": getattr(evento, "effective_date", None),
+ "luoghi_correlati": getattr(evento, "luoghi_correlati", None),
+ "prezzo": prezzo,
+ "contact_info": getattr(evento, "contact_info", None),
+ }
+
+ def plone2volto(self, url):
+ portal_url = api.portal.get().absolute_url()
+ frontend_domain = api.portal.get_registry_record(
+ "volto.frontend_domain", default=""
+ )
+ if frontend_domain and url.startswith(portal_url):
+ return url.replace(portal_url, frontend_domain, 1)
+ return url
+
+ def get_eventi(self):
+ if self.is_anonymous():
+ return []
+ pc = api.portal.get_tool("portal_catalog")
+
+ query = {
+ "portal_type": "Event",
+ "review_state": "published",
+ }
+ brains = pc(query)
+ results = {}
+ for brain in brains:
+ evento = brain.getObject()
+
+ information_dict = self.information_dict(evento)
+ if all(information_dict.values()):
+ continue
+
+ parent = evento.aq_inner.aq_parent
+ if parent.title not in results:
+ results[parent.title] = {
+ "url": self.plone2volto(parent.absolute_url()),
+ "children": [],
+ }
+ results[parent.title]["children"].append(
+ {
+ "title": evento.title,
+ "description": information_dict.get("description") and FLAG or "",
+ "url": self.plone2volto(evento.absolute_url()),
+ "data": {
+ "effective_date": information_dict.get("effective_date")
+ and FLAG
+ or "",
+ "luoghi_correlati": information_dict.get("luoghi_correlati")
+ and FLAG
+ or "",
+ "prezzo": information_dict.get("prezzo") and FLAG or "",
+ "contact_info": information_dict.get("contact_info")
+ and FLAG
+ or "",
+ },
+ }
+ )
+
+ results = dict(sorted(results.items()))
+ for key in results:
+ results[key]["children"].sort(key=lambda x: x["title"])
+
+ return results
+
+
+class DownloadCheckEventi(CheckEventi):
+ CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+
+ def __call__(self):
+ HEADER = [
+ "Titolo",
+ "Descrizione",
+ "Data",
+ "Luogo",
+ "Costo",
+ "Contatti",
+ ]
+
+ EMPTY_ROW = [""] * 3
+
+ eventi = self.get_eventi()
+
+ workbook = Workbook()
+ sheet = workbook.active
+ sheet.title = "Check Persone"
+ header_font = Font(bold=True)
+ section_link_font = Font(underline="single", color="0563C1", size=14)
+ link_fill = PatternFill(fill_type="solid", fgColor="DDDDDD")
+ link_font = Font(underline="single", color="0563C1")
+ section_fill = PatternFill(fill_type="solid", fgColor="E9E9E9")
+ alignment = Alignment(horizontal="center", vertical="top", wrapText=True)
+
+ section_row_height = int(14 * 1.5)
+
+ for category, category_data in eventi.items():
+ section_url = category_data["url"]
+ section_title = category
+ section_row = [section_title, "", ""]
+ sheet.append(section_row)
+ section_cell = sheet.cell(row=sheet.max_row, column=1)
+
+ section_cell.alignment = alignment
+ section_cell.hyperlink = section_url
+ sheet.merge_cells(
+ start_row=sheet.max_row,
+ start_column=1,
+ end_row=sheet.max_row,
+ end_column=3,
+ ) # noqa
+ for row in sheet.iter_rows(
+ min_row=sheet.max_row, max_row=sheet.max_row, min_col=1, max_col=3
+ ): # noqa
+ sheet.row_dimensions[row[0].row].height = section_row_height
+ for cell in row:
+ cell.fill = section_fill
+ cell.font = section_link_font
+
+ sheet.append(HEADER)
+ for col in range(1, len(HEADER) + 1):
+ header_cell = sheet.cell(row=sheet.max_row, column=col)
+ header_cell.fill = link_fill
+ header_cell.font = header_font
+
+ for col in sheet.columns:
+ column_letter = get_column_letter(col[0].column)
+ sheet.column_dimensions[column_letter].width = 35
+
+ for evento in category_data["children"]:
+ title_url = evento["url"]
+ dati_evento = [
+ evento["title"],
+ "X" if evento["description"] else "",
+ "X" if evento["data"]["effective_date"] else "",
+ "X" if evento["data"]["luoghi_correlati"] else "",
+ "X" if evento["data"]["prezzo"] else "",
+ "X" if evento["data"]["contact_info"] else "",
+ ]
+ row = dati_evento
+ sheet.append(row)
+
+ title_cell = sheet.cell(row=sheet.max_row, column=1)
+ check_cell = sheet.cell(row=sheet.max_row, column=2)
+ check_cell.alignment = check_cell.alignment.copy(horizontal="center")
+ title_cell.hyperlink = title_url
+ title_cell.font = link_font
+ column_letter_unit = get_column_letter(title_cell.column)
+ sheet.column_dimensions[column_letter_unit].width = 60
+
+ sheet.append(EMPTY_ROW)
+ sheet.append(EMPTY_ROW)
+
+ bytes_io = io.BytesIO()
+ workbook.save(bytes_io)
+ data = bytes_io.getvalue()
+ self.request.response.setHeader("Content-Length", len(data))
+ self.request.RESPONSE.setHeader("Content-Type", self.CT)
+ self.request.response.setHeader(
+ "Content-Disposition",
+ "attachment; filename=check_eventi.xlsx",
+ )
+ return data
diff --git a/src/design/plone/contenttypes/browser/utils/configure.zcml b/src/design/plone/contenttypes/browser/utils/configure.zcml
index 1421659b..f1c6fa85 100644
--- a/src/design/plone/contenttypes/browser/utils/configure.zcml
+++ b/src/design/plone/contenttypes/browser/utils/configure.zcml
@@ -41,7 +41,6 @@
template="templates/check_servizi.pt"
permission="zope2.Public"
/>
-
+
+
diff --git a/src/design/plone/contenttypes/browser/utils/templates/check_eventi.pt b/src/design/plone/contenttypes/browser/utils/templates/check_eventi.pt
new file mode 100644
index 00000000..0f01a710
--- /dev/null
+++ b/src/design/plone/contenttypes/browser/utils/templates/check_eventi.pt
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Verifica dello stato degli Eventi
+
+ Non hai i permessi per vedere questo elenco di informazioni. Se pensi
+ che questo non sia corretto verifica di essere autenticato oppure rivolgiti
+ agli amministratori del sito.
+
+
+
+
+ La lista seguente elenca tutti quegli Eventi per i quali non sono
+ ancora stati aggiunti i campi che AGID indica come obbligatori.
+ Ogni redattore può vedere in questa lista tutti gli Eventi e,
+ cliccando su ognuno, andare alla vista di dettaglio dell'Evento,
+ editarlo e compilare tutti i campi obbligatori.
+
Si fa notare, infine, che la seguente lista degli Eventi
+ presenta tutti quelli in stato pubblicato e
+ non scaduti
+ secondo
+ le logiche di pubblicazione del CMS Plone, ovvero con una data di scadenza ancora da raggiugnere.
+
+
+
+
+
+
+
+
+
+
+
+ Titolo
+ Descrizione
+ Data
+ Luogo
+ Costo
+ Contatti
+
+
+
+
+ ${evento/title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/design/plone/contenttypes/browser/utils/templates/utils.pt b/src/design/plone/contenttypes/browser/utils/templates/utils.pt
index 364313ca..12ecc6c5 100644
--- a/src/design/plone/contenttypes/browser/utils/templates/utils.pt
+++ b/src/design/plone/contenttypes/browser/utils/templates/utils.pt
@@ -39,6 +39,12 @@
Verifica dello stato dei servizi.
+
+ Check eventi
+
+ Verifica dello stato degli eventi.
+
+
From de4df094ed4adf305a168930ea997a104ee53c28 Mon Sep 17 00:00:00 2001
From: Mauro Amico
Date: Thu, 23 Nov 2023 15:10:47 +0100
Subject: [PATCH 2/4] zpretty
---
.../plone/contenttypes/browser/utils/configure.zcml | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/design/plone/contenttypes/browser/utils/configure.zcml b/src/design/plone/contenttypes/browser/utils/configure.zcml
index 9668e294..5127dcf5 100644
--- a/src/design/plone/contenttypes/browser/utils/configure.zcml
+++ b/src/design/plone/contenttypes/browser/utils/configure.zcml
@@ -53,6 +53,12 @@
class=".check_persone.DownloadCheckPersone"
permission="zope2.Public"
/>
+
Date: Thu, 23 Nov 2023 15:11:31 +0100
Subject: [PATCH 3/4] ci: cache tox
---
.github/workflows/tests.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index d7b0bd7b..0f5ee019 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -32,6 +32,7 @@ jobs:
path: |
~/.cache/pip
eggs
+ .tox
key: ${{ runner.os }}-pip-${{ matrix.config[0] }}-${{ hashFiles('setup.*', 'tox.ini') }}
restore-keys: |
${{ runner.os }}-pip-${{ matrix.config[0] }}-
From 9d0828a2793900cff1756c3001282be06de0a032 Mon Sep 17 00:00:00 2001
From: Mauro Amico
Date: Thu, 23 Nov 2023 18:15:35 +0100
Subject: [PATCH 4/4] Update
src/design/plone/contenttypes/browser/utils/configure.zcml
---
src/design/plone/contenttypes/browser/utils/configure.zcml | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/design/plone/contenttypes/browser/utils/configure.zcml b/src/design/plone/contenttypes/browser/utils/configure.zcml
index 5127dcf5..a76528f4 100644
--- a/src/design/plone/contenttypes/browser/utils/configure.zcml
+++ b/src/design/plone/contenttypes/browser/utils/configure.zcml
@@ -57,6 +57,7 @@
name="check-eventi"
for="*"
class=".check_eventi.CheckEventi"
+ permission="cmf.ManagePortal"
template="templates/check_eventi.pt"
/>