Binary file src/pyams_portal/locales/fr/LC_MESSAGES/pyams_portal.mo has changed
--- a/src/pyams_portal/locales/fr/LC_MESSAGES/pyams_portal.po Tue Jul 03 15:19:50 2018 +0200
+++ b/src/pyams_portal/locales/fr/LC_MESSAGES/pyams_portal.po Tue Jul 03 15:51:19 2018 +0200
@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2018-06-26 08:42+0200\n"
+"POT-Creation-Date: 2018-07-03 15:29+0200\n"
"PO-Revision-Date: 2015-05-12 12:10+0200\n"
"Last-Translator: Thierry Florac <tflorac@ulthar.net>\n"
"Language-Team: French <traduc@traduc.org>\n"
@@ -20,11 +20,11 @@
msgid "Portal template"
msgstr "Modèle de présentation"
-#: src/pyams_portal/__init__.py:43
+#: src/pyams_portal/__init__.py:46
msgid "Manage portal templates"
msgstr "Gérer les modèles de présentation"
-#: src/pyams_portal/__init__.py:47
+#: src/pyams_portal/__init__.py:50
msgid "Portal templates manager"
msgstr "Gestionnaire des modèles"
@@ -110,12 +110,12 @@
msgid "Add template"
msgstr "Ajouter un modèle"
-#: src/pyams_portal/zmi/template.py:144 src/pyams_portal/zmi/container.py:64
+#: src/pyams_portal/zmi/template.py:143 src/pyams_portal/zmi/container.py:64
#: src/pyams_portal/zmi/container.py:93
msgid "Portal templates"
msgstr "Modèles de présentation"
-#: src/pyams_portal/zmi/template.py:145
+#: src/pyams_portal/zmi/template.py:144
msgid "Add shared template"
msgstr "Ajout d'un modèle de présentation"
@@ -123,12 +123,13 @@
msgid "Presentation template"
msgstr "Présentation"
-#: src/pyams_portal/zmi/template.py:169 src/pyams_portal/zmi/layout.py:271
+#: src/pyams_portal/zmi/template.py:167 src/pyams_portal/zmi/layout.py:275
+#: src/pyams_portal/zmi/layout.py:644
msgid "Specified name is already used!"
msgstr "Le nom indiqué est déjà utilisé !"
-#: src/pyams_portal/zmi/template.py:111 src/pyams_portal/zmi/layout.py:235
-#: src/pyams_portal/zmi/layout.py:316 src/pyams_portal/zmi/layout.py:400
+#: src/pyams_portal/zmi/template.py:111 src/pyams_portal/zmi/layout.py:239
+#: src/pyams_portal/zmi/layout.py:320 src/pyams_portal/zmi/layout.py:404
#, python-format
msgid "« {0} » portal template"
msgstr "Modèle de présentation « {0} »"
@@ -138,47 +139,67 @@
msgid "{0} (local template)"
msgstr "{0} (modèle local)"
-#: src/pyams_portal/zmi/layout.py:79
+#: src/pyams_portal/zmi/layout.py:83
msgid "Properties"
msgstr "Propriétés"
-#: src/pyams_portal/zmi/layout.py:177
+#: src/pyams_portal/zmi/layout.py:181
msgid "Add row..."
msgstr "Ajouter une ligne"
-#: src/pyams_portal/zmi/layout.py:219
+#: src/pyams_portal/zmi/layout.py:223
msgid "Add slot..."
msgstr "Ajouter un panneau"
-#: src/pyams_portal/zmi/layout.py:237
+#: src/pyams_portal/zmi/layout.py:241
msgid "Add slot"
msgstr "Ajouter un panneau"
-#: src/pyams_portal/zmi/layout.py:384
+#: src/pyams_portal/zmi/layout.py:388
msgid "Add portlet..."
msgstr "Ajouter un composant"
-#: src/pyams_portal/zmi/layout.py:402
+#: src/pyams_portal/zmi/layout.py:406
msgid "Add portlet"
msgstr "Ajouter un composant"
-#: src/pyams_portal/zmi/layout.py:69
+#: src/pyams_portal/zmi/layout.py:583
+msgid "Duplicate template..."
+msgstr "Dupliquer le modèle"
+
+#: src/pyams_portal/zmi/layout.py:603
+msgid "Duplicate template"
+msgstr "Dupliquer le modèle"
+
+#: src/pyams_portal/zmi/layout.py:73
msgid "Template management"
msgstr "Ce modèle"
-#: src/pyams_portal/zmi/layout.py:103
+#: src/pyams_portal/zmi/layout.py:107
msgid "Template configuration"
msgstr "Configuration d'un modèle"
-#: src/pyams_portal/zmi/layout.py:98
+#: src/pyams_portal/zmi/layout.py:593
+msgid "Cancel"
+msgstr "Annuler"
+
+#: src/pyams_portal/zmi/layout.py:594
+msgid "Duplicate this template"
+msgstr "Dupliquer ce modèle"
+
+#: src/pyams_portal/zmi/layout.py:614
+msgid "New template name"
+msgstr "Nom du nouveau modèle"
+
+#: src/pyams_portal/zmi/layout.py:102
msgid "Local template configuration"
msgstr "Configuration d'un modèle local"
-#: src/pyams_portal/zmi/layout.py:146
+#: src/pyams_portal/zmi/layout.py:150
msgid "{{ missing portlet }}"
msgstr "{{ composant indisponible }}"
-#: src/pyams_portal/zmi/layout.py:137
+#: src/pyams_portal/zmi/layout.py:141
#, python-format
msgid ""
"Add component: {0}<br />Drag and drop button to page template to position "
@@ -187,12 +208,12 @@
"Ajouter un composant : <strong>{0}</strong><br />Faire un glisser/déposer du "
"bouton dans le modèle de présentation pour positionner le nouveau composant."
-#: src/pyams_portal/zmi/layout.py:321
+#: src/pyams_portal/zmi/layout.py:325
#, python-format
msgid "Edit « {0} » slot properties"
msgstr "Propriétés du panneau « {0} »"
-#: src/pyams_portal/zmi/layout.py:101
+#: src/pyams_portal/zmi/layout.py:105
#, python-format
msgid "Shared template configuration ({0})"
msgstr "Configuration d'un modèle partagé ({0})"
@@ -270,27 +291,27 @@
msgid "Large desktop device (> 1170px)"
msgstr "Écrans de grande taille (> 1170 px)"
-#: src/pyams_portal/zmi/templates/layout.pt:114
+#: src/pyams_portal/zmi/templates/layout.pt:116
msgid "Override parent or template settings"
msgstr "Remplacer le paramétrage du parent ou du modèle"
-#: src/pyams_portal/zmi/templates/layout.pt:133
+#: src/pyams_portal/zmi/templates/layout.pt:135
msgid "Delete row..."
msgstr "Supprimer la ligne"
-#: src/pyams_portal/zmi/templates/layout.pt:142
+#: src/pyams_portal/zmi/templates/layout.pt:144
msgid "Edit slot properties..."
msgstr "Propriétés"
-#: src/pyams_portal/zmi/templates/layout.pt:149
+#: src/pyams_portal/zmi/templates/layout.pt:151
msgid "Delete slot..."
msgstr "Supprimer le panneau"
-#: src/pyams_portal/zmi/templates/layout.pt:157
+#: src/pyams_portal/zmi/templates/layout.pt:159
msgid "Edit portlet properties..."
msgstr "Propriétés"
-#: src/pyams_portal/zmi/templates/layout.pt:165
+#: src/pyams_portal/zmi/templates/layout.pt:167
msgid "Delete portlet..."
msgstr "Supprimer le composant"
@@ -342,32 +363,32 @@
msgid "Hidden portlet"
msgstr "Composant non affiché"
-#: src/pyams_portal/interfaces/__init__.py:65
+#: src/pyams_portal/interfaces/__init__.py:68
msgid "Portlet"
msgstr "Composant"
-#: src/pyams_portal/interfaces/__init__.py:68
-#: src/pyams_portal/interfaces/__init__.py:195
+#: src/pyams_portal/interfaces/__init__.py:71
+#: src/pyams_portal/interfaces/__init__.py:198
msgid "Slot name"
msgstr "Nom du panneau"
-#: src/pyams_portal/interfaces/__init__.py:69
+#: src/pyams_portal/interfaces/__init__.py:72
msgid "Slot name to which this configuration applies"
msgstr "Nom du panneau correspondant à la configuration"
-#: src/pyams_portal/interfaces/__init__.py:82
+#: src/pyams_portal/interfaces/__init__.py:85
msgid "Portlet renderer"
msgstr "Mode de rendu"
-#: src/pyams_portal/interfaces/__init__.py:83
+#: src/pyams_portal/interfaces/__init__.py:86
msgid "Name of renderer used to render this portlet"
msgstr "Mode de rendu utilisé pour restituer ce composant"
-#: src/pyams_portal/interfaces/__init__.py:113
+#: src/pyams_portal/interfaces/__init__.py:116
msgid "Inherit parent configuration?"
msgstr "Hériter de la configuration du parent ?"
-#: src/pyams_portal/interfaces/__init__.py:114
+#: src/pyams_portal/interfaces/__init__.py:117
msgid ""
"This option is only available if context's parent is using the same "
"template..."
@@ -375,27 +396,27 @@
"Cette option n'est disponible que si le parent utilise le même modèle de "
"présentation..."
-#: src/pyams_portal/interfaces/__init__.py:196
+#: src/pyams_portal/interfaces/__init__.py:199
msgid "This name must be unique in a given template"
msgstr "Ce nom doit être unique au sein d'un modèle de présentation"
-#: src/pyams_portal/interfaces/__init__.py:199
+#: src/pyams_portal/interfaces/__init__.py:202
msgid "Row ID"
msgstr "ID de la ligne"
-#: src/pyams_portal/interfaces/__init__.py:213
+#: src/pyams_portal/interfaces/__init__.py:216
msgid "Visible slot?"
msgstr "Panneau visible ?"
-#: src/pyams_portal/interfaces/__init__.py:214
+#: src/pyams_portal/interfaces/__init__.py:217
msgid "Select 'no' to hide this slot..."
msgstr "Choisir 'non' pour masquer ce panneau..."
-#: src/pyams_portal/interfaces/__init__.py:218
+#: src/pyams_portal/interfaces/__init__.py:221
msgid "Extra small device width"
msgstr "Largeur sur très petits périphériques"
-#: src/pyams_portal/interfaces/__init__.py:219
+#: src/pyams_portal/interfaces/__init__.py:222
msgid ""
"Slot width, in columns count, on extra small devices (phones...); set to 0 "
"to hide the portlet"
@@ -403,11 +424,11 @@
"Largeur du panneau, en nombre de colonnes, sur les très petits périphériques "
"(téléphones...) ; indiquez une valeur de 0 pour masquer ce composant"
-#: src/pyams_portal/interfaces/__init__.py:225
+#: src/pyams_portal/interfaces/__init__.py:228
msgid "Small device width"
msgstr "Largeur sur petits périphériques"
-#: src/pyams_portal/interfaces/__init__.py:226
+#: src/pyams_portal/interfaces/__init__.py:229
msgid ""
"Slot width, in columns count, on small devices (tablets...); set to 0 to "
"hide the portlet"
@@ -415,11 +436,11 @@
"Largeur du panneau, en nombre de colonnes, sur les petits périphériques "
"(tablettes...) ; indiquez une valeur de 0 pour masquer ce composant"
-#: src/pyams_portal/interfaces/__init__.py:232
+#: src/pyams_portal/interfaces/__init__.py:235
msgid "Medium devices width"
msgstr "Largeur sur périphériques moyens"
-#: src/pyams_portal/interfaces/__init__.py:233
+#: src/pyams_portal/interfaces/__init__.py:236
msgid ""
"Slot width, in columns count, on medium desktop devices (>= 992 pixels); set "
"to 0 to hide the portlet"
@@ -427,11 +448,11 @@
"Largeur du panneau, en nombre de colonnes, sur les périphériques moyens (>= "
"992 pixels) ; indiquez une valeur de 0 pour masquer ce composant"
-#: src/pyams_portal/interfaces/__init__.py:239
+#: src/pyams_portal/interfaces/__init__.py:242
msgid "Large devices width"
msgstr "Largeur sur grands périphériques"
-#: src/pyams_portal/interfaces/__init__.py:240
+#: src/pyams_portal/interfaces/__init__.py:243
msgid ""
"Slot width, in columns count, on large desktop devices (>= 1200 pixels); set "
"to 0 to hide the portlet"
@@ -439,27 +460,27 @@
"Largeur du panneau, en nombre de colonnes, sur les grands périphériques (>= "
"1200 pixels) ; indiquez une valeur de 0 pour masquer ce composant"
-#: src/pyams_portal/interfaces/__init__.py:246
+#: src/pyams_portal/interfaces/__init__.py:249
msgid "CSS class"
msgstr "Class CSS"
-#: src/pyams_portal/interfaces/__init__.py:247
+#: src/pyams_portal/interfaces/__init__.py:250
msgid "CSS class applied to this slot"
msgstr "Classe CSS spécifique appliquée à ce panneau"
-#: src/pyams_portal/interfaces/__init__.py:360
+#: src/pyams_portal/interfaces/__init__.py:363
msgid "Template name"
msgstr "Nom du modèle"
-#: src/pyams_portal/interfaces/__init__.py:361
+#: src/pyams_portal/interfaces/__init__.py:364
msgid "Two registered templates can't share the same name..."
msgstr "Deux modèles partagés ne peuvent pas utiliser le même nom..."
-#: src/pyams_portal/interfaces/__init__.py:382
+#: src/pyams_portal/interfaces/__init__.py:385
msgid "Toolbar portlets"
msgstr "Composants de la barre d'outils"
-#: src/pyams_portal/interfaces/__init__.py:383
+#: src/pyams_portal/interfaces/__init__.py:386
msgid ""
"These portlets will be directly available in templates configuration page "
"toolbar"
@@ -467,52 +488,52 @@
"Ces composants seront directement accessibles dans la page de configuration "
"des modèles de présentation sous la forme d'une barre d'icônes"
-#: src/pyams_portal/interfaces/__init__.py:412
+#: src/pyams_portal/interfaces/__init__.py:415
msgid "Inherit parent template?"
msgstr "Hériter du modèle du parent ?"
-#: src/pyams_portal/interfaces/__init__.py:413
+#: src/pyams_portal/interfaces/__init__.py:416
msgid "Should we reuse parent template?"
msgstr "Doit-on ré-utiliser le modèle du parent ?"
-#: src/pyams_portal/interfaces/__init__.py:417
+#: src/pyams_portal/interfaces/__init__.py:420
msgid "Override parent template?"
msgstr "Ne pas hériter du modèle du parent ?"
-#: src/pyams_portal/interfaces/__init__.py:418
+#: src/pyams_portal/interfaces/__init__.py:421
msgid "Should we override parent template?"
msgstr "Doit-on remplacer le modèle de présentation du parent ?"
-#: src/pyams_portal/interfaces/__init__.py:422
+#: src/pyams_portal/interfaces/__init__.py:425
msgid "Use local template?"
msgstr "Utiliser un modèle local ?"
-#: src/pyams_portal/interfaces/__init__.py:423
+#: src/pyams_portal/interfaces/__init__.py:426
msgid ""
"If 'yes', you can define a custom local template instead of a shared template"
msgstr ""
"Si 'oui', vous pouvez définir un modèle de présentation local au lieu d'un "
"modèle partagé"
-#: src/pyams_portal/interfaces/__init__.py:428
+#: src/pyams_portal/interfaces/__init__.py:431
msgid "Local template"
msgstr "Modèle local"
-#: src/pyams_portal/interfaces/__init__.py:433
+#: src/pyams_portal/interfaces/__init__.py:436
msgid "Use shared template?"
msgstr "Utiliser un modèle partagé"
-#: src/pyams_portal/interfaces/__init__.py:434
+#: src/pyams_portal/interfaces/__init__.py:437
msgid "If 'yes', you can select a shared template"
msgstr ""
"Si 'oui', vous pouvez sélectionner un modèle de présentation partagé au lieu "
"d'un modèle local"
-#: src/pyams_portal/interfaces/__init__.py:438
+#: src/pyams_portal/interfaces/__init__.py:441
msgid "Page template"
msgstr "Modèle de page"
-#: src/pyams_portal/interfaces/__init__.py:439
+#: src/pyams_portal/interfaces/__init__.py:442
msgid "Template used for this page"
msgstr "Modèle de présentation utilisé pour cette page"
--- a/src/pyams_portal/locales/pyams_portal.pot Tue Jul 03 15:19:50 2018 +0200
+++ b/src/pyams_portal/locales/pyams_portal.pot Tue Jul 03 15:51:19 2018 +0200
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2018-06-26 08:42+0200\n"
+"POT-Creation-Date: 2018-07-03 15:29+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -20,11 +20,11 @@
msgid "Portal template"
msgstr ""
-#: ./src/pyams_portal/__init__.py:43
+#: ./src/pyams_portal/__init__.py:46
msgid "Manage portal templates"
msgstr ""
-#: ./src/pyams_portal/__init__.py:47
+#: ./src/pyams_portal/__init__.py:50
msgid "Portal templates manager"
msgstr ""
@@ -94,13 +94,13 @@
msgid "Add template"
msgstr ""
-#: ./src/pyams_portal/zmi/template.py:144
+#: ./src/pyams_portal/zmi/template.py:143
#: ./src/pyams_portal/zmi/container.py:64
#: ./src/pyams_portal/zmi/container.py:93
msgid "Portal templates"
msgstr ""
-#: ./src/pyams_portal/zmi/template.py:145
+#: ./src/pyams_portal/zmi/template.py:144
msgid "Add shared template"
msgstr ""
@@ -108,12 +108,13 @@
msgid "Presentation template"
msgstr ""
-#: ./src/pyams_portal/zmi/template.py:169 ./src/pyams_portal/zmi/layout.py:271
+#: ./src/pyams_portal/zmi/template.py:167 ./src/pyams_portal/zmi/layout.py:275
+#: ./src/pyams_portal/zmi/layout.py:644
msgid "Specified name is already used!"
msgstr ""
-#: ./src/pyams_portal/zmi/template.py:111 ./src/pyams_portal/zmi/layout.py:235
-#: ./src/pyams_portal/zmi/layout.py:316 ./src/pyams_portal/zmi/layout.py:400
+#: ./src/pyams_portal/zmi/template.py:111 ./src/pyams_portal/zmi/layout.py:239
+#: ./src/pyams_portal/zmi/layout.py:320 ./src/pyams_portal/zmi/layout.py:404
#, python-format
msgid "« {0} » portal template"
msgstr ""
@@ -123,59 +124,79 @@
msgid "{0} (local template)"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:79
+#: ./src/pyams_portal/zmi/layout.py:83
msgid "Properties"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:177
+#: ./src/pyams_portal/zmi/layout.py:181
msgid "Add row..."
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:219
+#: ./src/pyams_portal/zmi/layout.py:223
msgid "Add slot..."
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:237
+#: ./src/pyams_portal/zmi/layout.py:241
msgid "Add slot"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:384
+#: ./src/pyams_portal/zmi/layout.py:388
msgid "Add portlet..."
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:402
+#: ./src/pyams_portal/zmi/layout.py:406
msgid "Add portlet"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:69
+#: ./src/pyams_portal/zmi/layout.py:583
+msgid "Duplicate template..."
+msgstr ""
+
+#: ./src/pyams_portal/zmi/layout.py:603
+msgid "Duplicate template"
+msgstr ""
+
+#: ./src/pyams_portal/zmi/layout.py:73
msgid "Template management"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:103
+#: ./src/pyams_portal/zmi/layout.py:107
msgid "Template configuration"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:98
+#: ./src/pyams_portal/zmi/layout.py:593
+msgid "Cancel"
+msgstr ""
+
+#: ./src/pyams_portal/zmi/layout.py:594
+msgid "Duplicate this template"
+msgstr ""
+
+#: ./src/pyams_portal/zmi/layout.py:614
+msgid "New template name"
+msgstr ""
+
+#: ./src/pyams_portal/zmi/layout.py:102
msgid "Local template configuration"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:146
+#: ./src/pyams_portal/zmi/layout.py:150
msgid "{{ missing portlet }}"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:137
+#: ./src/pyams_portal/zmi/layout.py:141
#, python-format
msgid ""
"Add component: {0}<br />Drag and drop button to page template to position new"
" row"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:321
+#: ./src/pyams_portal/zmi/layout.py:325
#, python-format
msgid "Edit « {0} » slot properties"
msgstr ""
-#: ./src/pyams_portal/zmi/layout.py:101
+#: ./src/pyams_portal/zmi/layout.py:105
#, python-format
msgid "Shared template configuration ({0})"
msgstr ""
@@ -249,27 +270,27 @@
msgid "Large desktop device (> 1170px)"
msgstr ""
-#: ./src/pyams_portal/zmi/templates/layout.pt:114
+#: ./src/pyams_portal/zmi/templates/layout.pt:116
msgid "Override parent or template settings"
msgstr ""
-#: ./src/pyams_portal/zmi/templates/layout.pt:133
+#: ./src/pyams_portal/zmi/templates/layout.pt:135
msgid "Delete row..."
msgstr ""
-#: ./src/pyams_portal/zmi/templates/layout.pt:142
+#: ./src/pyams_portal/zmi/templates/layout.pt:144
msgid "Edit slot properties..."
msgstr ""
-#: ./src/pyams_portal/zmi/templates/layout.pt:149
+#: ./src/pyams_portal/zmi/templates/layout.pt:151
msgid "Delete slot..."
msgstr ""
-#: ./src/pyams_portal/zmi/templates/layout.pt:157
+#: ./src/pyams_portal/zmi/templates/layout.pt:159
msgid "Edit portlet properties..."
msgstr ""
-#: ./src/pyams_portal/zmi/templates/layout.pt:165
+#: ./src/pyams_portal/zmi/templates/layout.pt:167
msgid "Delete portlet..."
msgstr ""
@@ -319,160 +340,160 @@
msgid "Hidden portlet"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:65
+#: ./src/pyams_portal/interfaces/__init__.py:68
msgid "Portlet"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:68
-#: ./src/pyams_portal/interfaces/__init__.py:195
+#: ./src/pyams_portal/interfaces/__init__.py:71
+#: ./src/pyams_portal/interfaces/__init__.py:198
msgid "Slot name"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:69
+#: ./src/pyams_portal/interfaces/__init__.py:72
msgid "Slot name to which this configuration applies"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:82
+#: ./src/pyams_portal/interfaces/__init__.py:85
msgid "Portlet renderer"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:83
+#: ./src/pyams_portal/interfaces/__init__.py:86
msgid "Name of renderer used to render this portlet"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:113
+#: ./src/pyams_portal/interfaces/__init__.py:116
msgid "Inherit parent configuration?"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:114
+#: ./src/pyams_portal/interfaces/__init__.py:117
msgid ""
"This option is only available if context's parent is using the same "
"template..."
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:196
+#: ./src/pyams_portal/interfaces/__init__.py:199
msgid "This name must be unique in a given template"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:199
+#: ./src/pyams_portal/interfaces/__init__.py:202
msgid "Row ID"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:213
+#: ./src/pyams_portal/interfaces/__init__.py:216
msgid "Visible slot?"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:214
+#: ./src/pyams_portal/interfaces/__init__.py:217
msgid "Select 'no' to hide this slot..."
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:218
+#: ./src/pyams_portal/interfaces/__init__.py:221
msgid "Extra small device width"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:219
+#: ./src/pyams_portal/interfaces/__init__.py:222
msgid ""
"Slot width, in columns count, on extra small devices (phones...); set to 0 to"
" hide the portlet"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:225
+#: ./src/pyams_portal/interfaces/__init__.py:228
msgid "Small device width"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:226
+#: ./src/pyams_portal/interfaces/__init__.py:229
msgid ""
"Slot width, in columns count, on small devices (tablets...); set to 0 to hide"
" the portlet"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:232
+#: ./src/pyams_portal/interfaces/__init__.py:235
msgid "Medium devices width"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:233
+#: ./src/pyams_portal/interfaces/__init__.py:236
msgid ""
"Slot width, in columns count, on medium desktop devices (>= 992 pixels); set "
"to 0 to hide the portlet"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:239
+#: ./src/pyams_portal/interfaces/__init__.py:242
msgid "Large devices width"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:240
+#: ./src/pyams_portal/interfaces/__init__.py:243
msgid ""
"Slot width, in columns count, on large desktop devices (>= 1200 pixels); set "
"to 0 to hide the portlet"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:246
+#: ./src/pyams_portal/interfaces/__init__.py:249
msgid "CSS class"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:247
+#: ./src/pyams_portal/interfaces/__init__.py:250
msgid "CSS class applied to this slot"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:360
+#: ./src/pyams_portal/interfaces/__init__.py:363
msgid "Template name"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:361
+#: ./src/pyams_portal/interfaces/__init__.py:364
msgid "Two registered templates can't share the same name..."
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:382
+#: ./src/pyams_portal/interfaces/__init__.py:385
msgid "Toolbar portlets"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:383
+#: ./src/pyams_portal/interfaces/__init__.py:386
msgid ""
"These portlets will be directly available in templates configuration page "
"toolbar"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:412
+#: ./src/pyams_portal/interfaces/__init__.py:415
msgid "Inherit parent template?"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:413
+#: ./src/pyams_portal/interfaces/__init__.py:416
msgid "Should we reuse parent template?"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:417
+#: ./src/pyams_portal/interfaces/__init__.py:420
msgid "Override parent template?"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:418
+#: ./src/pyams_portal/interfaces/__init__.py:421
msgid "Should we override parent template?"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:422
+#: ./src/pyams_portal/interfaces/__init__.py:425
msgid "Use local template?"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:423
+#: ./src/pyams_portal/interfaces/__init__.py:426
msgid ""
"If 'yes', you can define a custom local template instead of a shared template"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:428
+#: ./src/pyams_portal/interfaces/__init__.py:431
msgid "Local template"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:433
+#: ./src/pyams_portal/interfaces/__init__.py:436
msgid "Use shared template?"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:434
+#: ./src/pyams_portal/interfaces/__init__.py:437
msgid "If 'yes', you can select a shared template"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:438
+#: ./src/pyams_portal/interfaces/__init__.py:441
msgid "Page template"
msgstr ""
-#: ./src/pyams_portal/interfaces/__init__.py:439
+#: ./src/pyams_portal/interfaces/__init__.py:442
msgid "Template used for this page"
msgstr ""
--- a/src/pyams_portal/zmi/layout.py Tue Jul 03 15:19:50 2018 +0200
+++ b/src/pyams_portal/zmi/layout.py Tue Jul 03 15:51:19 2018 +0200
@@ -9,6 +9,8 @@
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
+from pyams_utils.unicode import translate_string
+from pyams_utils.url import absolute_url
__docformat__ = 'restructuredtext'
@@ -23,7 +25,7 @@
IPortalTemplateContainerConfiguration, IPortalPortletsConfiguration, IPortalContext, IPortalPage, \
MANAGE_TEMPLATE_PERMISSION
from pyams_skin.interfaces import IInnerPage, IPageHeader
-from pyams_skin.interfaces.viewlet import IToolbarAddingMenu, IMenuHeader
+from pyams_skin.interfaces.viewlet import IToolbarAddingMenu, IMenuHeader, IContextActions
from pyams_skin.layer import IPyAMSLayer
from pyams_zmi.interfaces.menu import IPropertiesMenu, IContentManagementMenu
from pyams_zmi.layer import IAdminLayer
@@ -33,6 +35,7 @@
# import packages
from pyams_cache.beaker import get_cache
from pyams_form.form import AJAXAddForm, AJAXEditForm, ajax_config
+from pyams_form.schema import CloseButton
from pyams_pagelet.pagelet import pagelet_config
from pyams_portal.portlet import PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME
from pyams_portal.zmi.template import PortalTemplateHeaderAdapter
@@ -40,7 +43,7 @@
from pyams_skin.viewlet.toolbar import JsToolbarMenuItem, ToolbarMenuDivider, ToolbarMenuItem
from pyams_template.template import template_config
from pyams_utils.adapter import adapter_config
-from pyams_utils.registry import query_utility
+from pyams_utils.registry import query_utility, get_utility
from pyams_utils.traversing import get_parent
from pyams_viewlet.manager import viewletmanager_config
from pyams_viewlet.viewlet import viewlet_config
@@ -50,7 +53,8 @@
from pyramid.events import subscriber
from pyramid.exceptions import NotFound
from pyramid.view import view_config
-from z3c.form import field
+from z3c.form import field, button
+from zope.copy import copy
from zope.interface import implementer, Invalid, Interface
from pyams_portal import _
@@ -547,3 +551,94 @@
config = IPortalTemplateConfiguration(request.context)
config.delete_portlet(int(request.params.get('portlet_id')))
return {'status': 'success'}
+
+
+#
+# Portal template duplication form
+#
+
+@viewlet_config(name='duplication.divider', context=IPortalTemplate, layer=IPyAMSLayer,
+ view=PortalTemplateLayoutView, manager=IContextActions, permission=MANAGE_TEMPLATE_PERMISSION, weight=99)
+class PortalTemplateDuplicationMenuDivider(ToolbarMenuDivider):
+ """Portal template duplication menu divider"""
+
+ def __new__(cls, context, request, view, manager):
+ container = get_parent(context, IPortalTemplateContainer)
+ if container is None:
+ return None
+ return ToolbarMenuDivider.__new__(cls)
+
+
+@viewlet_config(name='duplication.menu', context=IPortalTemplate, layer=IPyAMSLayer,
+ view=PortalTemplateLayoutView, manager=IContextActions, permission=MANAGE_TEMPLATE_PERMISSION, weight=100)
+class PortalTemplateDuplicationMenu(ToolbarMenuItem):
+ """Portal template duplication menu item"""
+
+ def __new__(cls, context, request, view, manager):
+ container = get_parent(context, IPortalTemplateContainer)
+ if container is None:
+ return None
+ return ToolbarMenuDivider.__new__(cls)
+
+ label = _("Duplicate template...")
+ label_css_class = 'fa fa-fw fa-files-o'
+
+ url = 'duplicate.html'
+ modal_target = True
+
+
+class IPortalTemplateDuplicationButtons(Interface):
+ """Portal template duplication form buttons"""
+
+ close = CloseButton(name='close', title=_("Cancel"))
+ duplicate = button.Button(name='duplicate', title=_("Duplicate this template"))
+
+
+@pagelet_config(name='duplicate.html', context=IPortalTemplate, layer=IPyAMSLayer,
+ permission=MANAGE_TEMPLATE_PERMISSION)
+@ajax_config(name='duplicate.json', context=IPortalTemplate, layer=IPyAMSLayer, base=AJAXAddForm)
+class PortalTemplateDuplicationForm(AdminDialogAddForm):
+ """Portal template duplicate form"""
+
+ legend = _("Duplicate template")
+ icon_css_class = 'fa fa-fw fa-files-o'
+
+ fields = field.Fields(IPortalTemplate)
+ buttons = button.Buttons(IPortalTemplateDuplicationButtons)
+
+ edit_permission = MANAGE_TEMPLATE_PERMISSION
+
+ def updateWidgets(self, prefix=None):
+ super(PortalTemplateDuplicationForm, self).updateWidgets(prefix)
+ if 'name' in self.widgets:
+ self.widgets['name'].label = _("New template name")
+
+ def updateActions(self):
+ super(PortalTemplateDuplicationForm, self).updateActions()
+ if 'duplicate' in self.actions:
+ self.actions['duplicate'].addClass('btn-primary')
+
+ def create(self, data):
+ return copy(self.context)
+
+ def add(self, template):
+ container = get_utility(IPortalTemplateContainer)
+ container[translate_string(template.name, spaces='-')] = template
+
+ def nextURL(self):
+ return absolute_url(self.request.root, self.request, 'admin#portal-templates.html')
+
+ def get_ajax_output(self, changes):
+ return {
+ 'status': 'redirect',
+ 'location': self.nextURL()
+ }
+
+
+@subscriber(IDataExtractedEvent, form_selector=PortalTemplateDuplicationForm)
+def handle_new_template_data_extraction(event):
+ """Handle new template form data extraction"""
+ container = get_utility(IPortalTemplateContainer)
+ name = translate_string(event.data.get('name'), spaces='-')
+ if name in container:
+ event.form.widgets.errors += (Invalid(_("Specified name is already used!")),)
--- a/src/pyams_portal/zmi/template.py Tue Jul 03 15:19:50 2018 +0200
+++ b/src/pyams_portal/zmi/template.py Tue Jul 03 15:51:19 2018 +0200
@@ -136,8 +136,7 @@
@pagelet_config(name='add-portal-template.html', context=ISite, layer=IPyAMSLayer,
permission=MANAGE_TEMPLATE_PERMISSION)
-@ajax_config(name='add-portal-template.json', context=ISite, layer=IPyAMSLayer,
- permission=MANAGE_TEMPLATE_PERMISSION, base=AJAXAddForm)
+@ajax_config(name='add-portal-template.json', context=ISite, layer=IPyAMSLayer, base=AJAXAddForm)
class PortalTemplateAddForm(AdminDialogAddForm):
"""Portal template add form"""
@@ -146,8 +145,7 @@
icon_css_class = 'fa fa-fw fa-columns'
fields = field.Fields(IPortalTemplate)
- ajax_handler = 'add-portal-template.json'
- edit_permission = None
+ edit_permission = MANAGE_TEMPLATE_PERMISSION
def create(self, data):
return PortalTemplate()