Suppression des images d'une sélection avec ajax.
authorBenoît Pin <benoit.pin@gmail.com>
Fri, 29 Aug 2014 08:51:46 +0000 (10:51 +0200)
committerBenoît Pin <benoit.pin@gmail.com>
Fri, 29 Aug 2014 08:51:46 +0000 (10:51 +0200)
locales/en/LC_MESSAGES/portfolio.po
locales/fr/LC_MESSAGES/portfolio.mo
locales/fr/LC_MESSAGES/portfolio.po
locales/portfolio.pot
skins/getSelectionPhotosInfos.py
skins/selection_view.py
skins/selection_view_template.pt

index c36a5b2..31709aa 100644 (file)
@@ -48,8 +48,8 @@ msgstr ""
 msgid "This %s is already in the selection."
 msgstr ""
 
-#: o/skins/get_slide_buyable_items.pt:21 o/skins/photo_layout_macros.pt:52
-#: o/skins/photo_layout_macros.pt:55 o/skins/photo_view.pt:91
+#: o/skins/get_slide_buyable_items.pt:21 o/skins/photo_layout_macros.pt:51
+#: o/skins/photo_layout_macros.pt:54 o/skins/photo_view.pt:91
 #: o/skins/photo_view.pt:94
 msgid "Add to cart"
 msgstr ""
@@ -123,7 +123,8 @@ msgstr ""
 msgid "refresh amount"
 msgstr ""
 
-#: o/skins/my_cart_template.pt:59 o/skins/portfolio_view.pt:81
+#: o/skins/my_cart_template.pt:59 o/skins/portfolio_view.pt:88
+#: o/skins/selection_view_template.pt:31
 msgid "delete"
 msgstr ""
 
@@ -175,24 +176,24 @@ msgstr ""
 msgid "Dimensions"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:33 o/skins/photo_layout_macros.pt:36
+#: o/skins/photo_layout_macros.pt:32 o/skins/photo_layout_macros.pt:35
 msgid "Add to selection"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:42 o/skins/photo_layout_macros.pt:45
+#: o/skins/photo_layout_macros.pt:41 o/skins/photo_layout_macros.pt:44
 msgid "Remove to selection"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:61 o/skins/photo_layout_macros.pt:64
+#: o/skins/photo_layout_macros.pt:60 o/skins/photo_layout_macros.pt:63
 #: o/skins/portfolio_presentation_template.pt:47
 msgid "Delete"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:79 o/skins/photo_layout_macros.pt:82
+#: o/skins/photo_layout_macros.pt:78 o/skins/photo_layout_macros.pt:81
 msgid "Hide for anonymous"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:92 o/skins/photo_layout_macros.pt:95
+#: o/skins/photo_layout_macros.pt:91 o/skins/photo_layout_macros.pt:94
 msgid "Show for anonymous"
 msgstr ""
 
@@ -272,15 +273,15 @@ msgstr ""
 msgid "sorting:"
 msgstr ""
 
-#: o/skins/portfolio_view.pt:76
+#: o/skins/portfolio_view.pt:77
 msgid "manual"
 msgstr ""
 
-#: o/skins/portfolio_view.pt:77
+#: o/skins/portfolio_view.pt:79
 msgid "shooting"
 msgstr ""
 
-#: o/skins/portfolio_view.pt:78
+#: o/skins/portfolio_view.pt:81
 msgid "modification"
 msgstr ""
 
@@ -292,9 +293,21 @@ msgstr ""
 msgid "Description"
 msgstr ""
 
-#: o/skins/selection_view.py:64 o/skins/selection_view.py:66
-#: o/skins/selection_view_template.pt:18 o/skins/selectioncontext.py:115
-#: o/skins/selectioncontext.py:117
+#: o/skins/selection_view.py:56
+msgid "Photo deselected."
+msgstr ""
+
+#: o/skins/selection_view.py:58
+msgid "Deselected photos."
+msgstr ""
+
+#: o/skins/selection_view.py:60
+msgid "Nothing to deselect."
+msgstr ""
+
+#: o/skins/selection_view.py:70 o/skins/selection_view.py:72
+#: o/skins/selection_view_template.pt:18 o/skins/selectioncontext.py:116
+#: o/skins/selectioncontext.py:118
 msgid "My selection"
 msgstr ""
 
@@ -302,20 +315,20 @@ msgstr ""
 msgid "You are editing this ligthbox:"
 msgstr ""
 
