# HG changeset patch # User Damien Correia # Date 1527685725 -7200 # Node ID 24187991ec4c262f8c115c98ca2cd50d24d9a1da # Parent 339bbc810b9121a679c1e016e06e8a298e58adb0# Parent 73e2b54fdb63d2bdfab1f2e299474baa4447d33c merge default diff -r 339bbc810b91 -r 24187991ec4c setup.py --- a/setup.py Tue May 29 11:14:00 2018 +0200 +++ b/setup.py Wed May 30 15:08:45 2018 +0200 @@ -62,7 +62,7 @@ 'persistent', 'pyams_catalog', 'pyams_file', - 'pyams_form', + 'pyams_form >= 0.1.13', 'pyams_i18n', 'pyams_mail', 'pyams_pagelet', @@ -72,7 +72,7 @@ 'pyams_skin', 'pyams_template', 'pyams_thesaurus', - 'pyams_utils', + 'pyams_utils >= 0.1.15', 'pyams_viewlet', 'pyams_workflow', 'pyams_zmi', diff -r 339bbc810b91 -r 24187991ec4c src/pyams_content/component/paragraph/zmi/__init__.py --- a/src/pyams_content/component/paragraph/zmi/__init__.py Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/component/paragraph/zmi/__init__.py Wed May 30 15:08:45 2018 +0200 @@ -195,10 +195,16 @@ table_factory = ParagraphContainerTable else: table_factory = ParagraphContainerBaseTable + event = get_json_switched_table_refresh_event(self.context, self.request, table_factory) + table_id = event['options']['object_id'] return { 'status': 'success', 'message': self.request.localizer.translate(_("Paragraph was correctly added.")), - 'events': [get_json_switched_table_refresh_event(self.context, self.request, table_factory)] + 'events': [event], + 'callbacks': [{ + 'callback': 'PyAMS_content.paragraphs.switchLastEditor', + 'options': table_id + }] } diff -r 339bbc810b91 -r 24187991ec4c src/pyams_content/features/checker/zmi/__init__.py --- a/src/pyams_content/features/checker/zmi/__init__.py Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/features/checker/zmi/__init__.py Wed May 30 15:08:45 2018 +0200 @@ -20,13 +20,13 @@ from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION from pyams_form.interfaces.form import IWidgetsSuffixViewletsManager from pyams_skin.interfaces import IInnerPage -from pyams_skin.interfaces.viewlet import IContextActions +from pyams_skin.interfaces.viewlet import IContextActions, IToolbarViewletManager from pyams_skin.layer import IPyAMSLayer from pyams_zmi.layer import IAdminLayer # import packages from pyams_pagelet.pagelet import pagelet_config -from pyams_skin.viewlet.toolbar import ToolbarMenuItem +from pyams_skin.viewlet.toolbar import ToolbarMenuItem, ToolbarAction from pyams_viewlet.viewlet import viewlet_config, Viewlet from pyams_zmi.form import AdminDialogDisplayForm from z3c.form import field @@ -35,19 +35,22 @@ from pyams_content import _ -@viewlet_config(name='check-content.menu', context=Interface, layer=IAdminLayer, - view=IInnerPage, manager=IContextActions, permission=MANAGE_CONTENT_PERMISSION, weight=20) -class ContentCheckerMenu(ToolbarMenuItem): +@viewlet_config(name='content-check.action', context=Interface, layer=IAdminLayer, + view=IInnerPage, manager=IToolbarViewletManager, permission=MANAGE_CONTENT_PERMISSION, weight=55) +class ContentCheckerMenu(ToolbarAction): """Content checker menu item""" - label = _("Check content...") + label = _("Audit") + + group_css_class = 'btn-group margin-right-10' label_css_class = 'fa fa-fw fa-check-square-o' + css_class = 'btn btn-xs btn-default' - url = 'check-content.html' + url = 'content-check.html' modal_target = True -@pagelet_config(name='check-content.html', context=Interface, layer=IPyAMSLayer, +@pagelet_config(name='content-check.html', context=Interface, layer=IPyAMSLayer, permission=MANAGE_CONTENT_PERMISSION) class ContentCheckerForm(AdminDialogDisplayForm): """Content checker display form""" @@ -58,7 +61,7 @@ fields = field.Fields(Interface) -@viewlet_config(name='check-content', context=Interface, layer=IAdminLayer, view=ContentCheckerForm, +@viewlet_config(name='content-check', context=Interface, layer=IAdminLayer, view=ContentCheckerForm, manager=IWidgetsSuffixViewletsManager, weight=1) class ContentCheckerWidgetsSuffix(Viewlet): """Content checker widgets suffix""" diff -r 339bbc810b91 -r 24187991ec4c src/pyams_content/features/preview/zmi/__init__.py --- a/src/pyams_content/features/preview/zmi/__init__.py Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/features/preview/zmi/__init__.py Wed May 30 15:08:45 2018 +0200 @@ -44,7 +44,7 @@ label = _("Preview") - group_css_class = 'btn-group margin-right-10' + group_css_class = 'btn-group margin-right-5' label_css_class = 'fa fa-fw fa-binoculars' css_class = 'btn btn-xs btn-default' diff -r 339bbc810b91 -r 24187991ec4c 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 339bbc810b91 -r 24187991ec4c src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po --- a/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po Wed May 30 15:08:45 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 339bbc810b91 -r 24187991ec4c src/pyams_content/locales/pyams_content.pot --- a/src/pyams_content/locales/pyams_content.pot Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/locales/pyams_content.pot Wed May 30 15:08:45 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 339bbc810b91 -r 24187991ec4c src/pyams_content/shared/common/interfaces/__init__.py --- a/src/pyams_content/shared/common/interfaces/__init__.py Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/shared/common/interfaces/__init__.py Wed May 30 15:08:45 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 339bbc810b91 -r 24187991ec4c src/pyams_content/shared/common/security.py --- a/src/pyams_content/shared/common/security.py Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/shared/common/security.py Wed May 30 15:08:45 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 339bbc810b91 -r 24187991ec4c src/pyams_content/shared/common/zmi/security.py --- a/src/pyams_content/shared/common/zmi/security.py Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/shared/common/zmi/security.py Wed May 30 15:08:45 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 339bbc810b91 -r 24187991ec4c 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 15:08:45 2018 +0200 @@ -0,0 +1,41 @@ +
+ + +
diff -r 339bbc810b91 -r 24187991ec4c 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 15:08:45 2018 +0200 @@ -0,0 +1,41 @@ +
+ + +
diff -r 339bbc810b91 -r 24187991ec4c src/pyams_content/shared/common/zmi/workflow.py --- a/src/pyams_content/shared/common/zmi/workflow.py Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/shared/common/zmi/workflow.py Wed May 30 15:08:45 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!!")), ) diff -r 339bbc810b91 -r 24187991ec4c src/pyams_content/skin/resources/js/pyams_content.js --- a/src/pyams_content/skin/resources/js/pyams_content.js Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/skin/resources/js/pyams_content.js Wed May 30 15:08:45 2018 +0200 @@ -268,6 +268,9 @@ switcher.removeClass('fa-plus-square-o') .addClass('fa-minus-square-o'); para.data('ams-disabled-handlers', true); + MyAMS.skin.scrollTo(editor, { + offset: editor.height() - para.height() + }); } }); } else { @@ -279,6 +282,12 @@ } }, + switchLastEditor: function(table_id) { + var table = $('table[id="' + table_id + '"]'); + var tr = $('tr:last', table); + $('[data-ams-click-handler="PyAMS_content.paragraphs.switchEditor"]', tr).click(); + }, + switchAllEditors: function(element) { var source = $(this); var switcher = $('i', source); diff -r 339bbc810b91 -r 24187991ec4c src/pyams_content/skin/resources/js/pyams_content.min.js --- a/src/pyams_content/skin/resources/js/pyams_content.min.js Tue May 29 11:14:00 2018 +0200 +++ b/src/pyams_content/skin/resources/js/pyams_content.min.js Wed May 30 15:08:45 2018 +0200 @@ -1,1 +1,1 @@ -!function(t,e){"use strict";var a=e.MyAMS,i={widget:{treeview:{selectFolder:function(e,a){t(e.target).siblings('input[type="hidden"]').val(a.id)},unselectFolder:function(e,a){t(e.target).siblings('input[type="hidden"]').val(null)}}},TinyMCE:{initEditor:function(t){return tinyMCE.addI18n("fr",{"Link list":"Liste de liens","Toggle h3 header":"En-tête H3","Toggle h4 header":"En-tête H4","Insert internal link":"Insérer un lien interne","Link title":"Texte à afficher","Internal number":"N° interne"}),tinymce.PluginManager.add("internal_links",function(t,e){t.addButton("internal_links",{icon:"cloud-check",tooltip:"Insert internal link",image:"/--static--/pyams_content/img/internal-link.png",onclick:function(){t.windowManager.open({title:"Insert internal link",body:[{type:"textbox",name:"oid",label:"Internal number"},{type:"textbox",name:"title",label:"Link title",value:t.selection.getContent()}],onsubmit:function(e){t.insertContent(''+e.data.title+"")}})}})}),tinyMCE.PluginManager.add("headers",function(t,e){["h3","h4"].forEach(function(e){t.addButton("header-"+e,{tooltip:"Toggle "+e+" header",text:e.toUpperCase(),onClick:function(){t.execCommand("mceToggleFormat",!1,e)},onPostRender:function(){var a=this,i=function(){t.formatter.formatChanged(e,function(t){a.active(t)})};t.formatter?i():t.on("init",i)}})})}),t.image_list=i.TinyMCE.getImagesList,t.link_list=i.TinyMCE.getLinksList,t.style_formats=[{title:"Inline",items:[{title:"Bold",icon:"bold",format:"bold"},{title:"Italic",icon:"italic",format:"italic"},{title:"Underline",icon:"underline",format:"underline"},{title:"Strikethrough",icon:"strikethrough",format:"strikethrough"},{title:"Superscript",icon:"superscript",format:"superscript"},{title:"Subscript",icon:"subscript",format:"subscript"},{title:"Code",icon:"code",format:"code"}]},{title:"Blocks",items:[{title:"Paragraph",format:"p"},{title:"Blockquote",format:"blockquote"},{title:"Div",format:"div"},{title:"Pre",format:"pre"}]},{title:"Alignment",items:[{title:"Left",icon:"alignleft",format:"alignleft"},{title:"Center",icon:"aligncenter",format:"aligncenter"},{title:"Right",icon:"alignright",format:"alignright"},{title:"Justify",icon:"alignjustify",format:"alignjustify"}]}],t.plugins+=" internal_links headers",t.toolbar1&&(t.toolbar1="undo redo | header-h3 header-h4 styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent"),t.toolbar2&&(t.toolbar2="forecolor backcolor | charmap internal_links link | fullscreen preview print | code"),t},getImagesList:function(e){var i=t(document.activeElement).parents("form");if(i.exists()){var n=i.attr("data-ams-form-handler")||i.attr("action"),s=n.substr(0,n.lastIndexOf("/")+1);return a.ajax.post(s+"get-images-list.json",{},e)}},getLinksList:function(e){var i=t(document.activeElement).parents("form");if(i.exists()){var n=i.attr("data-ams-form-handler")||i.attr("action"),s=n.substr(0,n.lastIndexOf("/")+1);return a.ajax.post(s+"get-links-list.json",{},e)}}},galleries:{updateMediaTitle:function(e){t('img[id="'+e.media_id+'"]').attr("original-title",e.title)},switchMediaVisibility:function(e){return function(){var e=t(this),i=e.parents(".media"),n=i.parents(".gallery");a.ajax.post(n.data("ams-location")+"/set-media-visibility.json",{object_name:i.data("ams-element-name")},function(a,i){a.visible?(t("i",e).attr("class","fa fa-fw fa-eye"),e.parents(".btn-group").siblings("a.fancyimg").removeClass("not-visible")):(t("i",e).attr("class","fa fa-fw fa-eye-slash text-danger"),e.parents(".btn-group").siblings("a.fancyimg").addClass("not-visible"))})}},setOrder:function(e,i){if(!i||!i.item.hasClass("already-dropped")){var n=i.item.parents(".gallery"),s=t(".media",n).listattr("data-ams-element-name");a.ajax.post(n.data("ams-location")+"/set-medias-order.json",{medias:JSON.stringify(s)})}},removeMedia:function(e){return function(){var e=t(this);a.skin.bigBox({title:a.i18n.WARNING,content:'  '+a.i18n.DELETE_WARNING,buttons:a.i18n.BTN_OK_CANCEL},function(t){if(t===a.i18n.BTN_OK){var i=e.parents(".gallery").data("ams-location"),n=e.parents(".media"),s=n.data("ams-element-name");a.ajax.post(i+"/delete-element.json",{object_name:s},function(t,e){n.remove()})}})}},afterFancyboxLoad:function(t,e){t.element.hasClass("not-visible")&&t.inner.prepend('
')}},paragraphs:{preReload:function(){i.paragraphs.switched=t("i.switch.fa-minus-square-o","#paragraphs_list").parents("tr").listattr("id")},postReload:function(){t(i.paragraphs.switched).each(function(){t("i.switch.fa-plus-square-o",'[id="'+this+'"]').parents("div").first().click()}),delete i.paragraphs.switched},refreshParagraph:function(e){var a=t('tr[id="'+e.object_id+'"]');t("span.title",a).html(e.title||" - - - - - - - -")},switchEditor:function(e){var i=t(this),n=t("i.switch",i),s=i.parents("td"),r=t(".editor",s),o=i.parents("tr");if(n.hasClass("fa-plus-square-o")){var l=o.parents("table");r.html('

