# HG changeset patch # User Thierry Florac # Date 1527672194 -7200 # Node ID 070528d7f960779ac240a3c1e78d40857fdc2e7e # Parent 36062350d76879dcac1bb069b292f228eb7acf93 Added checks before publishing content diff -r 36062350d768 -r 070528d7f960 src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.mo Binary file src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.mo has changed diff -r 36062350d768 -r 070528d7f960 src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po --- 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 \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 @@ ">ATTENTION : certains modes de rendu ne prennent pas en " "compte tous les types de médias !" -#: 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}: {message}" msgstr " - {field} : {message}" -#: 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" diff -r 36062350d768 -r 070528d7f960 src/pyams_content/locales/pyams_content.pot --- 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 \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}: {message}" 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 "" diff -r 36062350d768 -r 070528d7f960 src/pyams_content/shared/common/interfaces/__init__.py --- 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""" diff -r 36062350d768 -r 070528d7f960 src/pyams_content/shared/common/security.py --- 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) diff -r 36062350d768 -r 070528d7f960 src/pyams_content/shared/common/zmi/security.py --- 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 '' + 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 '' + 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 '' 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', diff -r 36062350d768 -r 070528d7f960 src/pyams_content/shared/common/zmi/templates/check-input.pt --- /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 @@ +
+ + +
diff -r 36062350d768 -r 070528d7f960 src/pyams_content/shared/common/zmi/templates/preview-input.pt --- /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 @@ +
+ + +
diff -r 36062350d768 -r 070528d7f960 src/pyams_content/shared/common/zmi/workflow.py --- 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!!")), )