-#: o/skins/selection_view_template.pt:30
+#: o/skins/selection_view_template.pt:42
 msgid "Save as..."
 msgstr ""
 
-#: o/skins/selection_view_template.pt:33
+#: o/skins/selection_view_template.pt:45
 msgid "${please_login} if you want to save this selection."
 msgstr ""
 
 #. Default: "Please log in"
-#: o/skins/selection_view_template.pt:34
+#: o/skins/selection_view_template.pt:46
 msgid "login_to_save_seletion"
 msgstr ""
 
-#: o/skins/selection_view_template.pt:38
+#: o/skins/selection_view_template.pt:50
 msgid "Empty selection."
 msgstr ""
 
index 7af8c86..7097597 100644 (file)
Binary files a/locales/fr/LC_MESSAGES/portfolio.mo and b/locales/fr/LC_MESSAGES/portfolio.mo differ
index 210399f..dc2a367 100644 (file)
@@ -1,8 +1,8 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: Plinn 2.0\n"
-"POT-Creation-Date: Tue Jul  8 18:30:13 2014\n"
-"PO-Revision-Date: 2014-07-08 18:31+0200\n"
+"POT-Creation-Date: Fri Aug 29 10:44:06 2014\n"
+"PO-Revision-Date: 2014-08-29 10:45+0200\n"
 "Last-Translator:  Benoît PIN\n"
 "Language-Team: CRI http://cri.ensmp.fr\n"
 "Language: \n"
@@ -71,8 +71,8 @@ msgid "This %s is already in the selection."
 msgstr "Cette %s est déjà dans la sélection."
 
 # from portfolio-manual
-#: o/skins/get_slide_buyable_items.pt:21 o/skins/photo_layout_macros.pt:52
-#: o/skins/photo_layout_macros.pt:55 o/skins/photo_view.pt:91
+#: o/skins/get_slide_buyable_items.pt:21 o/skins/photo_layout_macros.pt:51
+#: o/skins/photo_layout_macros.pt:54 o/skins/photo_view.pt:91
 #: o/skins/photo_view.pt:94
 msgid "Add to cart"
 msgstr "Ajouter au panier"
@@ -148,7 +148,8 @@ msgstr "Prix (TTC)"
 msgid "refresh amount"
 msgstr "actualiser le montant"
 
-#: o/skins/my_cart_template.pt:59 o/skins/portfolio_view.pt:81
+#: o/skins/my_cart_template.pt:59 o/skins/portfolio_view.pt:88
+#: o/skins/selection_view_template.pt:31
 msgid "delete"
 msgstr "supprimer"
 
@@ -201,25 +202,25 @@ msgid "Dimensions"
 msgstr "Dimensions"
 
 # from portfolio-manual
-#: o/skins/photo_layout_macros.pt:33 o/skins/photo_layout_macros.pt:36
+#: o/skins/photo_layout_macros.pt:32 o/skins/photo_layout_macros.pt:35
 msgid "Add to selection"
 msgstr "Ajouter à la sélection"
 
 # from portfolio-manual
-#: o/skins/photo_layout_macros.pt:42 o/skins/photo_layout_macros.pt:45
+#: o/skins/photo_layout_macros.pt:41 o/skins/photo_layout_macros.pt:44
 msgid "Remove to selection"
 msgstr "Retirer de la sélection"
 
-#: o/skins/photo_layout_macros.pt:61 o/skins/photo_layout_macros.pt:64
+#: o/skins/photo_layout_macros.pt:60 o/skins/photo_layout_macros.pt:63
 #: o/skins/portfolio_presentation_template.pt:47
 msgid "Delete"
 msgstr "Supprimer"
 
-#: o/skins/photo_layout_macros.pt:79 o/skins/photo_layout_macros.pt:82
+#: o/skins/photo_layout_macros.pt:78 o/skins/photo_layout_macros.pt:81
 msgid "Hide for anonymous"
 msgstr "Masquer pour les anonymes"
 
-#: o/skins/photo_layout_macros.pt:92 o/skins/photo_layout_macros.pt:95
+#: o/skins/photo_layout_macros.pt:91 o/skins/photo_layout_macros.pt:94
 msgid "Show for anonymous"
 msgstr "Montrer aux anonymes"
 
@@ -299,15 +300,15 @@ msgstr "Supprimer la présentation"
 msgid "sorting:"
 msgstr "tri :"
 
-#: o/skins/portfolio_view.pt:76
+#: o/skins/portfolio_view.pt:77
 msgid "manual"
 msgstr "manuel"
 