'),a.ajax.post(l.data("ams-location")+"/get-paragraph-editor.json",{object_name:o.data("ams-element-name")},function(t){r.html(t),t&&(a.initContent(r),n.removeClass("fa-plus-square-o").addClass("fa-minus-square-o"),o.data("ams-disabled-handlers",!0))})}else a.skin.cleanContainer(r),r.empty(),n.removeClass("fa-minus-square-o").addClass("fa-plus-square-o"),o.removeData("ams-disabled-handlers")},switchAllEditors:function(e){var i=t(this),n=t("i",i),s=i.parents("table");n.hasClass("fa-plus-square-o")?(n.removeClass("fa-plus-square-o").addClass("fa-cog fa-spin"),a.ajax.post(s.data("ams-location")+"/get-paragraphs-editors.json",{},function(e){for(var i in e)if(e.hasOwnProperty(i)){var r=t('tr[data-ams-element-name="'+i+'"]',s),o=t(".editor",r);o.is(":empty")&&o.html(e[i]),t(".fa-plus-square-o",r).removeClass("fa-plus-square-o").addClass("fa-minus-square-o"),r.data("ams-disabled-handlers",!0)}t("i.fa-plus-square-o",t("tbody",s)).exists()||n.removeClass("fa-cog fa-spin").addClass("fa-minus-square-o"),a.initContent(s)})):(t(".editor",s).each(function(){a.skin.cleanContainer(t(this)),t(this).empty()}),t(".fa-minus-square-o",s).removeClass("fa-minus-square-o").addClass("fa-plus-square-o"),t("tr",s).removeData("ams-disabled-handlers"))},updateToolbar:function(e){var i=t('tr[id="'+e.object_id+'"]'),n=t(".title-toolbar",i);n.replaceWith(e.toolbar_tag),n=t(".title-toolbar",i),a.initContent(n)},updateMarkers:function(e){var i=t('tr[id="'+e.object_id+'"]'),n=t(".title-toolbar",i),s=t("DIV.action."+e.marker_type,n);s.exists()?s.replaceWith(e.marker_tag):t(e.marker_tag).appendTo(n),e.marker_tag&&(s=t("DIV.action."+e.marker_type,n),a.initContent(s)),a.helpers.sort(n,"weight")}},pictograms:{initManagerSelection:function(){var e=t(this),a=t('input[type="hidden"]',t(".selected-pictograms",e)).listattr("value");return{selected:JSON.stringify(a)}},switchPictogram:function(){var e=t(this),a=e.parents(".pictograms"),i=a.parents(".pictograms-manager");a.hasClass("available-pictograms")?t(".selected-pictograms",i).append(e):t(".available-pictograms",i).append(e)}},themes:{initExtracts:function(e){var i=t('select[name="form.widgets.thesaurus_name:list"]',e).val(),n=t('select[name="form.widgets.extract_name:list"]',e),s=n.val();i&&a.jsonrpc.post("getExtracts",{thesaurus_name:i},{url:"/api/thesaurus/json"},function(e){n.empty(),t(e.result).each(function(){t("").attr("value",this.id).attr("selected",this.id===s).text(this.text).appendTo(n)})}),n.attr("data-ams-events-handlers",'{"select2-open": "PyAMS_content.themes.getExtracts"}')},getExtracts:function(e){var i=t(e.currentTarget).parents("form"),n=t('select[name="form.widgets.thesaurus_name:list"]',i).val();n&&a.jsonrpc.post("getExtracts",{thesaurus_name:n},{url:"/api/thesaurus/json"},function(e){var a=t('select[name="form.widgets.extract_name:list"]',i).data("select2");a.results.empty(),a.opts.populateResults.call(a,a.results,e.result,{term:""})})}},fields:{refreshField:function(e){var a=t('table[id="form_fields_list"]'),i=t('tr[data-ams-element-name="'+e.object_name+'"]',a);t("td:nth-child(4)",i).html(e.title)}},imgmap:{init:function(){var e=t(this);a.ajax.check(t.fn.canvasAreaDraw,"/--static--/pyams_content/js/jquery-canvasAreaDraw"+a.devext+".js",function(){e.canvasAreaDraw({imageUrl:e.data("ams-image-url")})})},initPreview:function(){var e=t(this);a.ajax.check(t.fn.mapster,"/--static--/pyams_content/js/jquery-imagemapster-1.2.10"+a.devext+".js",function(){e.mapster({fillColor:"ff0000",fillOpacity:.35,selected:!0,highlight:!0,staticState:!0})})}},types:{switchSubtypes:function(e){var i=t(this),n=t("i.switch",i),s=i.parents("td"),r=t(".subtypes",s),o=i.parents("tr");if(n.hasClass("fa-plus-square-o")){var l=o.parents("table");r.html('

