Binary file src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.mo has changed
--- a/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po Tue May 29 09:51:54 2018 +0200
+++ b/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po Wed May 30 11:23:14 2018 +0200
@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2018-05-24 09:43+0200\n"
+"POT-Creation-Date: 2018-05-30 11:11+0200\n"
"PO-Revision-Date: 2015-09-10 10:42+0200\n"
"Last-Translator: Thierry Florac <tflorac@ulthar.net>\n"
"Language-Team: French\n"
@@ -81,7 +81,7 @@
msgid "Medias gallery"
msgstr "Galerie de médias"
-#: src/pyams_content/component/gallery/__init__.py:159
+#: src/pyams_content/component/gallery/__init__.py:154
msgid "Gallery"
msgstr "Galerie de médias"
@@ -321,8 +321,8 @@
#: src/pyams_content/component/extfile/__init__.py:255
#: src/pyams_content/component/extfile/__init__.py:260
-#: src/pyams_content/component/paragraph/video.py:49
-#: src/pyams_content/component/paragraph/video.py:62
+#: src/pyams_content/component/paragraph/video.py:51
+#: src/pyams_content/component/paragraph/video.py:64
msgid "Video"
msgstr "Vidéo"
@@ -479,7 +479,7 @@
#: src/pyams_content/component/illustration/paragraph.py:40
#: src/pyams_content/component/illustration/paragraph.py:47
-#: src/pyams_content/component/illustration/__init__.py:134
+#: src/pyams_content/component/illustration/__init__.py:132
#: src/pyams_content/component/illustration/zmi/__init__.py:54
#: src/pyams_content/component/illustration/zmi/__init__.py:81
msgid "Illustration"
@@ -516,13 +516,13 @@
"><strong>ATTENTION :</strong> certains modes de rendu ne prennent pas en "
"compte tous les types de médias !</span>"
-#: src/pyams_content/component/paragraph/milestone.py:205
-#: src/pyams_content/component/paragraph/milestone.py:227
+#: src/pyams_content/component/paragraph/milestone.py:199
+#: src/pyams_content/component/paragraph/milestone.py:222
#: src/pyams_content/component/paragraph/zmi/milestone.py:297
msgid "Milestones"
msgstr "Chronologie"
-#: src/pyams_content/component/paragraph/milestone.py:236
+#: src/pyams_content/component/paragraph/milestone.py:231
msgid "Milestones paragraph"
msgstr "Chronologie"
@@ -534,12 +534,12 @@
msgid "Selected paragraph is not visible"
msgstr "le bloc sélectionné n'est pas visible"
-#: src/pyams_content/component/paragraph/keypoint.py:44
+#: src/pyams_content/component/paragraph/keypoint.py:46
#: src/pyams_content/component/paragraph/interfaces/keypoint.py:39
msgid "Key points"
msgstr "Points clés"
-#: src/pyams_content/component/paragraph/keypoint.py:59
+#: src/pyams_content/component/paragraph/keypoint.py:61
msgid "Key points paragraph"
msgstr "Points clés"
@@ -551,13 +551,13 @@
msgid "no visible paragraph"
msgstr "aucun bloc de contenu visible"
-#: src/pyams_content/component/paragraph/pictogram.py:195
-#: src/pyams_content/component/paragraph/pictogram.py:217
+#: src/pyams_content/component/paragraph/pictogram.py:189
+#: src/pyams_content/component/paragraph/pictogram.py:212
#: src/pyams_content/component/paragraph/zmi/pictogram.py:301
msgid "Pictograms"
msgstr "Pictogrammes"
-#: src/pyams_content/component/paragraph/pictogram.py:226
+#: src/pyams_content/component/paragraph/pictogram.py:221
msgid "Pictograms paragraph"
msgstr "Pictogrammes"
@@ -565,61 +565,61 @@
msgid "Selected pictogram is missing"
msgstr "le pictogramme sélectionné est introuvable"
-#: src/pyams_content/component/paragraph/keynumber.py:189
-#: src/pyams_content/component/paragraph/keynumber.py:212
+#: src/pyams_content/component/paragraph/keynumber.py:183
+#: src/pyams_content/component/paragraph/keynumber.py:207
#: src/pyams_content/component/paragraph/zmi/keynumber.py:276
msgid "Key numbers"
msgstr "Chiffres-clés"
-#: src/pyams_content/component/paragraph/keynumber.py:221
+#: src/pyams_content/component/paragraph/keynumber.py:216
msgid "Key numbers paragraph"
msgstr "Chiffres-clés"
-#: src/pyams_content/component/paragraph/frame.py:50
+#: src/pyams_content/component/paragraph/frame.py:52
msgid "Framed text"
msgstr "Encadré"
-#: src/pyams_content/component/paragraph/frame.py:60
+#: src/pyams_content/component/paragraph/frame.py:62
msgid "Framed text paragraph"
msgstr "Encadré"
-#: src/pyams_content/component/paragraph/verbatim.py:48
+#: src/pyams_content/component/paragraph/verbatim.py:50
msgid "Verbatim"
msgstr "Verbatim"
-#: src/pyams_content/component/paragraph/verbatim.py:60
+#: src/pyams_content/component/paragraph/verbatim.py:62
msgid "Verbatim paragraph"
msgstr "Verbatim"
-#: src/pyams_content/component/paragraph/html.py:61
+#: src/pyams_content/component/paragraph/html.py:63
msgid "Raw HTML "
msgstr "Code HTML"
-#: src/pyams_content/component/paragraph/html.py:71
+#: src/pyams_content/component/paragraph/html.py:73
msgid "Raw HTML paragraph"
msgstr "Code HTML"
-#: src/pyams_content/component/paragraph/html.py:117
+#: src/pyams_content/component/paragraph/html.py:119
msgid "Rich text"
msgstr "Texte enrichi"
-#: src/pyams_content/component/paragraph/html.py:127
+#: src/pyams_content/component/paragraph/html.py:129
msgid "Rich text paragraph"
msgstr "Texte enrichi"
-#: src/pyams_content/component/paragraph/contact.py:45
-#: src/pyams_content/component/paragraph/contact.py:74
+#: src/pyams_content/component/paragraph/contact.py:47
+#: src/pyams_content/component/paragraph/contact.py:76
msgid "Contact card"
msgstr "Fiche contact"
-#: src/pyams_content/component/paragraph/header.py:44
+#: src/pyams_content/component/paragraph/header.py:46
#: src/pyams_content/component/paragraph/interfaces/header.py:39
#: src/pyams_content/features/alert/interfaces.py:65
#: src/pyams_content/features/alert/zmi/container.py:158
msgid "Header"
msgstr "Chapô"
-#: src/pyams_content/component/paragraph/header.py:59
+#: src/pyams_content/component/paragraph/header.py:61
msgid "Header paragraph"
msgstr "Chapô"
@@ -700,35 +700,36 @@
"REMARQUE : supprimer des types de la liste des types de blocs autorisés sera "
"sans effet sur les contenus existants."
-#: src/pyams_content/component/paragraph/zmi/__init__.py:208
+#: src/pyams_content/component/paragraph/zmi/__init__.py:214
+#: src/pyams_content/shared/common/zmi/templates/preview-input.pt:39
#: src/pyams_content/features/preview/zmi/__init__.py:45
msgid "Preview"
msgstr "Aperçu"
-#: src/pyams_content/component/paragraph/zmi/__init__.py:213
-#: src/pyams_content/shared/common/zmi/workflow.py:115
-#: src/pyams_content/shared/common/zmi/workflow.py:207
-#: src/pyams_content/shared/common/zmi/workflow.py:252
-#: src/pyams_content/shared/common/zmi/workflow.py:311
-#: src/pyams_content/shared/common/zmi/workflow.py:405
-#: src/pyams_content/shared/common/zmi/workflow.py:466
-#: src/pyams_content/shared/common/zmi/workflow.py:511
-#: src/pyams_content/shared/common/zmi/workflow.py:557
-#: src/pyams_content/shared/common/zmi/workflow.py:605
-#: src/pyams_content/shared/common/zmi/workflow.py:650
-#: src/pyams_content/shared/common/zmi/workflow.py:696
-#: src/pyams_content/shared/common/zmi/workflow.py:752
+#: src/pyams_content/component/paragraph/zmi/__init__.py:219
+#: src/pyams_content/shared/common/zmi/workflow.py:125
+#: src/pyams_content/shared/common/zmi/workflow.py:217
+#: src/pyams_content/shared/common/zmi/workflow.py:262
+#: src/pyams_content/shared/common/zmi/workflow.py:321
+#: src/pyams_content/shared/common/zmi/workflow.py:415
+#: src/pyams_content/shared/common/zmi/workflow.py:476
+#: src/pyams_content/shared/common/zmi/workflow.py:521
+#: src/pyams_content/shared/common/zmi/workflow.py:567
+#: src/pyams_content/shared/common/zmi/workflow.py:615
+#: src/pyams_content/shared/common/zmi/workflow.py:660
+#: src/pyams_content/shared/common/zmi/workflow.py:706
+#: src/pyams_content/shared/common/zmi/workflow.py:762
#: src/pyams_content/shared/common/zmi/__init__.py:276
#: src/pyams_content/shared/common/zmi/owner.py:74
#: src/pyams_content/features/review/zmi/__init__.py:90
msgid "Cancel"
msgstr "Annuler"
-#: src/pyams_content/component/paragraph/zmi/__init__.py:215
+#: src/pyams_content/component/paragraph/zmi/__init__.py:221
msgid "Submit"
msgstr "Enregistrer"
-#: src/pyams_content/component/paragraph/zmi/__init__.py:200
+#: src/pyams_content/component/paragraph/zmi/__init__.py:202
msgid "Paragraph was correctly added."
msgstr "Le bloc a été ajouté."
@@ -1236,13 +1237,13 @@
msgid "Presentation template used for this header"
msgstr "Mode de rendu utilisé par ce chapô"
-#: src/pyams_content/component/theme/__init__.py:81
+#: src/pyams_content/component/theme/__init__.py:65
#: src/pyams_content/component/theme/zmi/portlet.py:40
#: src/pyams_content/component/theme/interfaces/__init__.py:43
msgid "Themes"
msgstr "Thèmes"
-#: src/pyams_content/component/theme/__init__.py:90
+#: src/pyams_content/component/theme/__init__.py:74
msgid "no defined theme"
msgstr "aucun thème défini"
@@ -1263,8 +1264,8 @@
msgid "Selected themes"
msgstr "Thèmes sélectionnés"
-#: src/pyams_content/component/association/paragraph.py:46
-#: src/pyams_content/component/association/paragraph.py:55
+#: src/pyams_content/component/association/paragraph.py:48
+#: src/pyams_content/component/association/paragraph.py:57
msgid "Associations paragraph"
msgstr "Liens et pièces jointes"
@@ -1443,9 +1444,9 @@
"Nom de la boîte aux lettres, tel qu'il sera affiché dans l'application de "
"messagerie."
-#: src/pyams_content/component/video/paragraph.py:45
-#: src/pyams_content/component/video/paragraph.py:55
-#: src/pyams_content/component/video/__init__.py:80
+#: src/pyams_content/component/video/paragraph.py:47
+#: src/pyams_content/component/video/paragraph.py:57
+#: src/pyams_content/component/video/__init__.py:73
msgid "External video"
msgstr "Vidéo externe"
@@ -1875,50 +1876,54 @@
msgid "Click to see subtypes"
msgstr "Montrer ou caher les sous-types"
-#: src/pyams_content/shared/common/zmi/workflow.py:116
+#: src/pyams_content/shared/common/zmi/workflow.py:907
+msgid "Prior checks"
+msgstr "Contrôles préalables : avez-vous ?"
+
+#: src/pyams_content/shared/common/zmi/workflow.py:126
msgid "Request publication"
msgstr "Demander la publication"
-#: src/pyams_content/shared/common/zmi/workflow.py:208
+#: src/pyams_content/shared/common/zmi/workflow.py:218
#: src/pyams_content/workflow/__init__.py:315
msgid "Cancel publication request"
msgstr "Annuler la demande de publication"
-#: src/pyams_content/shared/common/zmi/workflow.py:253
+#: src/pyams_content/shared/common/zmi/workflow.py:263
msgid "Refuse publication request"
msgstr "Refuser la demande de publication"
-#: src/pyams_content/shared/common/zmi/workflow.py:312
+#: src/pyams_content/shared/common/zmi/workflow.py:322
#: src/pyams_content/workflow/basic.py:196
msgid "Publish"
msgstr "Publier"
-#: src/pyams_content/shared/common/zmi/workflow.py:406
+#: src/pyams_content/shared/common/zmi/workflow.py:416
msgid "Request retire"
msgstr "Demander le retrait"
-#: src/pyams_content/shared/common/zmi/workflow.py:467
+#: src/pyams_content/shared/common/zmi/workflow.py:477
msgid "Cancel retire request"
msgstr "Annuler la demande de retrait"
-#: src/pyams_content/shared/common/zmi/workflow.py:512
+#: src/pyams_content/shared/common/zmi/workflow.py:522
msgid "Retire"
msgstr "Retirer"
-#: src/pyams_content/shared/common/zmi/workflow.py:558
+#: src/pyams_content/shared/common/zmi/workflow.py:568
#: src/pyams_content/workflow/__init__.py:436
msgid "Request archive"
msgstr "Demander l'archivage"
-#: src/pyams_content/shared/common/zmi/workflow.py:606
+#: src/pyams_content/shared/common/zmi/workflow.py:616
msgid "Cancel archive request"
msgstr "Annuler la demande d'archivage"
-#: src/pyams_content/shared/common/zmi/workflow.py:651
+#: src/pyams_content/shared/common/zmi/workflow.py:661
msgid "Archive"
msgstr "Archiver"
-#: src/pyams_content/shared/common/zmi/workflow.py:697
+#: src/pyams_content/shared/common/zmi/workflow.py:707
#: src/pyams_content/workflow/__init__.py:501
#: src/pyams_content/workflow/__init__.py:513
#: src/pyams_content/workflow/__init__.py:525
@@ -1929,36 +1934,52 @@
msgid "Create new version"
msgstr "Créer une nouvelle version"
-#: src/pyams_content/shared/common/zmi/workflow.py:753
+#: src/pyams_content/shared/common/zmi/workflow.py:763
#: src/pyams_content/workflow/__init__.py:561
#: src/pyams_content/workflow/basic.py:248
msgid "Delete version"
msgstr "Supprimer cette version"
-#: src/pyams_content/shared/common/zmi/workflow.py:178
-#: src/pyams_content/shared/common/zmi/workflow.py:375
+#: src/pyams_content/shared/common/zmi/workflow.py:853
+msgid "Previewed content?"
+msgstr "Prévisualisé ce contenu ?"
+
+#: src/pyams_content/shared/common/zmi/workflow.py:857
+msgid "Verified content?"
+msgstr "Audité ce contenu ?"
+
+#: src/pyams_content/shared/common/zmi/workflow.py:188
+#: src/pyams_content/shared/common/zmi/workflow.py:385
msgid "Publication start date is required"
msgstr "La date de début de publication est obligatoire"
-#: src/pyams_content/shared/common/zmi/workflow.py:281
-#: src/pyams_content/shared/common/zmi/workflow.py:437
+#: src/pyams_content/shared/common/zmi/workflow.py:291
+#: src/pyams_content/shared/common/zmi/workflow.py:447
msgid "A comment is required"
msgstr "Le commentaire est obligatoire"
-#: src/pyams_content/shared/common/zmi/workflow.py:776
+#: src/pyams_content/shared/common/zmi/workflow.py:786
msgid "Delete content"
msgstr "Supprimer définitivement ce contenu"
-#: src/pyams_content/shared/common/zmi/workflow.py:785
+#: src/pyams_content/shared/common/zmi/workflow.py:795
msgid "Delete definitively"
msgstr "Supprimer définitivement"
-#: src/pyams_content/shared/common/zmi/workflow.py:80
+#: src/pyams_content/shared/common/zmi/workflow.py:920
+msgid ""
+"You must confirm that you previewed and checked this content before "
+"requesting publication!!"
+msgstr ""
+"Vous devez avoir prévisualisé et audité ce contenu avant de pouvoir le "
+"publier !!"
+
+#: src/pyams_content/shared/common/zmi/workflow.py:90
#, python-format
msgid "{state} | by {principal}"
msgstr "{state} | par {principal}"
-#: src/pyams_content/shared/common/zmi/workflow.py:76
+#: src/pyams_content/shared/common/zmi/workflow.py:86
#: src/pyams_content/workflow/__init__.py:648
#: src/pyams_content/workflow/__init__.py:619
#: src/pyams_content/workflow/basic.py:315
@@ -2400,36 +2421,64 @@
msgid "Content publication start date is not passed yet"
msgstr "La date de début de publication n'est pas encore atteinte"
-#: src/pyams_content/shared/common/zmi/security.py:61
+#: src/pyams_content/shared/common/zmi/security.py:65
+msgid "Contributors restrictions"
+msgstr "Paramètres des contributeurs"
+
+#: src/pyams_content/shared/common/zmi/security.py:74
+msgid "Content contributors restrictions"
+msgstr "Liste des contributeurs"
+
+#: src/pyams_content/shared/common/zmi/security.py:108
+msgid "Contributor name"
+msgstr "Nom du contributeur"
+
+#: src/pyams_content/shared/common/zmi/security.py:119
+#: src/pyams_content/shared/common/zmi/security.py:277
+#: src/pyams_content/shared/common/interfaces/__init__.py:252
+#: src/pyams_content/shared/common/interfaces/__init__.py:277
+msgid "Publication checks"
+msgstr "Activer le tunnel de publication"
+
+#: src/pyams_content/shared/common/zmi/security.py:225
msgid "Managers restrictions"
-msgstr "Restrictions des responsables"
-
-#: src/pyams_content/shared/common/zmi/security.py:70
+msgstr "Paramètres des responsables"
+
+#: src/pyams_content/shared/common/zmi/security.py:234
msgid "Content managers restrictions"
msgstr "Liste des responsables"
-#: src/pyams_content/shared/common/zmi/security.py:102
+#: src/pyams_content/shared/common/zmi/security.py:266
msgid "Manager name"
msgstr "Nom du responsable"
-#: src/pyams_content/shared/common/zmi/security.py:112
+#: src/pyams_content/shared/common/zmi/security.py:294
msgid "Restricted"
msgstr "Restrictions"
-#: src/pyams_content/shared/common/zmi/security.py:129
+#: src/pyams_content/shared/common/zmi/security.py:311
msgid "Owners"
msgstr "Propriétaires"
-#: src/pyams_content/shared/common/zmi/security.py:178
+#: src/pyams_content/shared/common/zmi/security.py:401
+msgid "Publication workflow"
+msgstr "Workflow de publication"
+
+#: src/pyams_content/shared/common/zmi/security.py:168
+#, python-format
+msgid "Edit contributor restrictions for « {0} »"
+msgstr "Gérer les paramètres d'intervention de « {0} »"
+
+#: src/pyams_content/shared/common/zmi/security.py:360
#, python-format
msgid "Edit manager restrictions for « {0} »"
-msgstr "Gérer le périmètre d'intervention de « {0} »"
-
-#: src/pyams_content/shared/common/zmi/security.py:220
+msgstr "Gérer les paramètres d'intervention de « {0} »"
+
+#: src/pyams_content/shared/common/zmi/security.py:407
msgid "Apply contents restrictions"
msgstr "Appliquer des restrictions d'accès"
-#: src/pyams_content/shared/common/zmi/security.py:222
+#: src/pyams_content/shared/common/zmi/security.py:409
msgid ""
"You can specify which contents this manager will be able to manage. If you "
"specify several criteria, the manager will be able to manage contents for "
@@ -2508,6 +2557,19 @@
"actuel ; il pourra ensuite à nouveau être publié, en créant une nouvelle "
"version."
+#: src/pyams_content/shared/common/zmi/templates/check-input.pt:34
+#: src/pyams_content/shared/common/zmi/templates/preview-input.pt:34
+#: src/pyams_content/shared/common/interfaces/types.py:39
+#: src/pyams_content/shared/form/zmi/field.py:159
+#: src/pyams_content/shared/form/interfaces/__init__.py:61
+msgid "Label"
+msgstr "Libellé"
+
+#: src/pyams_content/shared/common/zmi/templates/check-input.pt:39
+#: src/pyams_content/features/checker/zmi/__init__.py:43
+msgid "Audit"
+msgstr "Audit"
+
#: src/pyams_content/shared/common/zmi/templates/dashboard.pt:28
#: src/pyams_content/root/zmi/templates/dashboard.pt:28
msgid "Quick search..."
@@ -2735,12 +2797,6 @@
msgid "Name of this data type; must be unique between all data types"
msgstr "Nom de ce type de donnée ; doit être unique entre tous les types"
-#: src/pyams_content/shared/common/interfaces/types.py:39
-#: src/pyams_content/shared/form/zmi/field.py:159
-#: src/pyams_content/shared/form/interfaces/__init__.py:61
-msgid "Label"
-msgstr "Libellé"
-
#: src/pyams_content/shared/common/interfaces/types.py:42
msgid "Navigation label"
msgstr "Libellé de navigation"
@@ -3001,15 +3057,31 @@
"Les invités sont autorisés à consulter des contenus dont l'accès a été "
"restreint"
-#: src/pyams_content/shared/common/interfaces/__init__.py:216
+#: src/pyams_content/shared/common/interfaces/__init__.py:213
msgid "Principal ID"
msgstr "ID utilisateur"
-#: src/pyams_content/shared/common/interfaces/__init__.py:221
+#: src/pyams_content/shared/common/interfaces/__init__.py:253
+msgid ""
+"If 'yes', this contributor will have to confirm that contents have been "
+"previewed and checked before asking for publication"
+msgstr ""
+"Si 'oui', ce contributeur devra confirmer qu'il a bien prévisualisé et "
+"audité chaque contenu avant de pouvoir effectuer une demande de publication"
+
+#: src/pyams_content/shared/common/interfaces/__init__.py:278
+msgid ""
+"If 'yes', this manager will have to confirm that contents have been "
+"previewed and checked before publishing a content"
+msgstr ""
+"Si 'oui', ce responsable devra confirmer qu'il a bien prévisualisé et "
+"audité chaque contenu avant de pouvoir effectuer une publication"
+
+#: src/pyams_content/shared/common/interfaces/__init__.py:283
msgid "Restricted contents"
msgstr "Accès restreints"
-#: src/pyams_content/shared/common/interfaces/__init__.py:222
+#: src/pyams_content/shared/common/interfaces/__init__.py:284
msgid ""
"If 'yes', this manager will get restricted access to manage contents based "
"on selected settings"
@@ -3017,11 +3089,11 @@
"Si 'oui', ce responsable n'aura qu'un accès restreint à certains contenus en "
"fonction de paramètres spécifiques"
-#: src/pyams_content/shared/common/interfaces/__init__.py:227
+#: src/pyams_content/shared/common/interfaces/__init__.py:289
msgid "Selected owners"
msgstr "Propriétaires"
-#: src/pyams_content/shared/common/interfaces/__init__.py:228
+#: src/pyams_content/shared/common/interfaces/__init__.py:290
msgid "Manager will have access to contents owned by these principals"
msgstr ""
"Le responsable n'aura accès qu'aux contenus dont ces utilisateurs sont "
@@ -3035,51 +3107,51 @@
msgid "no field defined"
msgstr "aucun champ défini"
-#: src/pyams_content/shared/form/handler.py:85
+#: src/pyams_content/shared/form/handler.py:80
msgid "Mailto form handler"
msgstr "Envoi des données par mail"
-#: src/pyams_content/shared/form/handler.py:45
+#: src/pyams_content/shared/form/handler.py:44
msgid "No selected handler..."
msgstr "Aucun gestionnaire sélectionné"
-#: src/pyams_content/shared/form/field.py:147
+#: src/pyams_content/shared/form/field.py:137
msgid "Text"
msgstr "Texte simple"
-#: src/pyams_content/shared/form/field.py:157
+#: src/pyams_content/shared/form/field.py:147
msgid "Multi-lines text"
msgstr "Texte multi-lignes"
+#: src/pyams_content/shared/form/field.py:157
+msgid "Boolean"
+msgstr "Booléen"
+
#: src/pyams_content/shared/form/field.py:167
-msgid "Boolean"
-msgstr "Booléen"
-
-#: src/pyams_content/shared/form/field.py:177
msgid "Integer"
msgstr "Nombre entier"
-#: src/pyams_content/shared/form/field.py:187
+#: src/pyams_content/shared/form/field.py:177
msgid "Decimal"
msgstr "Nombre décimal"
+#: src/pyams_content/shared/form/field.py:187
+msgid "E-mail address"
+msgstr "Adresse de messagerie"
+
#: src/pyams_content/shared/form/field.py:197
-msgid "E-mail address"
-msgstr "Adresse de messagerie"
-
-#: src/pyams_content/shared/form/field.py:207
msgid "URI"
msgstr "URI"
-#: src/pyams_content/shared/form/field.py:217
+#: src/pyams_content/shared/form/field.py:207
msgid "Date"
msgstr "Date"
-#: src/pyams_content/shared/form/field.py:231
+#: src/pyams_content/shared/form/field.py:221
msgid "Choice"
msgstr "Choix unique dans une liste"
-#: src/pyams_content/shared/form/field.py:251
+#: src/pyams_content/shared/form/field.py:241
msgid "List"
msgstr "Choix multiples dans une liste"
@@ -3453,22 +3525,22 @@
msgid "Other terms"
msgstr "Autres thèmes"
-#: src/pyams_content/shared/imagemap/paragraph.py:45
-#: src/pyams_content/shared/imagemap/paragraph.py:58
+#: src/pyams_content/shared/imagemap/paragraph.py:47
+#: src/pyams_content/shared/imagemap/paragraph.py:60
#: src/pyams_content/shared/imagemap/interfaces/__init__.py:35
msgid "Image map"
msgstr "Image cliquable"
-#: src/pyams_content/shared/imagemap/paragraph.py:89
+#: src/pyams_content/shared/imagemap/paragraph.py:91
msgid "no selected image map"
msgstr "aucune image cliquable sélectionnée"
-#: src/pyams_content/shared/imagemap/paragraph.py:95
+#: src/pyams_content/shared/imagemap/paragraph.py:97
#, python-format
msgid "image map '{0}' can't be found"
msgstr "l'image cliquable '{0}' est introuvable"
-#: src/pyams_content/shared/imagemap/paragraph.py:103
+#: src/pyams_content/shared/imagemap/paragraph.py:105
#, python-format
msgid "image map '{0}' is not published"
msgstr "l'image cliquable '{0}' n'est pas publiée"
@@ -4239,19 +4311,19 @@
msgid "Add automatic content archiver"
msgstr "Ajout d'une tâche d'archivage automatique"
-#: src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:47
+#: src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:46
msgid "Shared sites"
msgstr "Sites et blogs"
-#: src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:66
+#: src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:67
msgid "Shared contents"
msgstr "Gabarits"
-#: src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:87
+#: src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:90
msgid "Shared tools"
msgstr "Outils"
-#: src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:108
+#: src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:113
msgid "My roles"
msgstr "Mes rôles"
@@ -4364,19 +4436,15 @@
msgid " - {field}: <span class=\"text-danger\">{message}</span>"
msgstr " - {field} : <span class=\"text-danger\">{message}</span>"
-#: src/pyams_content/features/checker/zmi/__init__.py:43
-msgid "Check content..."
-msgstr "Vérifier le contenu"
-
-#: src/pyams_content/features/checker/zmi/__init__.py:55
+#: src/pyams_content/features/checker/zmi/__init__.py:58
msgid "Content check"
-msgstr "Vérification de contenu"
-
-#: src/pyams_content/features/checker/zmi/__init__.py:79
+msgstr "Audit du contenu"
+
+#: src/pyams_content/features/checker/zmi/__init__.py:82
msgid "No checker available. This content is clean!"
msgstr "Pas de vérificateur disponible. Ce contenu est propre !"
-#: src/pyams_content/features/checker/zmi/__init__.py:75
+#: src/pyams_content/features/checker/zmi/__init__.py:78
#, python-format
msgid "{0}:"
msgstr "{0} :"
@@ -4529,17 +4597,17 @@
msgid "Presentation template used for this footer"
msgstr "Mode de rendu utilisé par ce pied de page"
-#: src/pyams_content/features/review/__init__.py:186
+#: src/pyams_content/features/review/__init__.py:180
#, python-format
msgid "Request comment: {comment}"
msgstr "Commentaire joint : {comment}"
-#: src/pyams_content/features/review/__init__.py:216
+#: src/pyams_content/features/review/__init__.py:210
#, python-format
msgid "A new comment was added on content « {0} »"
msgstr "Un nouveau commentaire a été ajouté pour le contenu « {0} »"
-#: src/pyams_content/features/review/__init__.py:173
+#: src/pyams_content/features/review/__init__.py:167
#, python-format
msgid "[{service_name}] A content review is requested"
msgstr "[{service_name}] Demande de relecture"
@@ -4745,6 +4813,9 @@
msgid "Hidden header"
msgstr "Ne pas afficher d'en-tête de pages"
+#~ msgid "Check content..."
+#~ msgstr "Auditer le contenu"
+
#~ msgid "Simple list view"
#~ msgstr "Vue simple d'une liste d'éléments"
--- a/src/pyams_content/locales/pyams_content.pot Tue May 29 09:51:54 2018 +0200
+++ b/src/pyams_content/locales/pyams_content.pot Wed May 30 11:23:14 2018 +0200
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2018-05-24 09:43+0200\n"
+"POT-Creation-Date: 2018-05-30 11:11+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -82,7 +82,7 @@
msgid "Medias gallery"
msgstr ""
-#: ./src/pyams_content/component/gallery/__init__.py:159
+#: ./src/pyams_content/component/gallery/__init__.py:154
msgid "Gallery"
msgstr ""
@@ -308,8 +308,8 @@
#: ./src/pyams_content/component/extfile/__init__.py:255
#: ./src/pyams_content/component/extfile/__init__.py:260
-#: ./src/pyams_content/component/paragraph/video.py:49
-#: ./src/pyams_content/component/paragraph/video.py:62
+#: ./src/pyams_content/component/paragraph/video.py:51
+#: ./src/pyams_content/component/paragraph/video.py:64
msgid "Video"
msgstr ""
@@ -455,7 +455,7 @@
#: ./src/pyams_content/component/illustration/paragraph.py:40
#: ./src/pyams_content/component/illustration/paragraph.py:47
-#: ./src/pyams_content/component/illustration/__init__.py:134
+#: ./src/pyams_content/component/illustration/__init__.py:132
#: ./src/pyams_content/component/illustration/zmi/__init__.py:54
#: ./src/pyams_content/component/illustration/zmi/__init__.py:81
msgid "Illustration"
@@ -489,13 +489,13 @@
msgid "Presentation template used for illustration"
msgstr ""
-#: ./src/pyams_content/component/paragraph/milestone.py:205
-#: ./src/pyams_content/component/paragraph/milestone.py:227
+#: ./src/pyams_content/component/paragraph/milestone.py:199
+#: ./src/pyams_content/component/paragraph/milestone.py:222
#: ./src/pyams_content/component/paragraph/zmi/milestone.py:297
msgid "Milestones"
msgstr ""
-#: ./src/pyams_content/component/paragraph/milestone.py:236
+#: ./src/pyams_content/component/paragraph/milestone.py:231
msgid "Milestones paragraph"
msgstr ""
@@ -507,12 +507,12 @@
msgid "Selected paragraph is not visible"
msgstr ""
-#: ./src/pyams_content/component/paragraph/keypoint.py:44
+#: ./src/pyams_content/component/paragraph/keypoint.py:46
#: ./src/pyams_content/component/paragraph/interfaces/keypoint.py:39
msgid "Key points"
msgstr ""
-#: ./src/pyams_content/component/paragraph/keypoint.py:59
+#: ./src/pyams_content/component/paragraph/keypoint.py:61
msgid "Key points paragraph"
msgstr ""
@@ -524,13 +524,13 @@
msgid "no visible paragraph"
msgstr ""
-#: ./src/pyams_content/component/paragraph/pictogram.py:195
-#: ./src/pyams_content/component/paragraph/pictogram.py:217
+#: ./src/pyams_content/component/paragraph/pictogram.py:189
+#: ./src/pyams_content/component/paragraph/pictogram.py:212
#: ./src/pyams_content/component/paragraph/zmi/pictogram.py:301
msgid "Pictograms"
msgstr ""
-#: ./src/pyams_content/component/paragraph/pictogram.py:226
+#: ./src/pyams_content/component/paragraph/pictogram.py:221
msgid "Pictograms paragraph"
msgstr ""
@@ -538,61 +538,61 @@
msgid "Selected pictogram is missing"
msgstr ""
-#: ./src/pyams_content/component/paragraph/keynumber.py:189
-#: ./src/pyams_content/component/paragraph/keynumber.py:212
+#: ./src/pyams_content/component/paragraph/keynumber.py:183
+#: ./src/pyams_content/component/paragraph/keynumber.py:207
#: ./src/pyams_content/component/paragraph/zmi/keynumber.py:276
msgid "Key numbers"
msgstr ""
-#: ./src/pyams_content/component/paragraph/keynumber.py:221
+#: ./src/pyams_content/component/paragraph/keynumber.py:216
msgid "Key numbers paragraph"
msgstr ""
-#: ./src/pyams_content/component/paragraph/frame.py:50
+#: ./src/pyams_content/component/paragraph/frame.py:52
msgid "Framed text"
msgstr ""
-#: ./src/pyams_content/component/paragraph/frame.py:60
+#: ./src/pyams_content/component/paragraph/frame.py:62
msgid "Framed text paragraph"
msgstr ""
-#: ./src/pyams_content/component/paragraph/verbatim.py:48
+#: ./src/pyams_content/component/paragraph/verbatim.py:50
msgid "Verbatim"
msgstr ""
-#: ./src/pyams_content/component/paragraph/verbatim.py:60
+#: ./src/pyams_content/component/paragraph/verbatim.py:62
msgid "Verbatim paragraph"
msgstr ""
-#: ./src/pyams_content/component/paragraph/html.py:61
+#: ./src/pyams_content/component/paragraph/html.py:63
msgid "Raw HTML "
msgstr ""
-#: ./src/pyams_content/component/paragraph/html.py:71
+#: ./src/pyams_content/component/paragraph/html.py:73
msgid "Raw HTML paragraph"
msgstr ""
-#: ./src/pyams_content/component/paragraph/html.py:117
+#: ./src/pyams_content/component/paragraph/html.py:119
msgid "Rich text"
msgstr ""
-#: ./src/pyams_content/component/paragraph/html.py:127
+#: ./src/pyams_content/component/paragraph/html.py:129
msgid "Rich text paragraph"
msgstr ""
-#: ./src/pyams_content/component/paragraph/contact.py:45
-#: ./src/pyams_content/component/paragraph/contact.py:74
+#: ./src/pyams_content/component/paragraph/contact.py:47
+#: ./src/pyams_content/component/paragraph/contact.py:76
msgid "Contact card"
msgstr ""
-#: ./src/pyams_content/component/paragraph/header.py:44
+#: ./src/pyams_content/component/paragraph/header.py:46
#: ./src/pyams_content/component/paragraph/interfaces/header.py:39
#: ./src/pyams_content/features/alert/interfaces.py:65
#: ./src/pyams_content/features/alert/zmi/container.py:158
msgid "Header"
msgstr ""
-#: ./src/pyams_content/component/paragraph/header.py:59
+#: ./src/pyams_content/component/paragraph/header.py:61
msgid "Header paragraph"
msgstr ""
@@ -663,35 +663,36 @@
"NOTICE: removing types from allowed types list will have no effect on already created contents!"
msgstr ""
-#: ./src/pyams_content/component/paragraph/zmi/__init__.py:208
+#: ./src/pyams_content/component/paragraph/zmi/__init__.py:214
+#: ./src/pyams_content/shared/common/zmi/templates/preview-input.pt:39
#: ./src/pyams_content/features/preview/zmi/__init__.py:45
msgid "Preview"
msgstr ""
-#: ./src/pyams_content/component/paragraph/zmi/__init__.py:213
-#: ./src/pyams_content/shared/common/zmi/workflow.py:115
-#: ./src/pyams_content/shared/common/zmi/workflow.py:207
-#: ./src/pyams_content/shared/common/zmi/workflow.py:252
-#: ./src/pyams_content/shared/common/zmi/workflow.py:311
-#: ./src/pyams_content/shared/common/zmi/workflow.py:405
-#: ./src/pyams_content/shared/common/zmi/workflow.py:466
-#: ./src/pyams_content/shared/common/zmi/workflow.py:511
-#: ./src/pyams_content/shared/common/zmi/workflow.py:557
-#: ./src/pyams_content/shared/common/zmi/workflow.py:605
-#: ./src/pyams_content/shared/common/zmi/workflow.py:650
-#: ./src/pyams_content/shared/common/zmi/workflow.py:696
-#: ./src/pyams_content/shared/common/zmi/workflow.py:752
+#: ./src/pyams_content/component/paragraph/zmi/__init__.py:219
+#: ./src/pyams_content/shared/common/zmi/workflow.py:125
+#: ./src/pyams_content/shared/common/zmi/workflow.py:217
+#: ./src/pyams_content/shared/common/zmi/workflow.py:262
+#: ./src/pyams_content/shared/common/zmi/workflow.py:321
+#: ./src/pyams_content/shared/common/zmi/workflow.py:415
+#: ./src/pyams_content/shared/common/zmi/workflow.py:476
+#: ./src/pyams_content/shared/common/zmi/workflow.py:521
+#: ./src/pyams_content/shared/common/zmi/workflow.py:567
+#: ./src/pyams_content/shared/common/zmi/workflow.py:615
+#: ./src/pyams_content/shared/common/zmi/workflow.py:660
+#: ./src/pyams_content/shared/common/zmi/workflow.py:706
+#: ./src/pyams_content/shared/common/zmi/workflow.py:762
#: ./src/pyams_content/shared/common/zmi/__init__.py:276
#: ./src/pyams_content/shared/common/zmi/owner.py:74
#: ./src/pyams_content/features/review/zmi/__init__.py:90
msgid "Cancel"
msgstr ""
-#: ./src/pyams_content/component/paragraph/zmi/__init__.py:215
+#: ./src/pyams_content/component/paragraph/zmi/__init__.py:221
msgid "Submit"
msgstr ""
-#: ./src/pyams_content/component/paragraph/zmi/__init__.py:200
+#: ./src/pyams_content/component/paragraph/zmi/__init__.py:202
msgid "Paragraph was correctly added."
msgstr ""
@@ -1112,7 +1113,7 @@
msgstr ""
#: ./src/pyams_content/component/paragraph/interfaces/html.py:44
-msgid "raw HTML code template"
+msgid "Raw HTML code template"
msgstr ""
#: ./src/pyams_content/component/paragraph/interfaces/html.py:64
@@ -1185,13 +1186,13 @@
msgid "Presentation template used for this header"
msgstr ""
-#: ./src/pyams_content/component/theme/__init__.py:81
+#: ./src/pyams_content/component/theme/__init__.py:65
#: ./src/pyams_content/component/theme/zmi/portlet.py:40
#: ./src/pyams_content/component/theme/interfaces/__init__.py:43
msgid "Themes"
msgstr ""
-#: ./src/pyams_content/component/theme/__init__.py:90
+#: ./src/pyams_content/component/theme/__init__.py:74
msgid "no defined theme"
msgstr ""
@@ -1212,8 +1213,8 @@
msgid "Selected themes"
msgstr ""
-#: ./src/pyams_content/component/association/paragraph.py:46
-#: ./src/pyams_content/component/association/paragraph.py:55
+#: ./src/pyams_content/component/association/paragraph.py:48
+#: ./src/pyams_content/component/association/paragraph.py:57
msgid "Associations paragraph"
msgstr ""
@@ -1384,9 +1385,9 @@
msgid "Address as displayed in address book"
msgstr ""
-#: ./src/pyams_content/component/video/paragraph.py:45
-#: ./src/pyams_content/component/video/paragraph.py:55
-#: ./src/pyams_content/component/video/__init__.py:80
+#: ./src/pyams_content/component/video/paragraph.py:47
+#: ./src/pyams_content/component/video/paragraph.py:57
+#: ./src/pyams_content/component/video/__init__.py:73
msgid "External video"
msgstr ""
@@ -1793,50 +1794,54 @@
msgid "Click to see subtypes"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:116
+#: ./src/pyams_content/shared/common/zmi/workflow.py:907
+msgid "Prior checks"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/workflow.py:126
msgid "Request publication"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:208
+#: ./src/pyams_content/shared/common/zmi/workflow.py:218
#: ./src/pyams_content/workflow/__init__.py:315
msgid "Cancel publication request"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:253
+#: ./src/pyams_content/shared/common/zmi/workflow.py:263
msgid "Refuse publication request"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:312
+#: ./src/pyams_content/shared/common/zmi/workflow.py:322
#: ./src/pyams_content/workflow/basic.py:196
msgid "Publish"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:406
+#: ./src/pyams_content/shared/common/zmi/workflow.py:416
msgid "Request retire"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:467
+#: ./src/pyams_content/shared/common/zmi/workflow.py:477
msgid "Cancel retire request"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:512
+#: ./src/pyams_content/shared/common/zmi/workflow.py:522
msgid "Retire"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:558
+#: ./src/pyams_content/shared/common/zmi/workflow.py:568
#: ./src/pyams_content/workflow/__init__.py:436
msgid "Request archive"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:606
+#: ./src/pyams_content/shared/common/zmi/workflow.py:616
msgid "Cancel archive request"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:651
+#: ./src/pyams_content/shared/common/zmi/workflow.py:661
msgid "Archive"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:697
+#: ./src/pyams_content/shared/common/zmi/workflow.py:707
#: ./src/pyams_content/workflow/__init__.py:501
#: ./src/pyams_content/workflow/__init__.py:513
#: ./src/pyams_content/workflow/__init__.py:525
@@ -1847,36 +1852,50 @@
msgid "Create new version"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:753
+#: ./src/pyams_content/shared/common/zmi/workflow.py:763
#: ./src/pyams_content/workflow/__init__.py:561
#: ./src/pyams_content/workflow/basic.py:248
msgid "Delete version"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:178
-#: ./src/pyams_content/shared/common/zmi/workflow.py:375
+#: ./src/pyams_content/shared/common/zmi/workflow.py:853
+msgid "Previewed content?"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/workflow.py:857
+msgid "Verified content?"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/workflow.py:188
+#: ./src/pyams_content/shared/common/zmi/workflow.py:385
msgid "Publication start date is required"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:281
-#: ./src/pyams_content/shared/common/zmi/workflow.py:437
+#: ./src/pyams_content/shared/common/zmi/workflow.py:291
+#: ./src/pyams_content/shared/common/zmi/workflow.py:447
msgid "A comment is required"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:776
+#: ./src/pyams_content/shared/common/zmi/workflow.py:786
msgid "Delete content"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:785
+#: ./src/pyams_content/shared/common/zmi/workflow.py:795
msgid "Delete definitively"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:80
+#: ./src/pyams_content/shared/common/zmi/workflow.py:920
+msgid ""
+"You must confirm that you previewed and checked this content before "
+"requesting publication!!"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/workflow.py:90
#, python-format
msgid "{state} | by {principal}"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/workflow.py:76
+#: ./src/pyams_content/shared/common/zmi/workflow.py:86
#: ./src/pyams_content/workflow/__init__.py:648
#: ./src/pyams_content/workflow/__init__.py:619
#: ./src/pyams_content/workflow/basic.py:315
@@ -2305,36 +2324,64 @@
msgid "Content publication start date is not passed yet"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/security.py:61
+#: ./src/pyams_content/shared/common/zmi/security.py:65
+msgid "Contributors restrictions"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/security.py:74
+msgid "Content contributors restrictions"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/security.py:108
+msgid "Contributor name"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/security.py:119
+#: ./src/pyams_content/shared/common/zmi/security.py:277
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:252
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:277
+msgid "Publication checks"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/security.py:225
msgid "Managers restrictions"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/security.py:70
+#: ./src/pyams_content/shared/common/zmi/security.py:234
msgid "Content managers restrictions"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/security.py:102
+#: ./src/pyams_content/shared/common/zmi/security.py:266
msgid "Manager name"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/security.py:112
+#: ./src/pyams_content/shared/common/zmi/security.py:294
msgid "Restricted"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/security.py:129
+#: ./src/pyams_content/shared/common/zmi/security.py:311
msgid "Owners"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/security.py:178
+#: ./src/pyams_content/shared/common/zmi/security.py:401
+msgid "Publication workflow"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/security.py:168
+#, python-format
+msgid "Edit contributor restrictions for « {0} »"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/security.py:360
#, python-format
msgid "Edit manager restrictions for « {0} »"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/security.py:220
+#: ./src/pyams_content/shared/common/zmi/security.py:407
msgid "Apply contents restrictions"
msgstr ""
-#: ./src/pyams_content/shared/common/zmi/security.py:222
+#: ./src/pyams_content/shared/common/zmi/security.py:409
msgid ""
"You can specify which contents this manager will be able to manage. If you "
"specify several criteria, the manager will be able to manage contents for "
@@ -2402,6 +2449,19 @@
"again except by creating a new version."
msgstr ""
+#: ./src/pyams_content/shared/common/zmi/templates/check-input.pt:34
+#: ./src/pyams_content/shared/common/zmi/templates/preview-input.pt:34
+#: ./src/pyams_content/shared/common/interfaces/types.py:39
+#: ./src/pyams_content/shared/form/zmi/field.py:159
+#: ./src/pyams_content/shared/form/interfaces/__init__.py:61
+msgid "Label"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/zmi/templates/check-input.pt:39
+#: ./src/pyams_content/features/checker/zmi/__init__.py:43
+msgid "Audit"
+msgstr ""
+
#: ./src/pyams_content/shared/common/zmi/templates/dashboard.pt:28
#: ./src/pyams_content/root/zmi/templates/dashboard.pt:28
msgid "Quick search..."
@@ -2594,12 +2654,6 @@
msgid "Name of this data type; must be unique between all data types"
msgstr ""
-#: ./src/pyams_content/shared/common/interfaces/types.py:39
-#: ./src/pyams_content/shared/form/zmi/field.py:159
-#: ./src/pyams_content/shared/form/interfaces/__init__.py:61
-msgid "Label"
-msgstr ""
-
#: ./src/pyams_content/shared/common/interfaces/types.py:42
msgid "Navigation label"
msgstr ""
@@ -2824,25 +2878,37 @@
"Guests are users which are allowed to view contents with restricted access"
msgstr ""
-#: ./src/pyams_content/shared/common/interfaces/__init__.py:216
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:213
msgid "Principal ID"
msgstr ""
-#: ./src/pyams_content/shared/common/interfaces/__init__.py:221
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:253
+msgid ""
+"If 'yes', this contributor will have to confirm that contents have been "
+"previewed and checked before asking for publication"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:278
+msgid ""
+"If 'yes', this manager will have to confirm that contents have been previewed"
+" and checked before publishing a content"
+msgstr ""
+
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:283
msgid "Restricted contents"
msgstr ""
-#: ./src/pyams_content/shared/common/interfaces/__init__.py:222
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:284
msgid ""
"If 'yes', this manager will get restricted access to manage contents based on"
" selected settings"
msgstr ""
-#: ./src/pyams_content/shared/common/interfaces/__init__.py:227
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:289
msgid "Selected owners"
msgstr ""
-#: ./src/pyams_content/shared/common/interfaces/__init__.py:228
+#: ./src/pyams_content/shared/common/interfaces/__init__.py:290
msgid "Manager will have access to contents owned by these principals"
msgstr ""
@@ -2854,51 +2920,51 @@
msgid "no field defined"
msgstr ""
-#: ./src/pyams_content/shared/form/handler.py:85
+#: ./src/pyams_content/shared/form/handler.py:80
msgid "Mailto form handler"
msgstr ""
-#: ./src/pyams_content/shared/form/handler.py:45
+#: ./src/pyams_content/shared/form/handler.py:44
msgid "No selected handler..."
msgstr ""
+#: ./src/pyams_content/shared/form/field.py:137
+msgid "Text"
+msgstr ""
+
#: ./src/pyams_content/shared/form/field.py:147
-msgid "Text"
+msgid "Multi-lines text"
msgstr ""
#: ./src/pyams_content/shared/form/field.py:157
-msgid "Multi-lines text"
+msgid "Boolean"
msgstr ""
#: ./src/pyams_content/shared/form/field.py:167
-msgid "Boolean"
+msgid "Integer"
msgstr ""
#: ./src/pyams_content/shared/form/field.py:177
-msgid "Integer"
+msgid "Decimal"
msgstr ""
#: ./src/pyams_content/shared/form/field.py:187
-msgid "Decimal"
+msgid "E-mail address"
msgstr ""
#: ./src/pyams_content/shared/form/field.py:197
-msgid "E-mail address"
+msgid "URI"
msgstr ""
#: ./src/pyams_content/shared/form/field.py:207
-msgid "URI"
-msgstr ""
-
-#: ./src/pyams_content/shared/form/field.py:217
msgid "Date"
msgstr ""
-#: ./src/pyams_content/shared/form/field.py:231
+#: ./src/pyams_content/shared/form/field.py:221
msgid "Choice"
msgstr ""
-#: ./src/pyams_content/shared/form/field.py:251
+#: ./src/pyams_content/shared/form/field.py:241
msgid "List"
msgstr ""
@@ -3248,22 +3314,22 @@
msgid "Other terms"
msgstr ""
-#: ./src/pyams_content/shared/imagemap/paragraph.py:45
-#: ./src/pyams_content/shared/imagemap/paragraph.py:58
+#: ./src/pyams_content/shared/imagemap/paragraph.py:47
+#: ./src/pyams_content/shared/imagemap/paragraph.py:60
#: ./src/pyams_content/shared/imagemap/interfaces/__init__.py:35
msgid "Image map"
msgstr ""
-#: ./src/pyams_content/shared/imagemap/paragraph.py:89
+#: ./src/pyams_content/shared/imagemap/paragraph.py:91
msgid "no selected image map"
msgstr ""
-#: ./src/pyams_content/shared/imagemap/paragraph.py:95
+#: ./src/pyams_content/shared/imagemap/paragraph.py:97
#, python-format
msgid "image map '{0}' can't be found"
msgstr ""
-#: ./src/pyams_content/shared/imagemap/paragraph.py:103
+#: ./src/pyams_content/shared/imagemap/paragraph.py:105
#, python-format
msgid "image map '{0}' is not published"
msgstr ""
@@ -4023,19 +4089,19 @@
msgid "Add automatic content archiver"
msgstr ""
-#: ./src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:47
+#: ./src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:46
msgid "Shared sites"
msgstr ""
-#: ./src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:66
+#: ./src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:67
msgid "Shared contents"
msgstr ""
-#: ./src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:87
+#: ./src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:90
msgid "Shared tools"
msgstr ""
-#: ./src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:108
+#: ./src/pyams_content/skin/zmi/viewlet/toplinks/__init__.py:113
msgid "My roles"
msgstr ""
@@ -4148,19 +4214,15 @@
msgid " - {field}: <span class=\"text-danger\">{message}</span>"
msgstr ""
-#: ./src/pyams_content/features/checker/zmi/__init__.py:43
-msgid "Check content..."
-msgstr ""
-
-#: ./src/pyams_content/features/checker/zmi/__init__.py:55
+#: ./src/pyams_content/features/checker/zmi/__init__.py:58
msgid "Content check"
msgstr ""
-#: ./src/pyams_content/features/checker/zmi/__init__.py:79
+#: ./src/pyams_content/features/checker/zmi/__init__.py:82
msgid "No checker available. This content is clean!"
msgstr ""
-#: ./src/pyams_content/features/checker/zmi/__init__.py:75
+#: ./src/pyams_content/features/checker/zmi/__init__.py:78
#, python-format
msgid "{0}:"
msgstr ""
@@ -4303,17 +4365,17 @@
msgid "Presentation template used for this footer"
msgstr ""
-#: ./src/pyams_content/features/review/__init__.py:186
+#: ./src/pyams_content/features/review/__init__.py:180
#, python-format
msgid "Request comment: {comment}"
msgstr ""
-#: ./src/pyams_content/features/review/__init__.py:216
+#: ./src/pyams_content/features/review/__init__.py:210
#, python-format
msgid "A new comment was added on content « {0} »"
msgstr ""
-#: ./src/pyams_content/features/review/__init__.py:173
+#: ./src/pyams_content/features/review/__init__.py:167
#, python-format
msgid "[{service_name}] A content review is requested"
msgstr ""
--- a/src/pyams_content/shared/common/interfaces/__init__.py Tue May 29 09:51:54 2018 +0200
+++ b/src/pyams_content/shared/common/interfaces/__init__.py Wed May 30 11:23:14 2018 +0200
@@ -204,19 +204,81 @@
#
+# Generic restrictions interfaces
+#
+
+class IRestrictionInfo(Interface):
+ """User restriction base interface"""
+
+ principal_id = Principal(title=_("Principal ID"),
+ required=True)
+
+ restriction_interface = Attribute("Restrictions interface")
+
+
+class IRestrictions(Interface):
+ """Restrictions manager interface"""
+
+ restrictions_key = Attribute("Restrictions annotations key")
+ restrictions_factory_interface = Attribute("Restrictions factory")
+
+ def get_restrictions(self, principal, create_if_none=False):
+ """Get manager restrictions for given principal"""
+
+ def new_restrictions(self, principal):
+ """Create new manager restrictions"""
+
+ def set_restrictions(self, principal, restrictions=None):
+ """Set manager restrictions for given principal"""
+
+ def drop_restrictions(self, principal):
+ """Drop manager restrictions for given principal"""
+
+
+class IRestrictionsFactory(Interface):
+ """Restrictions factory interface"""
+
+
+#
+# Shared tool contributor security restrictions
+#
+
+CONTRIBUTOR_RESTRICTIONS_KEY = 'pyams_content.contributor.restrictions'
+
+
+class IContributorRestrictionInfo(IRestrictionInfo):
+ """Shared content contributor restrictions"""
+
+ publication_checks = Bool(title=_("Publication checks"),
+ description=_("If 'yes', this contributor will have to confirm that contents have "
+ "been previewed and checked before asking for publication"),
+ required=False,
+ default=True)
+
+
+class IContributorRestrictions(IRestrictions):
+ """Contributor restrictions interface"""
+
+
+class IContributorRestrictionsFactory(IRestrictionsFactory):
+ """Contributor restrictions factory interface"""
+
+
+#
# Shared tool manager security restrictions
#
MANAGER_RESTRICTIONS_KEY = 'pyams_content.manager.restrictions'
-class IManagerRestrictionInfo(Interface):
+class IManagerRestrictionInfo(IRestrictionInfo):
"""Shared content manager restrictions"""
- principal_id = Principal(title=_("Principal ID"),
- required=True)
-
- restriction_interface = Attribute("Restrictions interface")
+ publication_checks = Bool(title=_("Publication checks"),
+ description=_("If 'yes', this manager will have to confirm that contents have "
+ "been previewed and checked before publishing a content"),
+ required=False,
+ default=True)
restricted_contents = Bool(title=_("Restricted contents"),
description=_("If 'yes', this manager will get restricted access to manage contents "
@@ -232,18 +294,9 @@
"""Check if principal is granted access to given content"""
-class IManagerRestrictionsFactory(Interface):
- """Manager restrictions factory interface"""
+class IManagerRestrictions(IRestrictions):
+ """Manager restrictions interface"""
-class IManagerRestrictions(Interface):
- """Manager restrictions"""
-
- def get_restrictions(self, principal):
- """Get manager restrictions for given principal"""
-
- def set_restrictions(self, principal, restrictions):
- """Set manager restrictions for given principal"""
-
- def drop_restrictions(self, principal):
- """Drop manager restrictions for given principal"""
+class IManagerRestrictionsFactory(IRestrictionsFactory):
+ """Manager restrictions factory interface"""
--- a/src/pyams_content/shared/common/security.py Tue May 29 09:51:54 2018 +0200
+++ b/src/pyams_content/shared/common/security.py Wed May 30 11:23:14 2018 +0200
@@ -16,9 +16,11 @@
# import standard library
# import interfaces
-from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION, MANAGER_ROLE
+from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION, MANAGER_ROLE, CONTRIBUTOR_ROLE
from pyams_content.shared.common.interfaces import IWfSharedContent, IManagerRestrictions, MANAGER_RESTRICTIONS_KEY, \
- IManagerRestrictionsFactory, IBaseSharedTool, IManagerRestrictionInfo
+ IManagerRestrictionsFactory, IBaseSharedTool, IManagerRestrictionInfo, IRestrictionInfo, \
+ IContributorRestrictionInfo, IContributorRestrictions, IContributorRestrictionsFactory, \
+ CONTRIBUTOR_RESTRICTIONS_KEY, IRestrictions
# import packages
from persistent import Persistent
@@ -32,19 +34,123 @@
from zope.schema.fieldproperty import FieldProperty
+@implementer(IRestrictionInfo)
+class PrincipalRestrictionInfo(Persistent):
+ """Principal restriction info"""
+
+ principal_id = FieldProperty(IManagerRestrictionInfo['principal_id'])
+
+ def __init__(self, principal_id):
+ self.principal_id = principal_id
+
+
+@implementer(IRestrictions)
+class PrincipalRestrictions(ContextAdapter):
+ """Shared tool restrictions"""
+
+ restrictions_key = None
+ restrictions_factory_interface = None
+
+ def new_restrictions(self, principal):
+ if IPrincipalInfo.providedBy(principal):
+ principal = principal.id
+ factory = self.restrictions_factory_interface(self.context)
+ return factory(principal)
+
+ def get_restrictions(self, principal, create_if_none=False):
+ if IPrincipalInfo.providedBy(principal):
+ principal = principal.id
+ restrictions_folder = get_annotation_adapter(self.context, self.restrictions_key, Folder)
+ restrictions = restrictions_folder.get(principal)
+ if (restrictions is None) and create_if_none:
+ restrictions = self.new_restrictions(principal)
+ self.set_restrictions(principal, restrictions)
+ return restrictions
+
+ def set_restrictions(self, principal, restrictions=None):
+ if IPrincipalInfo.providedBy(principal):
+ principal = principal.id
+ restrictions_folder = get_annotation_adapter(self.context, self.restrictions_key, Folder)
+ if restrictions is None:
+ restrictions = self.new_restrictions(principal)
+ restrictions_folder[principal] = restrictions
+
+ def drop_restrictions(self, principal):
+ restrictions_folder = get_annotation_adapter(self.context, self.restrictions_key)
+ if restrictions_folder is None:
+ return
+ if IPrincipalInfo.providedBy(principal):
+ principal = principal.id
+ if principal in restrictions_folder:
+ del restrictions_folder[principal]
+
+
+#
+# Contributor restrictions
+#
+
+@implementer(IContributorRestrictionInfo)
+class SharedToolContributorRestrictionInfo(PrincipalRestrictionInfo):
+ """Shared tool contributor restriction info"""
+
+ restriction_interface = IContributorRestrictionInfo
+
+ publication_checks = FieldProperty(IContributorRestrictionInfo['publication_checks'])
+
+
+@adapter_config(context=IBaseSharedTool, provides=IContributorRestrictions)
+class SharedToolContributorRestrictions(PrincipalRestrictions):
+ """Shared tool contributor restrictions"""
+
+ restrictions_key = CONTRIBUTOR_RESTRICTIONS_KEY
+ restrictions_factory_interface = IContributorRestrictionsFactory
+
+
+@subscriber(IGrantedRoleEvent, role_selector=CONTRIBUTOR_ROLE)
+def handle_added_contributor_role(event):
+ """Handle added contributor role"""
+ shared_tool = event.object.__parent__
+ contributor_restrictions = IContributorRestrictions(shared_tool, None)
+ if contributor_restrictions:
+ contributor_restrictions.set_restrictions(event.principal_id)
+
+
+@subscriber(IRevokedRoleEvent, role_selector=CONTRIBUTOR_ROLE)
+def handle_revoked_contributor_role(event):
+ """Handle revoked contributor role"""
+ restrictions = IContributorRestrictions(event.object.__parent__, None)
+ if restrictions:
+ restrictions.drop_restrictions(event.principal_id)
+
+
+@adapter_config(context=IWfSharedContent, provides=IContributorRestrictions)
+def shared_content_contributor_restrictions(context):
+ """Shared tool contributor restrictions"""
+ tool = get_parent(context, IBaseSharedTool)
+ if tool is not None:
+ return IContributorRestrictions(tool)
+
+
+@adapter_config(context=IBaseSharedTool, provides=IContributorRestrictionsFactory)
+def shared_tool_contributor_restrictions_factory(context):
+ """Default shared tool contributor restrictions factory"""
+ return SharedToolContributorRestrictionInfo
+
+
+#
+# Manager restrictions
+#
+
@implementer(IManagerRestrictionInfo)
-class SharedToolManagerRestrictionInfo(Persistent):
+class SharedToolManagerRestrictionInfo(PrincipalRestrictionInfo):
"""Shared tool manager restriction info"""
restriction_interface = IManagerRestrictionInfo
- principal_id = FieldProperty(IManagerRestrictionInfo['principal_id'])
+ publication_checks = FieldProperty(IManagerRestrictionInfo['publication_checks'])
restricted_contents = FieldProperty(IManagerRestrictionInfo['restricted_contents'])
owners = FieldProperty(IManagerRestrictionInfo['owners'])
- def __init__(self, principal_id):
- self.principal_id = principal_id
-
def check_access(self, context, permission=MANAGE_CONTENT_PERMISSION, request=None):
if request is None:
request = check_request()
@@ -58,29 +164,11 @@
@adapter_config(context=IBaseSharedTool, provides=IManagerRestrictions)
-class SharedToolManagerRestrictions(ContextAdapter):
+class SharedToolManagerRestrictions(PrincipalRestrictions):
"""Shared tool manager restrictions"""
- def get_restrictions(self, principal):
- restrictions_folder = get_annotation_adapter(self.context, MANAGER_RESTRICTIONS_KEY, Folder)
- if IPrincipalInfo.providedBy(principal):
- principal = principal.id
- return restrictions_folder.get(principal)
-
- def set_restrictions(self, principal, restrictions):
- restrictions_folder = get_annotation_adapter(self.context, MANAGER_RESTRICTIONS_KEY, Folder)
- if IPrincipalInfo.providedBy(principal):
- principal = principal.id
- restrictions_folder[principal] = restrictions
-
- def drop_restrictions(self, principal):
- restrictions_folder = get_annotation_adapter(self.context, MANAGER_RESTRICTIONS_KEY)
- if restrictions_folder is None:
- return
- if IPrincipalInfo.providedBy(principal):
- principal = principal.id
- if principal in restrictions_folder:
- del restrictions_folder[principal]
+ restrictions_key = MANAGER_RESTRICTIONS_KEY
+ restrictions_factory_interface = IManagerRestrictionsFactory
@subscriber(IGrantedRoleEvent, role_selector=MANAGER_ROLE)
@@ -89,8 +177,7 @@
shared_tool = event.object.__parent__
manager_restrictions = IManagerRestrictions(shared_tool, None)
if manager_restrictions:
- restrictions = IManagerRestrictionsFactory(shared_tool)(event.principal_id)
- manager_restrictions.set_restrictions(event.principal_id, restrictions)
+ manager_restrictions.set_restrictions(event.principal_id)
@subscriber(IRevokedRoleEvent, role_selector=MANAGER_ROLE)
--- a/src/pyams_content/shared/common/zmi/security.py Tue May 29 09:51:54 2018 +0200
+++ b/src/pyams_content/shared/common/zmi/security.py Wed May 30 11:23:14 2018 +0200
@@ -17,7 +17,7 @@
# import interfaces
from pyams_content.interfaces import MANAGE_TOOL_PERMISSION
-from pyams_content.shared.common.interfaces import IBaseSharedTool, IManagerRestrictions, IManagerRestrictionsFactory
+from pyams_content.shared.common.interfaces import IBaseSharedTool, IManagerRestrictions, IContributorRestrictions
from pyams_security.interfaces import ISecurityManager, IPrincipalInfo
from pyams_security.zmi.interfaces import IObjectSecurityMenu
from pyams_skin.interfaces import IInnerPage, IPageHeader
@@ -53,8 +53,172 @@
from pyams_content import _
+#
+# Contributor restrictions views
+#
+
+@viewlet_config(name='contributors-restrictions.menu', context=IBaseSharedTool, layer=IAdminLayer,
+ manager=IObjectSecurityMenu, permission=MANAGE_TOOL_PERMISSION, weight=910)
+class SharedToolContributorsRestrictionsMenu(MenuItem):
+ """Shared tool contributors restrictions menu"""
+
+ label = _("Contributors restrictions")
+ icon_class = 'fa-lock'
+ url = '#contributors-restrictions.html'
+
+
+class SharedToolContributorsRestrictionsTable(BaseTable):
+ """Shared tool contributors restrictions table"""
+
+ id = 'security_contributors_restrictions'
+ title = _("Content contributors restrictions")
+
+
+@adapter_config(context=(IBaseSharedTool, IAdminLayer, SharedToolContributorsRestrictionsTable), provides=IValues)
+class SharedToolContributorsRestrictionsValuesAdapter(ContextRequestViewAdapter):
+ """Shared tool contributor restrictions values adapter"""
+
+ @property
+ def values(self):
+ contributor = get_utility(ISecurityManager)
+ return sorted([contributor.get_principal(principal_id) for principal_id in self.context.contributors],
+ key=lambda x: x.title)
+
+
+@adapter_config(context=(IPrincipalInfo, IAdminLayer, SharedToolContributorsRestrictionsTable),
+ provides=ITableElementEditor)
+class ContributorInfoElementEditor(ContextRequestViewAdapter):
+ """Contributor info element editor"""
+
+ view_name = 'contributor-restrictions.html'
+
+ @property
+ def url(self):
+ return resource_url(self.view.context, self.request, self.view_name, query={'principal_id': self.context.id})
+
+ modal_target = True
+
+
+@adapter_config(name='name',
+ context=(IBaseSharedTool, IAdminLayer, SharedToolContributorsRestrictionsTable),
+ provides=IColumn)
+class SharedToolContributorsRestrictionsNameColumn(I18nColumn, GetAttrColumn):
+ """Shared tool contributor restrictions name column"""
+
+ _header = _("Contributor name")
+ attrName = 'title'
+ weight = 10
+
+
+@adapter_config(name='checks',
+ context=(IBaseSharedTool, IAdminLayer, SharedToolContributorsRestrictionsTable),
+ provides=IColumn)
+class SharedToolContributorsRestrictionsChecksColumn(I18nColumn, GetAttrColumn):
+ """Shared tool contributor enabled publication checks column"""
+
+ _header = _("Publication checks")
+ weight = 20
+ cssClasses = {'td': 'center'}
+
+ def getValue(self, obj):
+ restrictions = IContributorRestrictions(self.context).get_restrictions(obj, create_if_none=True)
+ if restrictions.publication_checks:
+ return '<i class="fa fa-fw fa-check"></i>'
+ else:
+ return '--'
+
+
+@pagelet_config(name='contributors-restrictions.html', context=IBaseSharedTool, layer=IPyAMSLayer,
+ permission=MANAGE_TOOL_PERMISSION)
+@implementer(IInnerPage)
+class SharedToolContributorsRestrictionsView(AdminView, ContainerView):
+ """Shared tool contributors restrictions view"""
+
+ table_class = SharedToolContributorsRestrictionsTable
+
+
+@adapter_config(context=(IBaseSharedTool, IAdminLayer, SharedToolContributorsRestrictionsView), provides=IPageHeader)
+class SharedToolContributorsRestrictionsHeaderAdapter(DefaultPageHeaderAdapter):
+ """Shared tool contributors restrictions header adapter"""
+
+ back_url = 'admin#protected-object-roles.html'
+ back_target = None
+
+ icon_class = 'fa fa-fw fa-lock'
+
+
+#
+# Contributor restrictions edit form
+#
+
+@pagelet_config(name='contributor-restrictions.html', context=IBaseSharedTool, layer=IPyAMSLayer,
+ permission=MANAGE_TOOL_PERMISSION)
+class SharedToolContributorRestrictionsEditForm(AdminDialogEditForm):
+ """Shared tool contributor restrictions edit form"""
+
+ prefix = 'tool_restrictions.'
+
+ icon_css_class = 'fa fa-fw fa-lock'
+
+ ajax_handler = 'contributor-restrictions.json'
+ edit_permission = MANAGE_TOOL_PERMISSION
+
+ @property
+ def legend(self):
+ return self.request.localizer.translate(_("Edit contributor restrictions for « {0} »")).format(self.principal.title)
+
+ @cached_property
+ def interface(self):
+ restrictions = self.getContent()
+ return restrictions.restriction_interface
+
+ @property
+ def fields(self):
+ fields = field.Fields(self.interface)
+ fields['publication_checks'].widgetFactory = SingleCheckBoxFieldWidget
+ return fields
+
+ @cached_property
+ def principal_id(self):
+ principal_id = self.request.params.get('principal_id') or \
+ self.request.params.get('{0}widgets.principal_id'.format(self.prefix))
+ if not principal_id:
+ raise NotFound
+ return principal_id
+
+ @cached_property
+ def principal(self):
+ manager = get_utility(ISecurityManager)
+ return manager.get_principal(self.principal_id)
+
+ def getContent(self):
+ contributor_restrictions = IContributorRestrictions(self.context)
+ return contributor_restrictions.get_restrictions(self.principal_id, create_if_none=True)
+
+ def updateWidgets(self, prefix=None):
+ super(SharedToolContributorRestrictionsEditForm, self).updateWidgets(prefix)
+ self.widgets['principal_id'].value = self.principal
+ self.widgets['principal_id'].mode = HIDDEN_MODE
+
+
+@view_config(name='contributor-restrictions.json', context=IBaseSharedTool, request_type=IPyAMSLayer,
+ permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
+class SharedToolContributorRestrictionsAJAXEditForm(AJAXEditForm, SharedToolContributorRestrictionsEditForm):
+ """Shared tool contributor restrictions edit form, JSON renderer"""
+
+ def get_ajax_output(self, changes):
+ if changes:
+ return {'status': 'reload'}
+ else:
+ return super(SharedToolContributorRestrictionsAJAXEditForm, self).get_ajax_output(changes)
+
+
+#
+# Manager restrictions views
+#
+
@viewlet_config(name='managers-restrictions.menu', context=IBaseSharedTool, layer=IAdminLayer,
- manager=IObjectSecurityMenu, permission=MANAGE_TOOL_PERMISSION, weight=910)
+ manager=IObjectSecurityMenu, permission=MANAGE_TOOL_PERMISSION, weight=920)
class SharedToolManagersRestrictionsMenu(MenuItem):
"""Shared tool managers restrictions menu"""
@@ -66,12 +230,12 @@
class SharedToolManagersRestrictionsTable(BaseTable):
"""Shared tool manager restrictions table"""
- id = 'security_manager_restrictions'
+ id = 'security_managers_restrictions'
title = _("Content managers restrictions")
@adapter_config(context=(IBaseSharedTool, IAdminLayer, SharedToolManagersRestrictionsTable), provides=IValues)
-class SharedToolManagerRestrictionsValuesAdapter(ContextRequestViewAdapter):
+class SharedToolManagersRestrictionsValuesAdapter(ContextRequestViewAdapter):
"""Shared tool manager restrictions values adapter"""
@property
@@ -83,7 +247,7 @@
@adapter_config(context=(IPrincipalInfo, IAdminLayer, SharedToolManagersRestrictionsTable),
provides=ITableElementEditor)
-class PrincipalInfoElementEditor(ContextRequestViewAdapter):
+class ManagerInfoElementEditor(ContextRequestViewAdapter):
"""Principal info element editor"""
view_name = 'manager-restrictions.html'
@@ -104,6 +268,24 @@
weight = 10
+@adapter_config(name='checks',
+ context=(IBaseSharedTool, IAdminLayer, SharedToolManagersRestrictionsTable),
+ provides=IColumn)
+class SharedToolManagerRestrictionsChecksColumn(I18nColumn, GetAttrColumn):
+ """Shared tool manager enabled publication checks column"""
+
+ _header = _("Publication checks")
+ weight = 40
+ cssClasses = {'td': 'center'}
+
+ def getValue(self, obj):
+ restrictions = IManagerRestrictions(self.context).get_restrictions(obj, create_if_none=True)
+ if restrictions.publication_checks:
+ return '<i class="fa fa-fw fa-check"></i>'
+ else:
+ return '--'
+
+
@adapter_config(name='restricted', context=(IBaseSharedTool, IAdminLayer, SharedToolManagersRestrictionsTable),
provides=IColumn)
class SharedToolManagerRestrictionsEnabledColumn(I18nColumn, GetAttrColumn):
@@ -114,8 +296,8 @@
cssClasses = {'td': 'center'}
def getValue(self, obj):
- restrictions = IManagerRestrictions(self.context).get_restrictions(obj)
- if (restrictions is not None) and restrictions.restricted_contents:
+ restrictions = IManagerRestrictions(self.context).get_restrictions(obj, create_if_none=True)
+ if restrictions.restricted_contents:
return '<i class="fa fa-fw fa-check"></i>'
else:
return '--'
@@ -185,6 +367,7 @@
@property
def fields(self):
fields = field.Fields(self.interface)
+ fields['publication_checks'].widgetFactory = SingleCheckBoxFieldWidget
fields['restricted_contents'].widgetFactory = SingleCheckBoxFieldWidget
return fields
@@ -203,11 +386,7 @@
def getContent(self):
manager_restrictions = IManagerRestrictions(self.context)
- restrictions = manager_restrictions.get_restrictions(self.principal_id)
- if restrictions is None:
- restrictions = IManagerRestrictionsFactory(self.context)(self.principal_id)
- manager_restrictions.set_restrictions(self.principal_id, restrictions)
- return restrictions
+ return manager_restrictions.get_restrictions(self.principal_id, create_if_none=True)
def updateWidgets(self, prefix=None):
super(SharedToolManagerRestrictionsEditForm, self).updateWidgets(prefix)
@@ -216,6 +395,14 @@
def updateGroups(self):
names = getFieldNamesInOrder(self.interface)
+ names.remove('publication_checks')
+ group = NamedWidgetsGroup(self, 'publication_checks', self.widgets,
+ ('publication_checks',),
+ legend=_("Publication workflow"),
+ css_class='inner')
+ group.label_css_class = 'control-label col-md-2'
+ group.input_css_class = 'col-md-10'
+ self.add_group(group)
self.add_group(NamedWidgetsGroup(self, 'restricted_access', self.widgets, names,
legend=_("Apply contents restrictions"),
css_class='inner',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/common/zmi/templates/check-input.pt Wed May 30 11:23:14 2018 +0200
@@ -0,0 +1,41 @@
+<div class="inline-group" i18n:domain="pyams_form">
+ <label class="radio"
+ tal:repeat="item view/items">
+ <input type="radio"
+ tal:define="checked item/checked"
+ tal:attributes="id item/id;
+ name item/name;
+ class view/klass;
+ value item/value;
+ style view/style;
+ title view/title;
+ lang view/lang;
+ onclick view/onclick;
+ ondblclick view/ondblclick;
+ onmousedown view/onmousedown;
+ onmouseup view/onmouseup;
+ onmouseover view/onmouseover;
+ onmousemove view/onmousemove;
+ onmouseout view/onmouseout;
+ onkeypress view/onkeypress;
+ onkeydown view/onkeydown;
+ onkeyup view/onkeyup;
+ disabled view/disabled;
+ tabindex view/tabindex;
+ onfocus view/onfocus;
+ onblur view/onblur;
+ onchange view/onchange;
+ readonly view/readonly;
+ alt view/alt;
+ accesskey view/accesskey;
+ onselect view/onselect;
+ checked python: checked and 'checked' or None;
+ data-ams-data extension:object_data(view);" />
+ <i></i><span tal:replace="item/label" i18n:translate="">Label</span>
+ </label>
+ <button class="btn btn-xs col-md-2" i18n:domain="pyams_content"
+ data-ams-url="content-check.html" data-toggle="modal">
+ <i class="fa fa-fw fa-check-square-o"></i>
+ <span i18n:translate="">Audit</span>
+ </button>
+</div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/common/zmi/templates/preview-input.pt Wed May 30 11:23:14 2018 +0200
@@ -0,0 +1,41 @@
+<div class="inline-group" i18n:domain="pyams_form">
+ <label class="radio"
+ tal:repeat="item view/items">
+ <input type="radio"
+ tal:define="checked item/checked"
+ tal:attributes="id item/id;
+ name item/name;
+ class view/klass;
+ value item/value;
+ style view/style;
+ title view/title;
+ lang view/lang;
+ onclick view/onclick;
+ ondblclick view/ondblclick;
+ onmousedown view/onmousedown;
+ onmouseup view/onmouseup;
+ onmouseover view/onmouseover;
+ onmousemove view/onmousemove;
+ onmouseout view/onmouseout;
+ onkeypress view/onkeypress;
+ onkeydown view/onkeydown;
+ onkeyup view/onkeyup;
+ disabled view/disabled;
+ tabindex view/tabindex;
+ onfocus view/onfocus;
+ onblur view/onblur;
+ onchange view/onchange;
+ readonly view/readonly;
+ alt view/alt;
+ accesskey view/accesskey;
+ onselect view/onselect;
+ checked python: checked and 'checked' or None;
+ data-ams-data extension:object_data(view);" />
+ <i></i><span tal:replace="item/label" i18n:translate="">Label</span>
+ </label>
+ <button class="btn btn-xs col-md-2" i18n:domain="pyams_content"
+ data-ams-url="content-preview.html" data-toggle="modal">
+ <i class="fa fa-fw fa-binoculars"></i>
+ <span i18n:translate="">Preview</span>
+ </button>
+</div>
--- a/src/pyams_content/shared/common/zmi/workflow.py Tue May 29 09:51:54 2018 +0200
+++ b/src/pyams_content/shared/common/zmi/workflow.py Wed May 30 11:23:14 2018 +0200
@@ -9,6 +9,12 @@
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
+from z3c.form.browser.radio import RadioWidget
+from z3c.form.widget import FieldWidget
+
+from pyams_form.group import NamedWidgetsGroup
+from pyams_form.interfaces import IFormLayer
+from pyams_form.widget import widgettemplate_config
__docformat__ = 'restructuredtext'
@@ -18,8 +24,9 @@
# import interfaces
from pyams_content.interfaces import PUBLISH_CONTENT_PERMISSION, CREATE_CONTENT_PERMISSION, MANAGE_CONTENT_PERMISSION
-from pyams_content.shared.common.interfaces import IWfSharedContent, IBaseSharedTool, ISharedContent
-from pyams_form.interfaces.form import IWidgetsPrefixViewletsManager, IFormSuffixViewletsManager
+from pyams_content.shared.common.interfaces import IWfSharedContent, IBaseSharedTool, ISharedContent, \
+ IContributorRestrictions, IManagerRestrictions
+from pyams_form.interfaces.form import IWidgetsPrefixViewletsManager, IFormSuffixViewletsManager, IInnerSubForm
from pyams_security.interfaces import ISecurityManager
from pyams_skin.layer import IPyAMSLayer
from pyams_workflow.interfaces import IWorkflowInfo, IWorkflowTransitionInfo, IWorkflowPublicationInfo, \
@@ -33,6 +40,7 @@
from pyams_form.schema import CloseButton
from pyams_pagelet.pagelet import pagelet_config
from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
from pyams_utils.date import format_datetime
from pyams_utils.registry import get_utility
from pyams_utils.text import text_to_html
@@ -41,10 +49,12 @@
from pyams_utils.url import absolute_url
from pyams_viewlet.viewlet import viewlet_config, Viewlet
from pyams_workflow.zmi.transition import WorkflowContentTransitionForm, WorkflowContentTransitionAJAXForm
+from pyams_zmi.form import InnerAdminAddForm
from pyramid.events import subscriber
from pyramid.view import view_config
from z3c.form import field, button
from zope.interface import Interface, Invalid
+from zope.schema import Bool
from pyams_content import _
@@ -831,3 +841,84 @@
if request.principal.id in context.owner:
return None
return Viewlet.__new__(cls)
+
+
+#
+# Contributor checks before publication request
+#
+
+class IContributorChecks(Interface):
+ """Contributor checks interface"""
+
+ preview = Bool(title=_("Previewed content?"),
+ required=True,
+ default=False)
+
+ check = Bool(title=_("Verified content?"),
+ required=True,
+ default=False)
+
+
+@widgettemplate_config(mode='input', template='templates/preview-input.pt', layer=IFormLayer)
+class PreviewWidget(RadioWidget):
+ """Preview check widget"""
+
+
+def PreviewFieldWidget(field, request):
+ return FieldWidget(field, PreviewWidget(request))
+
+
+@widgettemplate_config(mode='input', template='templates/check-input.pt', layer=IFormLayer)
+class CheckWidget(RadioWidget):
+ """Control check widget"""
+
+
+def CheckFieldWidget(field, request):
+ return FieldWidget(field, CheckWidget(request))
+
+
+@adapter_config(name='contributor-checks',
+ context=(IWfSharedContent, IPyAMSLayer, PublicationRequestForm),
+ provides=IInnerSubForm)
+@adapter_config(name='contributor-checks',
+ context=(IWfSharedContent, IPyAMSLayer, PublicationForm),
+ provides=IInnerSubForm)
+class ContributorChecksForm(InnerAdminAddForm):
+ """Contributor checks form"""
+
+ def __new__(cls, context, request, form):
+ principal_id = request.principal.id
+ restrictions = IManagerRestrictions(context, None)
+ if restrictions is not None:
+ manager_restrictions = restrictions.get_restrictions(principal_id)
+ if (manager_restrictions is not None) and \
+ (manager_restrictions.check_access(context, request=request)) and \
+ (not manager_restrictions.publication_checks):
+ return None
+ if isinstance(form, PublicationForm):
+ restrictions = IContributorRestrictions(context, None)
+ if restrictions is not None:
+ contributor_restrictions = restrictions.get_restrictions(principal_id)
+ if (contributor_restrictions is not None) and \
+ (not contributor_restrictions.publication_checks):
+ return None
+ return InnerAdminAddForm.__new__(cls)
+
+ legend = _("Prior checks")
+ legend_class = 'inner bold text-danger'
+
+ label_css_class = 'control-label col-md-4'
+ input_css_class = 'col-md-8'
+
+ fields = field.Fields(IContributorChecks)
+ fields['preview'].widgetFactory = PreviewFieldWidget
+ fields['check'].widgetFactory = CheckFieldWidget
+
+
+@subscriber(IDataExtractedEvent, form_selector=ContributorChecksForm)
+def handle_contributor_checks_data_extraction(event):
+ """Handle extraction of contributor checks"""
+ data = event.data
+ if not (data.get('preview') and data.get('check')):
+ event.form.widgets.errors += (Invalid(_("You must confirm that you previewed and checked this content before "
+ "requesting publication!!")), )