-#: o/skins/portfolio_view.pt:77
+#: o/skins/portfolio_view.pt:79
 msgid "shooting"
 msgstr "prise de vue"
 
-#: o/skins/portfolio_view.pt:78
+#: o/skins/portfolio_view.pt:81
 msgid "modification"
 msgstr "modification"
 
@@ -319,9 +320,21 @@ msgstr "Enregistrer la sélection dans une table lumineuse"
 msgid "Description"
 msgstr "Description"
 
-#: o/skins/selection_view.py:64 o/skins/selection_view.py:66
-#: o/skins/selection_view_template.pt:18 o/skins/selectioncontext.py:115
-#: o/skins/selectioncontext.py:117
+#: o/skins/selection_view.py:56
+msgid "Photo deselected."
+msgstr "Photo désélectionnée."
+
+#: o/skins/selection_view.py:58
+msgid "Deselected photos."
+msgstr "Photos désélectionnées."
+
+#: o/skins/selection_view.py:60
+msgid "Nothing to deselect."
+msgstr "Rien à désélectionner."
+
+#: o/skins/selection_view.py:70 o/skins/selection_view.py:72
+#: o/skins/selection_view_template.pt:18 o/skins/selectioncontext.py:116
+#: o/skins/selectioncontext.py:118
 msgid "My selection"
 msgstr "Ma sélection"
 
@@ -329,20 +342,20 @@ msgstr "Ma sélection"
 msgid "You are editing this ligthbox:"
 msgstr "Vous éditez cette table lumineuse :"
 
-#: o/skins/selection_view_template.pt:30
+#: o/skins/selection_view_template.pt:42
 msgid "Save as..."
 msgstr "Enregistrer sous..."
 
-#: o/skins/selection_view_template.pt:33
+#: o/skins/selection_view_template.pt:45
 msgid "${please_login} if you want to save this selection."
 msgstr "Si vous souhaiter enregistrer cette sélection, ${please_login}"
 
 #. Default: "Please log in"
-#: o/skins/selection_view_template.pt:34
+#: o/skins/selection_view_template.pt:46
 msgid "login_to_save_seletion"
 msgstr "veuillez vous connecter."
 
-#: o/skins/selection_view_template.pt:38
+#: o/skins/selection_view_template.pt:50
 msgid "Empty selection."
 msgstr "Sélection vide."
 
index f89ad7e..6d8a06a 100644 (file)
@@ -14,7 +14,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: 3.0\n"
-"POT-Creation-Date: Tue Jul  8 18:30:13 2014\n"
+"POT-Creation-Date: Fri Aug 29 10:44:06 2014\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: Zope 3 Developers <zope-dev@zope.org>\n"
@@ -79,8 +79,8 @@ msgid "This %s is already in the selection."
 msgstr ""
 
 #: o/skins/get_slide_buyable_items.pt:21
-#: o/skins/photo_layout_macros.pt:52
-#: o/skins/photo_layout_macros.pt:55
+#: o/skins/photo_layout_macros.pt:51
+#: o/skins/photo_layout_macros.pt:54
 #: o/skins/photo_view.pt:91
 #: o/skins/photo_view.pt:94
 msgid "Add to cart"
@@ -160,8 +160,10 @@ msgstr ""
 
 #: o/skins/my_cart_template.pt:59
 #: o/skins/my_cart_template.pt:59
-#: o/skins/portfolio_view.pt:81
-#: o/skins/portfolio_view.pt:81
+#: o/skins/portfolio_view.pt:88
+#: o/skins/portfolio_view.pt:88
+#: o/skins/selection_view_template.pt:31
+#: o/skins/selection_view_template.pt:31
 msgid "delete"
 msgstr ""
 
@@ -215,29 +217,29 @@ msgstr ""
 msgid "Dimensions"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:33
-#: o/skins/photo_layout_macros.pt:36
+#: o/skins/photo_layout_macros.pt:32
+#: o/skins/photo_layout_macros.pt:35
 msgid "Add to selection"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:42
-#: o/skins/photo_layout_macros.pt:45
+#: o/skins/photo_layout_macros.pt:41
+#: o/skins/photo_layout_macros.pt:44
 msgid "Remove to selection"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:61
-#: o/skins/photo_layout_macros.pt:64
+#: o/skins/photo_layout_macros.pt:60
+#: o/skins/photo_layout_macros.pt:63
 #: o/skins/portfolio_presentation_template.pt:47
 msgid "Delete"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:79