'),a.ajax.post(l.data("ams-location")+"/get-subtypes-table.json",{object_name:o.data("ams-element-name")},function(t){r.html(t),t&&(a.initContent(r),n.removeClass("fa-plus-square-o").addClass("fa-minus-square-o"))})}else a.skin.cleanContainer(r),r.empty(),n.removeClass("fa-minus-square-o").addClass("fa-plus-square-o")}},site:{switchVisibility:function(){return function(){var e=t(this),i=e.parents("tr").first();a.ajax.post(i.data("ams-location")+"/switch-content-visibility.json",{object_name:i.data("ams-element-name")},function(a,i){var n="fa-eye";a.visible||(n+="-slash"),a.published||(n+=" text-danger"),t("i",e).attr("class","fa fa-fw "+n)})}}},review:{timer:null,timer_duration:{general:3e4,chat:5e3},initComments:function(e){var n=t(".chat-body",e);n.animate({scrollTop:n[0].scrollHeight},1e3),clearInterval(i.review.timer),i.review.timer=setInterval(i.review.updateComments,i.review.timer_duration.chat),a.skin.registerCleanCallback(i.review.cleanCommentsCallback)},cleanCommentsCallback:function(){clearInterval(i.review.timer),i.review.timer=setInterval(i.review.updateComments,i.review.timer_duration.general)},updateComments:function(){var e,i=t(".badge",'nav a[href="#review-comments.html"]'),n=t(".chat-body",".widget-body");e=n.exists()?t(".message",n).length:parseInt(i.text()),a.ajax.post("get-last-review-comments.json",{count:e},function(a){n.exists()&&i.removeClass("bg-color-danger").addClass("bg-color-info"),e!==a.count&&(i.text(a.count).removeClass("hidden"),n.exists()&&(t(".messages",n).append(a.content),n.animate({scrollTop:n[0].scrollHeight},1e3)),n.exists()||i.removeClass("bg-color-info").addClass("bg-color-danger").animate({padding:"3px 12px 2px","margin-right":"9px"},"slow",function(){t(this).animate({padding:"3px 6px 2px","margin-right":"15px"},"slow")}))})},initCommentData:function(e){var a=t(".chat-body",".widget-body");return{count:t(".message",a).length}},addCommentAction:function(){return function(){t('textarea[name="comment"]').focus()}},addCommentCallback:function(e){var a=t(this),i=a.parents(".widget-body");t(".messages",i).append(e.content),t('textarea[name="comment"]',a).val("");var n=t(".chat-body",i);n.animate({scrollTop:n[0].scrollHeight},1e3),t(".badge",'nav a[href="#review-comments.html"]').text(e.count).removeClass("hidden")}},profile:{switchFavorite:function(){var e=t(this),i=e.data("sequence-oid");a.ajax.post("switch-user-favorite.json",{oid:i},function(t,a){t.favorite?e.removeClass("fa-star-o").addClass("fa-star"):e.removeClass("fa-star").addClass("fa-star-o")})}}};t(".badge",'nav a[href="#review-comments.html"]').exists()&&(i.review.timer=setInterval(i.review.updateComments,i.review.timer_duration.general)),e.PyAMS_content=i}(jQuery,this); +!function(t,e){"use strict";var a=e.MyAMS,i={widget:{treeview:{selectFolder:function(e,a){t(e.target).siblings('input[type="hidden"]').val(a.id)},unselectFolder:function(e,a){t(e.target).siblings('input[type="hidden"]').val(null)}}},TinyMCE:{initEditor:function(t){return tinyMCE.addI18n("fr",{"Link list":"Liste de liens","Toggle h3 header":"En-tête H3","Toggle h4 header":"En-tête H4","Insert internal link":"Insérer un lien interne","Link title":"Texte à afficher","Internal number":"N° interne"}),tinymce.PluginManager.add("internal_links",function(t,e){t.addButton("internal_links",{icon:"cloud-check",tooltip:"Insert internal link",image:"/--static--/pyams_content/img/internal-link.png",onclick:function(){t.windowManager.open({title:"Insert internal link",body:[{type:"textbox",name:"oid",label:"Internal number"},{type:"textbox",name:"title",label:"Link title",value:t.selection.getContent()}],onsubmit:function(e){t.insertContent(''+e.data.title+"")}})}})}),tinyMCE.PluginManager.add("headers",function(t,e){["h3","h4"].forEach(function(e){t.addButton("header-"+e,{tooltip:"Toggle "+e+" header",text:e.toUpperCase(),onClick:function(){t.execCommand("mceToggleFormat",!1,e)},onPostRender:function(){var a=this,i=function(){t.formatter.formatChanged(e,function(t){a.active(t)})};t.formatter?i():t.on("init",i)}})})}),t.image_list=i.TinyMCE.getImagesList,t.link_list=i.TinyMCE.getLinksList,t.style_formats=[{title:"Inline",items:[{title:"Bold",icon:"bold",format:"bold"},{title:"Italic",icon:"italic",format:"italic"},{title:"Underline",icon:"underline",format:"underline"},{title:"Strikethrough",icon:"strikethrough",format:"strikethrough"},{title:"Superscript",icon:"superscript",format:"superscript"},{title:"Subscript",icon:"subscript",format:"subscript"},{title:"Code",icon:"code",format:"code"}]},{title:"Blocks",items:[{title:"Paragraph",format:"p"},{title:"Blockquote",format:"blockquote"},{title:"Div",format:"div"},{title:"Pre",format:"pre"}]},{title:"Alignment",items:[{title:"Left",icon:"alignleft",format:"alignleft"},{title:"Center",icon:"aligncenter",format:"aligncenter"},{title:"Right",icon:"alignright",format:"alignright"},{title:"Justify",icon:"alignjustify",format:"alignjustify"}]}],t.plugins+=" internal_links headers",t.toolbar1&&(t.toolbar1="undo redo | header-h3 header-h4 styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent"),t.toolbar2&&(t.toolbar2="forecolor backcolor | charmap internal_links link | fullscreen preview print | code"),t},getImagesList:function(e){var i=t(document.activeElement).parents("form");if(i.exists()){var n=i.attr("data-ams-form-handler")||i.attr("action"),s=n.substr(0,n.lastIndexOf("/")+1);return a.ajax.post(s+"get-images-list.json",{},e)}},getLinksList:function(e){var i=t(document.activeElement).parents("form");if(i.exists()){var n=i.attr("data-ams-form-handler")||i.attr("action"),s=n.substr(0,n.lastIndexOf("/")+1);return a.ajax.post(s+"get-links-list.json",{},e)}}},galleries:{updateMediaTitle:function(e){t('img[id="'+e.media_id+'"]').attr("original-title",e.title)},switchMediaVisibility:function(e){return function(){var e=t(this),i=e.parents(".media"),n=i.parents(".gallery");a.ajax.post(n.data("ams-location")+"/set-media-visibility.json",{object_name:i.data("ams-element-name")},function(a,i){a.visible?(t("i",e).attr("class","fa fa-fw fa-eye"),e.parents(".btn-group").siblings("a.fancyimg").removeClass("not-visible")):(t("i",e).attr("class","fa fa-fw fa-eye-slash text-danger"),e.parents(".btn-group").siblings("a.fancyimg").addClass("not-visible"))})}},setOrder:function(e,i){if(!i||!i.item.hasClass("already-dropped")){var n=i.item.parents(".gallery"),s=t(".media",n).listattr("data-ams-element-name");a.ajax.post(n.data("ams-location")+"/set-medias-order.json",{medias:JSON.stringify(s)})}},removeMedia:function(e){return function(){var e=t(this);a.skin.bigBox({title:a.i18n.WARNING,content:'  '+a.i18n.DELETE_WARNING,buttons:a.i18n.BTN_OK_CANCEL},function(t){if(t===a.i18n.BTN_OK){var i=e.parents(".gallery").data("ams-location"),n=e.parents(".media"),s=n.data("ams-element-name");a.ajax.post(i+"/delete-element.json",{object_name:s},function(t,e){n.remove()})}})}},afterFancyboxLoad:function(t,e){t.element.hasClass("not-visible")&&t.inner.prepend('
')}},paragraphs:{preReload:function(){i.paragraphs.switched=t("i.switch.fa-minus-square-o","#paragraphs_list").parents("tr").listattr("id")},postReload:function(){t(i.paragraphs.switched).each(function(){t("i.switch.fa-plus-square-o",'[id="'+this+'"]').parents("div").first().click()}),delete i.paragraphs.switched},refreshParagraph:function(e){var a=t('tr[id="'+e.object_id+'"]');t("span.title",a).html(e.title||" - - - - - - - -")},switchEditor:function(e){var i=t(this),n=t("i.switch",i),s=i.parents("td"),r=t(".editor",s),o=i.parents("tr");if(n.hasClass("fa-plus-square-o")){var l=o.parents("table");r.html('