-#: o/skins/photo_layout_macros.pt:82
+#: o/skins/photo_layout_macros.pt:78
+#: o/skins/photo_layout_macros.pt:81
 msgid "Hide for anonymous"
 msgstr ""
 
-#: o/skins/photo_layout_macros.pt:92
-#: o/skins/photo_layout_macros.pt:95
+#: o/skins/photo_layout_macros.pt:91
+#: o/skins/photo_layout_macros.pt:94
 msgid "Show for anonymous"
 msgstr ""
 
@@ -324,15 +326,15 @@ msgstr ""
 msgid "sorting:"
 msgstr ""
 
-#: o/skins/portfolio_view.pt:76
+#: o/skins/portfolio_view.pt:77
 msgid "manual"
 msgstr ""
 
-#: o/skins/portfolio_view.pt:77
+#: o/skins/portfolio_view.pt:79
 msgid "shooting"
 msgstr ""
 
-#: o/skins/portfolio_view.pt:78
+#: o/skins/portfolio_view.pt:81
 msgid "modification"
 msgstr ""
 
@@ -344,11 +346,23 @@ msgstr ""
 msgid "Description"
 msgstr ""
 
-#: o/skins/selection_view.py:64
-#: o/skins/selection_view.py:66
+#: o/skins/selection_view.py:56
+msgid "Photo deselected."
+msgstr ""
+
+#: o/skins/selection_view.py:58
+msgid "Deselected photos."
+msgstr ""
+
+#: o/skins/selection_view.py:60
+msgid "Nothing to deselect."
+msgstr ""
+
+#: o/skins/selection_view.py:70
+#: o/skins/selection_view.py:72
 #: o/skins/selection_view_template.pt:18
-#: o/skins/selectioncontext.py:115
-#: o/skins/selectioncontext.py:117
+#: o/skins/selectioncontext.py:116
+#: o/skins/selectioncontext.py:118
 msgid "My selection"
 msgstr ""
 
@@ -356,20 +370,20 @@ msgstr ""
 msgid "You are editing this ligthbox:"
 msgstr ""
 
-#: o/skins/selection_view_template.pt:30
+#: o/skins/selection_view_template.pt:42
 msgid "Save as..."
 msgstr ""
 
-#: o/skins/selection_view_template.pt:33
+#: o/skins/selection_view_template.pt:45
 msgid "${please_login} if you want to save this selection."
 msgstr ""
 
-#: o/skins/selection_view_template.pt:34
+#: o/skins/selection_view_template.pt:46
 #. Default: "Please log in"
 msgid "login_to_save_seletion"
 msgstr ""
 
-#: o/skins/selection_view_template.pt:38
+#: o/skins/selection_view_template.pt:50
 msgid "Empty selection."
 msgstr ""
 
index 362f76d..20e6d61 100644 (file)
@@ -15,15 +15,15 @@ toUrl = req.physicalPathToURL
 lightboxpath = req.SESSION.get('lightboxpath', None)
 selectionIsLightbox = False
 if lightboxpath is None :
-       selection = req.SESSION.get('objects_selection', [])
+    selection = req.SESSION.get('objects_selection', [])
 else :
-       try :
-               lightbox = portal.restrictedTraverse(lightboxpath)
-               selection = lightbox.getUidList()
-               selectionIsLightbox = True
-       except:
-               req.SESSION.set('lightboxpath', None)
-               selection = req.SESSION.get('objects_selection', [])
+    try :
+        lightbox = portal.restrictedTraverse(lightboxpath)
+        selection = lightbox.getUidList()
+        selectionIsLightbox = True
+    except:
+        req.SESSION.set('lightboxpath', None)
+        selection = req.SESSION.get('objects_selection', [])
 
 
 brains = [uidh.getBrain(uid) for uid in selection]
@@ -34,29 +34,29 @@ cart = req.SESSION.get('cart', None)
 
 infos = []
 for index, b in enumerate(batch) :