'),a.ajax.post(l.data("ams-location")+"/get-paragraph-editor.json",{object_name:o.data("ams-element-name")},function(t){r.html(t),t&&(a.initContent(r),n.removeClass("fa-plus-square-o").addClass("fa-minus-square-o"),o.data("ams-disabled-handlers",!0),a.skin.scrollTo(r,{offset:r.height()-o.height()}))})}else a.skin.cleanContainer(r),r.empty(),n.removeClass("fa-minus-square-o").addClass("fa-plus-square-o"),o.removeData("ams-disabled-handlers")},switchLastEditor:function(e){var a=t('table[id="'+e+'"]'),i=t("tr:last",a);t('[data-ams-click-handler="PyAMS_content.paragraphs.switchEditor"]',i).click()},switchAllEditors:function(e){var i=t(this),n=t("i",i),s=i.parents("table");n.hasClass("fa-plus-square-o")?(n.removeClass("fa-plus-square-o").addClass("fa-cog fa-spin"),a.ajax.post(s.data("ams-location")+"/get-paragraphs-editors.json",{},function(e){for(var i in e)if(e.hasOwnProperty(i)){var r=t('tr[data-ams-element-name="'+i+'"]',s),o=t(".editor",r);o.is(":empty")&&o.html(e[i]),t(".fa-plus-square-o",r).removeClass("fa-plus-square-o").addClass("fa-minus-square-o"),r.data("ams-disabled-handlers",!0)}t("i.fa-plus-square-o",t("tbody",s)).exists()||n.removeClass("fa-cog fa-spin").addClass("fa-minus-square-o"),a.initContent(s)})):(t(".editor",s).each(function(){a.skin.cleanContainer(t(this)),t(this).empty()}),t(".fa-minus-square-o",s).removeClass("fa-minus-square-o").addClass("fa-plus-square-o"),t("tr",s).removeData("ams-disabled-handlers"))},updateToolbar:function(e){var i=t('tr[id="'+e.object_id+'"]'),n=t(".title-toolbar",i);n.replaceWith(e.toolbar_tag),n=t(".title-toolbar",i),a.initContent(n)},updateMarkers:function(e){var i=t('tr[id="'+e.object_id+'"]'),n=t(".title-toolbar",i),s=t("DIV.action."+e.marker_type,n);s.exists()?s.replaceWith(e.marker_tag):t(e.marker_tag).appendTo(n),e.marker_tag&&(s=t("DIV.action."+e.marker_type,n),a.initContent(s)),a.helpers.sort(n,"weight")}},pictograms:{initManagerSelection:function(){var e=t(this),a=t('input[type="hidden"]',t(".selected-pictograms",e)).listattr("value");return{selected:JSON.stringify(a)}},switchPictogram:function(){var e=t(this),a=e.parents(".pictograms"),i=a.parents(".pictograms-manager");a.hasClass("available-pictograms")?t(".selected-pictograms",i).append(e):t(".available-pictograms",i).append(e)}},themes:{initExtracts:function(e){var i=t('select[name="form.widgets.thesaurus_name:list"]',e).val(),n=t('select[name="form.widgets.extract_name:list"]',e),s=n.val();i&&a.jsonrpc.post("getExtracts",{thesaurus_name:i},{url:"/api/thesaurus/json"},function(e){n.empty(),t(e.result).each(function(){t("").attr("value",this.id).attr("selected",this.id===s).text(this.text).appendTo(n)})}),n.attr("data-ams-events-handlers",'{"select2-open": "PyAMS_content.themes.getExtracts"}')},getExtracts:function(e){var i=t(e.currentTarget).parents("form"),n=t('select[name="form.widgets.thesaurus_name:list"]',i).val();n&&a.jsonrpc.post("getExtracts",{thesaurus_name:n},{url:"/api/thesaurus/json"},function(e){var a=t('select[name="form.widgets.extract_name:list"]',i).data("select2");a.results.empty(),a.opts.populateResults.call(a,a.results,e.result,{term:""})})}},fields:{refreshField:function(e){var a=t('table[id="form_fields_list"]'),i=t('tr[data-ams-element-name="'+e.object_name+'"]',a);t("td:nth-child(4)",i).html(e.title)}},imgmap:{init:function(){var e=t(this);a.ajax.check(t.fn.canvasAreaDraw,"/--static--/pyams_content/js/jquery-canvasAreaDraw"+a.devext+".js",function(){e.canvasAreaDraw({imageUrl:e.data("ams-image-url")})})},initPreview:function(){var e=t(this);a.ajax.check(t.fn.mapster,"/--static--/pyams_content/js/jquery-imagemapster-1.2.10"+a.devext+".js",function(){e.mapster({fillColor:"ff0000",fillOpacity:.35,selected:!0,highlight:!0,staticState:!0})})}},types:{switchSubtypes:function(e){var i=t(this),n=t("i.switch",i),s=i.parents("td"),r=t(".subtypes",s),o=i.parents("tr");if(n.hasClass("fa-plus-square-o")){var l=o.parents("table");r.html('