-       path = b.getPath().split('/')
-       path.insert(portalDepth, 'selectioncontext')
-       p = b.getObject()
-       if pptool :
-               buyable = bool(pptool.getPrintingOptionsFor(p))
-               if cart and cart.locked :
-                       buyable = False
-       else :
-               buyable = False
-       
-       d = {'href': toUrl('/'.join(path))
-               ,'thumbUrl' : '%s/getThumbnail' % b.getURL()
-               ,'thumbSize' : b.getThumbnailSize
-               ,'title' : ('%s - %s' % (b.Title, b.Description)).strip(' -')
-               ,'cmf_uid':b.cmf_uid
-               ,'className':''
-               ,'buyable' : buyable
-               ,'o':b
-               }
-       infos.append(d)
+    path = b.getPath().split('/')
+    path.insert(portalDepth, 'selectioncontext')
+    p = b.getObject()
+    if pptool :
+        buyable = bool(pptool.getPrintingOptionsFor(p))
+        if cart and cart.locked :
+            buyable = False
+    else :
+        buyable = False
+    
+    d = {'href': toUrl('/'.join(path))
+        ,'thumbUrl' : '%s/getThumbnail' % b.getURL()
+        ,'thumbSize' : b.getThumbnailSize
+        ,'title' : ('%s - %s' % (b.Title, b.Description)).strip(' -')
+        ,'cmf_uid':b.cmf_uid
+        ,'className':''
+        ,'buyable' : buyable
+        ,'o':b
+        }
+    infos.append(d)
 
 features = {}
-features['del'] = lambda b : '%s/remove_to_selection' % b.getURL()
+features['checkbox'] = True
 features['cart'] = lambda b : '%s/get_slide_buyable_items' % b.getURL()
 
 return {'infos' : infos,
index 0a419a7..c30d397 100755 (executable)
@@ -1,38 +1,85 @@
 ##parameters=
-from Products.CMFCore.utils import getToolByName
+from Products.CMFCore.utils import getUtilityByInterfaceName
 from Products.Portfolio.utils import translate
 def _(message) : return translate(message, context).encode('utf-8')
 
 req = context.REQUEST
-utool = getToolByName(context, 'portal_url')
+utool = getUtilityByInterfaceName('Products.CMFCore.interfaces.IURLTool')
 portal = utool.getPortalObject()
 portal_url = utool()
 
+form = req.form
+fg = form.get
+sd = context.session_data_manager.getSessionData(create = 1)
+
 # check if a lightbox is currently selected
-lightboxpath = req.SESSION.get('lightboxpath', None)
+lightboxpath = sd.get('lightboxpath', None)
 selectionIsLightbox = False
 if lightboxpath is not None :
-       try :
-               lightbox = portal.restrictedTraverse(lightboxpath)
-               selectionIsLightbox = True
-       except:
-               req.SESSION.set('lightboxpath', None)
+    try :
+        lightbox = portal.restrictedTraverse(lightboxpath)
+        selectionIsLightbox = True
+    except:
+        sd['lightboxpath'] = None
+
+# form processing
+if fg('delete.x') or form.has_key('delete') :
+    selection = sd.get('objects_selection', [])
+    selDict = sd.get('objects_selection_dict', {})
+
+    # get selection from session data or from selected lightbox
+    if not selectionIsLightbox :
+       selection = sd.get('objects_selection', [])
+    else :
+       try :
+               lightbox = portal.restrictedTraverse(lightboxpath)
+               selection = lightbox.getUidList()
+       except KeyError :
+               sd['lightboxpath'] = None
+               selection = sd.get('objects_selection', [])
+        
+    # remove items from selection
+    rmCpt = 0
+    for uid in [int(uid) for uid in fg('uids', [])] :
+        if selDict.has_key(uid) :
+            del selDict[uid]
+            selection.remove(uid)
+            if selectionIsLightbox :
+                lightbox.remove(uid)
+            sd['objects_selection'] = selection
+            sd['objects_selection_dict'] = selDict
+            rmCpt = rmCpt + 1
+        
+    # ui feedback message
+    if rmCpt :
+        if rmCpt == 1 :
+            msg = _('Photo deselected.')
+        else :
+            msg = _('Deselected photos.')
+    else :
+        msg = _('Nothing to deselect.')
+    
+    if fg('ajax') :
+        req.RESPONSE.setHeader('Content-Type', 'text/xml;;charset=utf-8')
+        return '<deleted>%s</deleted>' % msg
+    else :
+        context.setStatus(True, msg)
 
 # breadcrumbs customization
 if selectionIsLightbox :
-       lastBcTitle = '%s (%s)' % (_('My selection'), lightbox.title_or_id())
+    lastBcTitle = '%s (%s)' % (_('My selection'), lightbox.title_or_id())
 else :
-       lastBcTitle = _('My selection')
+    lastBcTitle = _('My selection')
 
 breadcrumbs = [
-       { 'id'          : 'root'
-       , 'title'       : portal.title
-       , 'url'    : portal_url},
-       
-       {'id'           : 'selection_view'
-        ,'title'       : lastBcTitle
-        , 'url'        : '%s/selection_view' % portal_url}
-       ]
+    { 'id'      : 'root'
+    , 'title'   : portal.title
+    , 'url'    : portal_url},
+    
+    {'id'       : 'selection_view'
+     ,'title'   : lastBcTitle
+     , 'url'    : '%s/selection_view' % portal_url}
+    ]
 
 
 options = {}