'),a.ajax.post(l.data("ams-location")+"/get-subtypes-table.json",{object_name:o.data("ams-element-name")},function(t){r.html(t),t&&(a.initContent(r),n.removeClass("fa-plus-square-o").addClass("fa-minus-square-o"))})}else a.skin.cleanContainer(r),r.empty(),n.removeClass("fa-minus-square-o").addClass("fa-plus-square-o")}},site:{switchVisibility:function(){return function(){var e=t(this),i=e.parents("tr").first();a.ajax.post(i.data("ams-location")+"/switch-content-visibility.json",{object_name:i.data("ams-element-name")},function(a,i){var n="fa-eye";a.visible||(n+="-slash"),a.published||(n+=" text-danger"),t("i",e).attr("class","fa fa-fw "+n)})}}},review:{timer:null,timer_duration:{general:3e4,chat:5e3},initComments:function(e){var n=t(".chat-body",e);n.animate({scrollTop:n[0].scrollHeight},1e3),clearInterval(i.review.timer),i.review.timer=setInterval(i.review.updateComments,i.review.timer_duration.chat),a.skin.registerCleanCallback(i.review.cleanCommentsCallback)},cleanCommentsCallback:function(){clearInterval(i.review.timer),i.review.timer=setInterval(i.review.updateComments,i.review.timer_duration.general)},updateComments:function(){var e,i=t(".badge",'nav a[href="#review-comments.html"]'),n=t(".chat-body",".widget-body");e=n.exists()?t(".message",n).length:parseInt(i.text()),a.ajax.post("get-last-review-comments.json",{count:e},function(a){n.exists()&&i.removeClass("bg-color-danger").addClass("bg-color-info"),e!==a.count&&(i.text(a.count).removeClass("hidden"),n.exists()&&(t(".messages",n).append(a.content),n.animate({scrollTop:n[0].scrollHeight},1e3)),n.exists()||i.removeClass("bg-color-info").addClass("bg-color-danger").animate({padding:"3px 12px 2px","margin-right":"9px"},"slow",function(){t(this).animate({padding:"3px 6px 2px","margin-right":"15px"},"slow")}))})},initCommentData:function(e){var a=t(".chat-body",".widget-body");return{count:t(".message",a).length}},addCommentAction:function(){return function(){t('textarea[name="comment"]').focus()}},addCommentCallback:function(e){var a=t(this),i=a.parents(".widget-body");t(".messages",i).append(e.content),t('textarea[name="comment"]',a).val("");var n=t(".chat-body",i);n.animate({scrollTop:n[0].scrollHeight},1e3),t(".badge",'nav a[href="#review-comments.html"]').text(e.count).removeClass("hidden")}},profile:{switchFavorite:function(){var e=t(this),i=e.data("sequence-oid");a.ajax.post("switch-user-favorite.json",{oid:i},function(t,a){t.favorite?e.removeClass("fa-star-o").addClass("fa-star"):e.removeClass("fa-star").addClass("fa-star-o")})}}};t(".badge",'nav a[href="#review-comments.html"]').exists()&&(i.review.timer=setInterval(i.review.updateComments,i.review.timer_duration.general)),e.PyAMS_content=i}(jQuery,this);