@@ -42,8 +89,8 @@ options['selectionIsLightbox'] = selectionIsLightbox
 options['breadcrumbs'] = breadcrumbs
 
 if selectionIsLightbox :
-       options['lightbox'] = lightbox
+    options['lightbox'] = lightbox
 else :
-       options['selectionName'] = 'not saved yet'
+    options['selectionName'] = 'not saved yet'
 
 return context.selection_view_template(**options)
index 6684241..82cabe8 100644 (file)
          tal:omit-tag=""
          i18n:domain="portfolio">
       <h1 i18n:translate="">My selection</h1>
-                       <em tal:condition="python: not options['selectionIsLightbox'] and len(batch)">
-                               (<span tal:content="options/selectionName" tal:omit-tag="" i18n:translate="">selection name</span>)
-                       </em>
-                       <div tal:condition="options/selectionIsLightbox">
-                               <em i18n:translate="">You are editing this ligthbox:</em>
-                               <a tal:attributes="href options/lightbox/absolute_url"
-                                tal:content="options/lightbox/title_or_id">lightbox url</a>
-                       </div>
-      <div metal:use-macro="here/photo_layout_macros/macros/grid"></div>
+      <em tal:condition="python: not options['selectionIsLightbox'] and len(batch)">
+        (<span tal:content="options/selectionName" tal:omit-tag="" i18n:translate="">selection name</span>)
+      </em>
+      <div tal:condition="options/selectionIsLightbox">
+        <em i18n:translate="">You are editing this ligthbox:</em>
+        <a tal:attributes="href options/lightbox/absolute_url"
+           tal:content="options/lightbox/title_or_id">lightbox url</a>
+      </div>
+      <form tal:attributes="action string:$portal_url/selection_view" method="post">
+        <div id="lightbox_toolbar" class="image_toolbar"
+             tal:define="ModifyPortalContent modules/Products/CMFCore/permissions/ModifyPortalContent"
+             tal:condition="python:mtool.checkPermission(ModifyPortalContent, here)">
+          <input type="image" width="17" height="27" alt="delete" title="delete"
+                 name="delete"
+                 tal:attributes="src string:$portal_url/trash_btn.gif"
+                 i18n:attributes="alt;title"/>
+          <br/>
+        </div>
+        <div metal:use-macro="here/photo_layout_macros/macros/grid"></div>
+      </form>
       <br clear="all"/>
-                       <form tal:attributes="action string:$portal_url/save_as_lightbox_form"
-                                               tal:condition="python:not isAnon and not options['selectionIsLightbox'] and len(batch)">
-                               <input type="submit" value="Save as..." name="saveas" i18n:attributes="value"/>
-                       </form>
-                       <div tal:condition="python:isAnon and len(batch)" i18n:translate="">
-                         <span i18n:name="please_login">
-                         <a tal:define="mq python:modules['ZTUtils'].make_query"
-                            tal:attributes="href python:'%s/login_form?%s' % (portal_url, mq(came_from='%s/save_as_lightbox_form' % portal_url))"
-                            i18n:translate="login_to_save_seletion">Please log in</a></span> if you want to save this selection.
-                       </div>
+      <form tal:attributes="action string:$portal_url/save_as_lightbox_form"
+            tal:condition="python:not isAnon and not options['selectionIsLightbox'] and len(batch)">
+        <input type="submit" value="Save as..." name="saveas" i18n:attributes="value"/>
+      </form>
+      <div tal:condition="python:isAnon and len(batch)" i18n:translate="">
+        <span i18n:name="please_login">
+        <a tal:define="mq python:modules['ZTUtils'].make_query"
+           tal:attributes="href python:'%s/login_form?%s' % (portal_url, mq(came_from='%s/save_as_lightbox_form' % portal_url))"
+           i18n:translate="login_to_save_seletion">Please log in</a></span> if you want to save this selection.
+      </div>
       <div tal:condition="python:not len(batch)" i18n:translate="">Empty selection.</div>
     </div>
   </body>