Le thème créé pour realis est reconverti en thème « photo » pour Plinn core.
authorBenoît Pin <benoit.pin@gmail.com>
Sun, 14 Nov 2010 21:28:02 +0000 (22:28 +0100)
committerBenoît Pin <benoit.pin@gmail.com>
Sun, 14 Nov 2010 21:28:02 +0000 (22:28 +0100)
36 files changed:
directories.zcml
profiles/photo/skins.xml
skins/photo_theme/base_properties.props [new file with mode: 0755]
skins/photo_theme/collapsePalette.gif [new file with mode: 0644]
skins/photo_theme/collapsedPalette.gif [new file with mode: 0644]
skins/photo_theme/createMemberContent.py [new file with mode: 0755]
skins/photo_theme/customer_join_form.py [new file with mode: 0755]
skins/photo_theme/customer_join_template.pt [new file with mode: 0644]
skins/photo_theme/doFormSearch.py [new file with mode: 0755]
skins/photo_theme/expandPalette.gif [new file with mode: 0644]
skins/photo_theme/expandedPalette.gif [new file with mode: 0644]
skins/photo_theme/folder_contents.py [new file with mode: 0755]
skins/photo_theme/folder_contents_macros.pt [new file with mode: 0644]
skins/photo_theme/global_plinn_style.css.dtml [new file with mode: 0755]
skins/photo_theme/global_plinn_style.css.dtml.metadata [new file with mode: 0644]
skins/photo_theme/homepage_dispatcher.py [new file with mode: 0755]
skins/photo_theme/imagerotator.swf [new file with mode: 0644]
skins/photo_theme/info.gif [new file with mode: 0644]
skins/photo_theme/loading_progress.gif [new file with mode: 0755]
skins/photo_theme/logo.gif [new file with mode: 0755]
skins/photo_theme/logout.py [new file with mode: 0755]
skins/photo_theme/main_template_macros.pt [new file with mode: 0644]
skins/photo_theme/main_template_standard.pt [new file with mode: 0755]
skins/photo_theme/member_albums.py [new file with mode: 0755]
skins/photo_theme/member_albums_template.pt [new file with mode: 0644]
skins/photo_theme/mi.gif [new file with mode: 0644]
skins/photo_theme/mi_ani.gif [new file with mode: 0644]
skins/photo_theme/pl.gif [new file with mode: 0644]
skins/photo_theme/pl_ani.gif [new file with mode: 0644]
skins/photo_theme/portfolio_properties.props [new file with mode: 0644]
skins/photo_theme/realis_main_macros.pt [new file with mode: 0644]
skins/photo_theme/realis_style.css.dtml [new file with mode: 0644]
skins/photo_theme/search.pt [new file with mode: 0644]
skins/photo_theme/search_results_macros.pt [new file with mode: 0644]
skins/photo_theme/tabs.pt [new file with mode: 0644]
skins/photo_theme/validatePrivateAccess.py [new file with mode: 0755]

index 714ce40..1c12729 100644 (file)
@@ -1,6 +1,7 @@
 <configure
     xmlns="http://namespaces.zope.org/zope"
     xmlns:cmf="http://namespaces.zope.org/cmf">
+  <cmf:registerDirectory name="photo_theme" recursive="True"/>
   <cmf:registerDirectory name="content" recursive="True"/>
   <cmf:registerDirectory name="control" recursive="True"/>
   <cmf:registerDirectory name="generic" recursive="True"/>
index 1ca266e..4ab03bc 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <object name="portal_skins" meta_type="CMF Skins Tool" allow_any="False"
-   cookie_persistence="False" default_skin="Realis"
+   cookie_persistence="False" default_skin="Plinn photo"
    request_varname="portal_skin">
  <object name="Images" meta_type="Filesystem Directory View"
     directory="Products.CMFDefault:skins/Images"/>
@@ -45,6 +45,8 @@
     directory="Products.Plinn:skins/generic"/>
  <object name="plinn_images" meta_type="Filesystem Directory View"
     directory="Products.Plinn:skins/images"/>
+ <object name="plinn_photo_theme" meta_type="Filesystem Directory View"
+    directory="Products.Plinn:skins/photo_theme"/>
  <object name="portfolio" meta_type="Filesystem Directory View"
     directory="Products.Portfolio:skins"/>
  <object name="realis" meta_type="Filesystem Directory View"
@@ -59,9 +61,9 @@
     directory="Products.CMFDefault:skins/zpt_generic"/>
  <object name="zpt_topic" meta_type="Filesystem Directory View"
     directory="Products.CMFTopic:skins/zpt_topic"/>
- <skin-path name="Realis">
+ <skin-path name="Plinn photo">
   <layer name="custom"/>
-  <layer name="realis"/>
+  <layer name="plinn_photo_theme"/>
   <layer name="photoprint"/>
   <layer name="plinn_content"/>
   <layer name="plinn_control"/>
diff --git a/skins/photo_theme/base_properties.props b/skins/photo_theme/base_properties.props
new file mode 100755 (executable)
index 0000000..a32b6ea
--- /dev/null
@@ -0,0 +1,65 @@
+title:string=Color, font, logo and border defaults
+
+backgroundColor:string=#484848
+fontColor:string=#9da097
+fontFamily:string=Arial, Helvetica, Geneva, Swiss, SunSans-Regular, sans-serif
+fontBaseSize:string=90%
+headingFontFamily:string=Arial, Helvetica, Geneva, Swiss, SunSans-Regular, sans-serif
+
+linkColor:string=#e6eadd
+linkHoverColor:string=#f28c18
+
+fontSmallSize:string=90%
+
+
+topbarBackgroundColor:string=#000
+breadcrumbsBackground:string=#484848
+
+tabsBorderColor:string=#202020
+tabsBorderWidth:string=2px
+tabsBottomBorderSelectedWidth:string=3px
+tabsFontColor:string=#e6eadd
+tabsBackgroundColor:string=#484848
+selectedTabBackgroundColor:string=#484848
+
+descriptionColor:string=#9da097
+
+inputFontColor:string=#000
+
+evenRowBackgroundColor:string=#202020
+oddRowBackgroundColor:string=#484848
+highLightColor:string=#f28c18
+
+messageBackgroundColor:string=#484848
+messageBorderColor:string=#484848
+
+weekTableFontHeight:int=10
+weekTableGridStep:int=10
+todayBackgroundColor:string=#f0f0f0
+calGridBorderColor:string=#ccc
+calHalfGridBorderColor:string=#e5e5e5
+
+contentBackgroundColor:string=#484848
+
+configFontColor:string=#fff
+configBackgroundColor:string=#3e3e3e
+
+portfolioSlideBackgroundColor:string=#f2f2f2
+
+memberActionsBoxBackground:string=#484848
+footerBackgroundColor:string=#707070
+outlineColor:string=#F28C18
+bylineBackgroundColor:string=#202020
+messageFontColor:string=#F28C18
+listingHeaderBackgroundColor:string=#000
+listingHeaderFontColor:string=#ddd
+listingBarBorderColor:string=#202020
+newsTitleBorderColor:string=#ddd
+boxesBorderColor:string=#ddd
+specialLinkColor:string=#e6eadd
+specialLinkHoverColor:string=#f28c18
+bulletColor:string=#ef8e32
+boxeHeaderBackgroundColor:string=#484848
+
+twoColumnFormFontColor:string=#fff
+twoColumnFormBackground:string=#3A3A3A
diff --git a/skins/photo_theme/collapsePalette.gif b/skins/photo_theme/collapsePalette.gif
new file mode 100644 (file)
index 0000000..2777170
Binary files /dev/null and b/skins/photo_theme/collapsePalette.gif differ
diff --git a/skins/photo_theme/collapsedPalette.gif b/skins/photo_theme/collapsedPalette.gif
new file mode 100644 (file)
index 0000000..17caf53
Binary files /dev/null and b/skins/photo_theme/collapsedPalette.gif differ
diff --git a/skins/photo_theme/createMemberContent.py b/skins/photo_theme/createMemberContent.py
new file mode 100755 (executable)
index 0000000..0256a30
--- /dev/null
@@ -0,0 +1,2 @@
+##parameters=member,member_id,member_folder
+return None
\ No newline at end of file
diff --git a/skins/photo_theme/customer_join_form.py b/skins/photo_theme/customer_join_form.py
new file mode 100755 (executable)
index 0000000..a1e3111
--- /dev/null
@@ -0,0 +1,61 @@
+##parameters=add=''
+from Products.CMFCore.utils import getToolByName
+from Products.realis.utils import translate
+from ZTUtils import make_query as mq
+_ = lambda msg : translate(msg, context)
+ptool = getToolByName(script, 'portal_properties')
+atool = getToolByName(script, 'portal_actions')
+validate_email = ptool.getProperty('validate_email')
+options = {}
+options['validate_email'] = validate_email
+
+req = context.REQUEST
+resp = req.RESPONSE
+form = req.form
+fg = lambda name : form.get(name,'').strip()
+
+
+if add and \
+       context.validatePassword(**form) and \
+       context.customer_add_control(**form) and \
+       context.validatePrivateAccess(**form) :
+       came_from = fg('came_from')
+       if came_from :
+               return context.setRedirect(     atool, 'user/logged_in'
+                                                                 , came_from = came_from
+                                                                 , __ac_name=fg('member_id')
+                                                                 , __ac_password=fg('password'))
+               #return resp.redirect('%s?%s' % ( came_from, mq(__ac_name=fg('member_id'), __ac_password=fg('password'), noajax='1')) )
+       else:
+               options['member_id'] = fg('member_id')
+               options['password'] = fg('password')
+               options['form_action'] = target = atool.getActionInfo('user/logged_in')['url']
+               return context.confirm_join_template(**options)
+
+continuationFields = [
+         'given_name'
+       , 'name'
+       , 'member_email'
+       , 'member_id'
+       , 'password'
+       , 'confirm'
+       , 'send_password'
+       , 'wedding_id'
+       , 'wedding_password'
+       , 'wedding_password_confirm'
+       , 'billing_address'
+       , 'billing_city'
+       , 'billing_zipcode'
+       , 'country'
+       , 'phone'
+       , 'accept_gcs']
+
+
+for name in continuationFields :
+       options[name] = fg(name)
+
+# TODO try to be more clever...
+if not options['country']:
+       options['country'] = 'FR'
+options['came_from'] = fg('came_from')
+return context.customer_join_template(**options)
diff --git a/skins/photo_theme/customer_join_template.pt b/skins/photo_theme/customer_join_template.pt
new file mode 100644 (file)
index 0000000..5c2a95c
--- /dev/null
@@ -0,0 +1,159 @@
+<html metal:use-macro="context/main_template/macros/master">
+  <head>
+    <meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
+  </head>
+  <body metal:fill-slot="main_no_tabs" i18n:domain="realis"
+        tal:omit-tag="">
+    <div tal:condition="python:options.get('came_from', '').endswith('/my_cart')"
+         tal:define="step_authentication python:True" tal:omit-tag="">
+      <div metal:use-macro="here/sell_macros/macros/sell_steps"></div>
+    </div>
+    <h1 i18n:translate="">New customer account</h1>
+    
+    <form tal:attributes="action string:portal_url/customer_join_form" method="post">
+      <table class="TwoColumnForm">
+        <tr>
+          <td colspan="2" style="text-align:center">
+            <h3 i18n:translate="">Customer informations</h3>
+          </td>
+        </tr>
+        <tr>
+          <th i18n:translate="">First name</th>
+          <td>
+            <input type="text" name="given_name" size="30" value="" tal:attributes="value options/given_name" />
+          </td>
+        </tr>
+        <tr>
+          <th i18n:translate="">Last name</th>
+          <td>
+            <input type="text" name="name" size="30" value="" tal:attributes="value options/name" />
+          </td>
+        </tr>
+        <tr>
+          <th i18n:translate="">Email Address</th>
+          <td>
+            <input type="text" name="member_email" size="30"
+                   tal:attributes="value options/member_email" />
+          </td>
+        </tr>
+        <tr>
+         <th i18n:translate="">Member ID</th>
+         <td>
+          <input type="text" name="member_id" size="30" value=""
+                 tal:attributes="value options/member_id" />
+         </td>
+        </tr>
+        <tal:case tal:condition="not: options/validate_email">
+          <tr>
+            <th i18n:translate="">Password</th>
+            <td>
+              <input type="password" name="password" size="30" tal:attributes="value options/password" />
+            </td>
+          </tr>
+          <tr>
+            <th i18n:translate="">Password (confirm)</th>
+            <td>
+              <input type="password" name="confirm" size="30" tal:attributes="value options/confirm" />
+            </td>
+          </tr>
+          <tr>
+            <th i18n:translate="">Mail Password?</th>
+            <td>
+              <input type="checkbox" name="send_password" id="cb_send_password"
+                     tal:attributes="checked options/send_password" />
+              <em><label for="cb_send_password" i18n:translate="">Check this box to
+                have the password mailed.</label></em>
+            </td>
+          </tr>
+        </tal:case>
+        <tr>
+          <td colspan="2"><hr/></td>
+        </tr>
+        <tr>
+          <td colspan="2" style="text-align:center">
+            <h3>Accès à des images privées</h3>
+            veuillez entrer le code d'accès pour accéder / acheter les images<br/>
+            d'un événement privé couvert par les photographes de notre agence.
+          </td>
+        </tr>
+        <tr>
+          <th>Identifiant collection privée</th>
+          <td>
+            <input type="text" name="wedding_id" tal:attributes="value options/wedding_id"/>
+          </td>
+        </tr>
+        <tr>
+          <th>Mot de passe associé</th>
+          <td>
+            <input type="password" name="wedding_password" tal:attributes="value options/wedding_password" />
+          </td>
+        </tr>
+        <tr>
+          <th>Confirmation du mot de passe</th>
+          <td>
+            <input type="password" name="wedding_password_confirm" tal:attributes="value options/wedding_password_confirm" />
+          </td>
+        </tr>
+        <tr>
+          <td colspan="2"><hr/></td>
+        </tr>
+        <tr>
+          <td colspan="2" style="text-align:center">
+            <h3 i18n:translate="">Billing informations</h3>
+          </td>
+        </tr>
+        <tr>
+          <th i18n:translate="">Address</th>
+          <td>
+            <textarea name="billing_address" tal:content="options/billing_address"
+                      cols="30" rows="1" style="width:auto"></textarea>
+          </td>
+        </tr>
+        <tr>
+          <th i18n:translate="">City</th>
+          <td>
+            <input type="text" name="billing_city" size="35" tal:attributes="value options/billing_city"/>
+          </td>
+        </tr>
+        <tr>
+          <th i18n:translate="">Zip code</th>
+          <td>
+            <input type="text" name="billing_zipcode" size="5" tal:attributes="value options/billing_zipcode"/>
+          </td>
+        </tr>
+        <tr>
+          <th i18n:translate="">Country</th>
+          <td>
+            <select name="country"
+                    tal:define="countries python:modules['Products.iso_3166_1'].fr.countries"
+                    i18n:domain="iso_3166_1">
+              <option tal:repeat="c countries" tal:attributes="value python:c[0]; selected python:c[0]==options['country']" tal:content="python:c[0]" i18n:translate=""></option>
+            </select>
+          </td>
+        </tr>
+        <tr>
+          <th i18n:translate="">Phone</th>
+          <td>
+            <input type="text" name="phone" tal:attributes="value options/phone"/>
+          </td>
+        </tr>
+        <tr>
+          <th><br/></th>
+          <td>
+            <input type="checkbox" name="accept_gcs" tal:attributes="checked python:options['accept_gcs']" />
+            <a tal:attributes="href string:$portal_url/cgv" target="_blank" i18n:translate="">I accept general conditions of sales</a>
+          </td>
+        </tr>
+        <tr>
+          <td>&nbsp;</td>
+          <td>
+            <input type="hidden" name="noAjax" value="1"/>
+            <input type="hidden" name="came_from" tal:condition="options/came_from" tal:attributes="value options/came_from" />
+            <input type="submit" name="add" value="Register" i18n:attributes="value"/>
+            <input type="submit" name="cancle" value="Cancel" i18n:attributes="value" style="margin-left:15em"/>
+          </td>
+        </tr>
+      </table>
+    </form>
+  </body>
+</html>
diff --git a/skins/photo_theme/doFormSearch.py b/skins/photo_theme/doFormSearch.py
new file mode 100755 (executable)
index 0000000..d917835
--- /dev/null
@@ -0,0 +1,45 @@
+## Script (Python) "doFormSearch"
+##parameters=REQUEST
+##title=Pre-process form variables, then return catalog query results.
+##
+vars = REQUEST.form
+form_vars = {}
+skip_vars = ['strCreator']
+select_vars = ( 'review_state'
+                         , 'Subject'
+                         , 'portal_type'
+                         )
+date_vars = ('created',
+                        )
+epoch = DateTime("1970/01/01 00:00:00 GMT")
+
+for k, v in vars.items():
+
+       if k in select_vars:
+               if same_type( v, [] ):
+                       v = filter( None, v )
+               if not v:
+                       continue
+
+       if k in date_vars:
+               if v == epoch and vars.get(k+'_usage') == 'range:min':
+                       skip_vars.append(k+'_usage')
+                       continue
+
+       form_vars[ k ] = v
+
+if form_vars.has_key('portal_type') :
+       try : form_vars['portal_type'].remove('Member Data')
+       except ValueError : pass
+else :
+       form_vars['portal_type'] = context.portal_types.objectIds()
+
+for k in skip_vars:
+       if form_vars.has_key(k) :
+               del form_vars[k]
+
+if vars.has_key('strCreator') :
+       form_vars['Creator'] = [ m.id for m in context.portal_membership.looseSearchMembers(vars['strCreator']) ]
+
+results = context.portal_catalog( form_vars )
+return {'results':results, 'searchArgs':form_vars}
diff --git a/skins/photo_theme/expandPalette.gif b/skins/photo_theme/expandPalette.gif
new file mode 100644 (file)
index 0000000..cb52874
Binary files /dev/null and b/skins/photo_theme/expandPalette.gif differ
diff --git a/skins/photo_theme/expandedPalette.gif b/skins/photo_theme/expandedPalette.gif
new file mode 100644 (file)
index 0000000..9b4f5a0
Binary files /dev/null and b/skins/photo_theme/expandedPalette.gif differ
diff --git a/skins/photo_theme/folder_contents.py b/skins/photo_theme/folder_contents.py
new file mode 100755 (executable)
index 0000000..e0bc4d8
--- /dev/null
@@ -0,0 +1,232 @@
+##parameters=b_start=0, key='', reverse=0, ids=(), items_copy='', items_cut='', items_delete='', items_new='', items_paste='', items_rename='', items_up='', items_down='', items_top='', items_bottom='', items_sort='', template='', macro='', ajax=''
+##
+from Products.Plinn.PloneMisc import Batch
+from DateTime import DateTime
+locale_date_fmt = context.locale_date_fmt()
+from ZTUtils import make_query
+from Products.CMFCore.utils import getToolByName
+from Products.CMFDefault.permissions import AddPortalContent
+from Products.CMFDefault.permissions import DeleteObjects
+from Products.CMFDefault.permissions import ListFolderContents
+from Products.CMFDefault.permissions import ManageProperties
+from Products.CMFDefault.permissions import ViewManagementScreens
+from Products.CMFDefault.permissions import ModifyPortalContent
+from Products.CMFDefault.utils import html_marshal
+
+mtool = getToolByName(script, 'portal_membership')
+checkPermission = mtool.checkPermission
+utool = getToolByName(script, 'portal_url')
+portal_url = utool()
+
+
+form = context.REQUEST.form
+default_target = 'object/folderContents'
+default_kw = {'b_start': b_start, 'key': key, 'reverse': reverse, 'ajax' : ajax}
+if items_copy :
+       if ajax : default_kw['syncFragments']=['rightCell']
+       if context.validateItemIds(**form) and \
+                       context.folder_copy_control(**form) and \
+                       context.setRedirect(context, default_target, **default_kw):
+               return
+elif items_cut :
+       if ajax : default_kw['syncFragments']=['rightCell']
+       if context.validateItemIds(**form) and \
+                       context.folder_cut_control(**form) and \
+                       context.setRedirect(context, default_target, **default_kw):
+                       return
+elif items_delete and \
+               context.validateItemIds(**form) and \
+               context.folder_delete_control(**form) and \
+               context.setRedirect(context, default_target, **default_kw):
+       return
+elif items_new and \
+               context.setRedirect(context, 'object/new', **default_kw):
+       return
+elif items_paste :
+       if ajax : default_kw['syncFragments']=['rightCell']
+       if context.folder_paste_control(**form) and \
+                       context.setRedirect(context, default_target, **default_kw):
+                       return
+elif items_rename and \
+               context.validateItemIds(**form) and \
+               context.setRedirect(context, 'object/rename_items', ids=ids,
+                                                       **default_kw):
+       return
+elif items_sort and \
+               context.folder_sort_control(**form) and \
+               context.setRedirect(context, default_target, b_start=b_start):
+       return
+elif items_up and \
+               context.validateItemIds(**form) and \
+               context.folder_up_control(**form) and \
+               context.setRedirect(context, default_target, **default_kw):
+       return
+elif items_down and \
+               context.validateItemIds(**form) and \
+               context.folder_down_control(**form) and \
+               context.setRedirect(context, default_target, **default_kw):
+       return
+elif items_top and \
+               context.validateItemIds(**form) and \
+               context.folder_top_control(**form) and \
+               context.setRedirect(context, default_target, **default_kw):
+       return
+elif items_bottom and \
+               context.validateItemIds(**form) and \
+               context.folder_bottom_control(**form) and \
+               context.setRedirect(context, default_target, **default_kw):
+       return
+       
+
+options = {}
+
+items_add_allowed = checkPermission(AddPortalContent, context)
+upitems_list_allowed = checkPermission(ListFolderContents, context, 'aq_parent')
+manage_props_allowed = checkPermission(ManageProperties, context)
+
+target = context.getActionInfo(default_target)['url']
+
+if not key:
+       (key, reverse) = context.getDefaultSorting()
+       is_default = 1
+elif (key, reverse) == context.getDefaultSorting():
+       is_default = 1
+else:
+       is_default = 0
+
+columns = ( {'key': 'Lock',
+                        'title': '',
+                        'width': '16',
+                        'colspan': None}
+                       , {'key': 'Type',
+                        'title': 'Type',
+                        'width': None,
+                        'colspan': '2'}
+                       , {'key': 'id',
+                        'title': 'Name',
+                        'width': None,
+                        'colspan': None}
+                       , {'key': 'modified',
+                        'title': 'Last Modified',
+                        'width': None,
+                        'colspan': None}
+                       , {'key': 'position',
+                        'title': 'Position',
+                        'width': None,
+                        'colspan': None }
+                       )
+
+for column in columns: 
+       images = []
+       if key == column['key'] :
+               if not is_default and manage_props_allowed :
+                       images.append( {'src' : getattr(context, 'set_default_sorting.gif').absolute_url(),
+                                                       'alt' : 'Set Sorting as Default',
+                                                       'id'     : 'SetSortingAsDefault',
+                                                       'href': '%s?%s' % (target, make_query(items_sort=True,
+                                                                                                                                 key=key,
+                                                                                                                                 reverse= (key != 'position' and [reverse] or [False])[0] )
+                                                                                                 )
+                                                        }
+                                                        )
+
+               if key != 'position' :
+                       if reverse :
+                               toggleImg = getattr(context, 'arrowDown.gif')
+                               alt = 'descending sort'
+                       else :
+                               toggleImg = getattr(context, 'arrowUp.gif')
+                               alt = 'ascending sort'
+                       query = make_query(key=column['key'], reverse = not reverse)
+               else :  
+                       toggleImg = getattr(context, 'arrowUp.gif')
+                       alt = 'ascending sort'
+                       query = make_query(key=column['key'])
+               images.append( {'src' : toggleImg.absolute_url(), 'alt' : alt} )
+       else :
+               if key != 'position' :
+                       query = make_query(key=column['key'], reverse = reverse)
+               else :
+                       query = make_query(key=column['key'])
+       
+       column['url'] = '%s?%s' % (target, query)
+       column['images'] = images
+
+context.filterCookie()
+folderfilter = context.REQUEST.get('folderfilter', '')
+filter = context.decodeFolderFilter(folderfilter)
+items = context.listCatalogedContents(contentFilter=filter)
+sort_dir = reverse and 'desc' or 'asc'
+sortFunc = key in ['Type'] and 'nocase' or 'cmp'
+items = sequence.sort( items, ((key, sortFunc, sort_dir),) )
+batch_obj = Batch(items, context.default_batch_size, b_start, orphan=0, quantumleap=1)
+items = []
+i = 1
+display_delete_button = True # TODO : à revoirs
+for item in batch_obj:
+       item_icon = item.getIcon
+       item_id = item.getId
+       item_position = key == 'position' and str(b_start + i) or '...'
+       i += 1
+       item_url = item.getURL()
+       #try : item_delete_allowed = context.objectIdCanBeDeleted(item_id)
+       #except : item_delete_allowed = checkPermission(DeleteObjects, context) # std zope perm
+       #if not display_delete_button :
+       #       display_delete_button = item_delete_allowed
+       items.append(
+               {'lock' : False,
+                'checkbox': True,
+                'icon': item_icon and ( '%s/%s' % (portal_url, item_icon) ) or '',
+                'id': item_id,
+                'modified': item.modified.strftime(locale_date_fmt),
+                'position': item_position,
+                'title_or_id': item.Title or item_id,
+                'type': item.Type or None,
+                'url': item_url } )
+
+options['batch'] = { 'listColumnInfos': tuple(columns),
+                                        'listItemInfos': tuple(items),
+                                        'sort_key' : key,
+                                        'sort_dir' : sort_dir,
+                                        'batch_obj': batch_obj }
+
+hidden_vars = []
+for name, value in html_marshal(**default_kw):
+       hidden_vars.append( {'name': name, 'value': value} )
+       
+# buttons
+buttons = []
+if items_add_allowed and context.allowedContentTypes():
+       buttons.append( {'name': 'items_new', 'value': 'New...'} )
+       if items:
+               buttons.append( {'name': 'items_rename', 'value': 'Rename'} )
+               
+if checkPermission(ViewManagementScreens, context) and items:
+       buttons.append( {'name': 'items_cut', 'value': 'Cut'} )
+       buttons.append( {'name': 'items_copy', 'value': 'Copy'} )
+       
+if items_add_allowed and context.cb_dataValid():
+       buttons.append( {'name': 'items_paste', 'value': 'Paste'} )
+       
+if display_delete_button and items:
+       buttons.append( {'name': 'items_delete', 'value': 'Delete'} )
+
+length = batch_obj.sequence_length
+is_orderable = manage_props_allowed and (key == 'position') and length > 1
+is_sortable = manage_props_allowed and not is_default
+options['form'] = { 'action': target,
+                                       'listHiddenVarInfos': tuple(hidden_vars),
+                                       'listButtonInfos': tuple(buttons),
+                                       'is_orderable': is_orderable,
+                                       'is_sortable': is_sortable }
+if not ajax and is_orderable :
+       deltas = range( 1, min(5, length) ) + range(5, length, 5)
+       options['form']['listDeltas'] = tuple(deltas)
+
+if template and macro :
+       options['template'] = template
+       options['macro'] = macro
+       return context.use_macro(**options)
+else :
+       return context.folder_contents_template(**options)
+
diff --git a/skins/photo_theme/folder_contents_macros.pt b/skins/photo_theme/folder_contents_macros.pt
new file mode 100644 (file)
index 0000000..00d2ee9
--- /dev/null
@@ -0,0 +1,118 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+  <head>
+    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+    <title>folder contents macros</title>
+  </head>
+
+  <body i18n:domain="cmf_default" metal:define-macro="FolderListing"
+                               tal:define="batch_dict options/batch;
+                                                                               batch batch_dict/batch_obj;
+                                                                               listColumnInfos batch_dict/listColumnInfos;
+                                                                               listItemInfos batch_dict/listItemInfos;"
+                               tal:omit-tag="">
+    <div style="display:none">
+      <span id="FolderUrl" tal:content="here/absolute_url" >Folder url for script</span>
+      <span tal:condition="options/form/is_orderable" tal:omit-tag="">
+             <span id="FirstItemPos" tal:content="python:listItemInfos[0]['position']">first batch item position</span>
+             <span id="BatchNavigationSize" tal:content="batch/size"></span>
+           </span>
+    </div>
+       <!-- batch navigation -->
+    <div tal:define="navBatchBarId string:topNavBatchBar" tal:omit-tag="">
+      <span metal:use-macro="here/batch_macros/macros/navigation">batch navigation</span>
+    </div>
+    <table class="listing" cellspacing="0">
+                       <thead id="FolderListingHeader">
+                               <tr>
+                                       <th tal:attributes="width column_info/width; colspan column_info/colspan" tal:repeat="column_info listColumnInfos" nowrap="nowrap" >
+                                               <a href="." tal:attributes="href column_info/url" tal:content="column_info/title" i18n:translate="">Type</a>
+                                               <span  tal:repeat="img column_info/images" tal:omit-tag="">
+                                                       <a tal:omit-tag="python:not img.has_key('href')"
+                                                                tal:attributes="href img/href|nothing ; title img/alt" i18n:attributes="title"
+                                                                ><img tal:attributes="src img/src ; alt img/alt ; id img/id|nothing" border="0" i18n:attributes="alt" /></a>
+                                               </span>
+                                       </th>
+                                       <td colspan="5" tal:replace="nothing"></td>
+                               </tr>
+                       </thead>
+                       <tbody id="FolderListingBody">
+<tbody tal:repeat="item_info listItemInfos" tal:omit-tag="">
+                   <tr class="" tal:attributes="class python: (even and 'even') or 'odd'" tal:define="even repeat/item_info/even">
+                     <td><img src="." alt="lock" height="16" width="16" border="0"
+                              tal:condition="python:not isAnon and item_info['lock']"
+                              tal:attributes="src here/lock.gif/absolute_url"
+                              i18n:attributes="alt" /></td>
+                     <td>
+                       <input id="" type="checkbox" name="ids:list" value=""
+                              tal:attributes="value item_info/id; id item_info/checkbox" tal:condition="item_info/checkbox" />
+                     </td>
+                     <td>
+                       <a href="." tal:attributes="href item_info/url" tal:condition="item_info/icon">
+                         <img src="." alt="" tal:attributes="src item_info/icon; alt item_info/type" border="0" i18n:attributes="alt" />
+                       </a>
+                     </td>
+                     <td>
+                       <a href="." tal:attributes="href item_info/url" tal:define="tod item_info/title_or_id; id item_info/id">
+                         <span tal:replace="id">id</span>
+                         <span tal:condition="python:tod != id">
+                           • <span tal:replace="tod">title</span>
+                         </span>
+                       </a>
+                     </td>
+                     <td>
+                       <span tal:replace="item_info/modified">2001</span>
+                     </td>
+                     <td>
+                       <span tal:replace="item_info/position">1</span>
+                     </td>
+                   </tr>
+</tbody>
+               </tbody>
+    </table>
+    <!-- batch navigation -->
+    <div tal:define="navBatchBarId string:bottomNavBatchBar" tal:omit-tag="">
+      <span metal:use-macro="here/batch_macros/macros/navigation">batch navigation</span>
+    </div>
+               <script type="text/javascript">
+               //<!--
+                       // variables for drag-and-drop ordered support
+                       var ddEnabled = false
+                       try {
+                               var firstItemPos = parseInt(document.getElementById("FirstItemPos").innerHTML);
+                               ddEnabled = true;
+                       }
+                       catch (e) {}
+
+                       var topNavBatchBar              = document.getElementById("topNavBatchBar");
+                       var bottomNavBatchBar   = document.getElementById("bottomNavBatchBar");
+                       var listing = document.getElementById("FolderListingBody");
+
+                       if (ddEnabled) {
+                               var rows = listing.getElementsByTagName("TR")
+                               for ( var i = 0 ; i < rows.length ; i++ )
+                                       rows[i].pos = i + firstItemPos;
+
+                               var fDDcontroler = new FolderDDropControler(listing);
+                               var topNavBatchBar              = document.getElementById("topNavBatchBar");
+                               var bottomNavBatchBar   = document.getElementById("bottomNavBatchBar");
+                               if (topNavBatchBar && bottomNavBatchBar) {
+                                       new DropTarget(topNavBatchBar, fDDcontroler);
+                                       new DropTarget(bottomNavBatchBar, fDDcontroler);
+                               }
+                       }
+
+
+                       addListener(document.getElementById("FolderListingHeader"), "click", loadListing);
+                       if (topNavBatchBar && bottomNavBatchBar) {
+                               addListener(topNavBatchBar, "click", loadListing);
+                               addListener(bottomNavBatchBar, "click", loadListing);
+                       }
+
+               //-->
+               </script>
+  </body>
+
+</html>
\ No newline at end of file
diff --git a/skins/photo_theme/global_plinn_style.css.dtml b/skins/photo_theme/global_plinn_style.css.dtml
new file mode 100755 (executable)
index 0000000..763ec4c
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+
+
+*/
+
+/* zpt_stylesheet.css */
+<dtml-var zpt_stylesheet.css>
+
+/* plinn_style.css */
+<dtml-var plinn_style.css>
+
+/* Portfolio */
+<dtml-var portfolio_style.css>
+
+/* realis_style.css */
+<dtml-var realis_style.css>
\ No newline at end of file
diff --git a/skins/photo_theme/global_plinn_style.css.dtml.metadata b/skins/photo_theme/global_plinn_style.css.dtml.metadata
new file mode 100644 (file)
index 0000000..855fecc
--- /dev/null
@@ -0,0 +1,2 @@
+[default]
+cache=HTTPCache
diff --git a/skins/photo_theme/homepage_dispatcher.py b/skins/photo_theme/homepage_dispatcher.py
new file mode 100755 (executable)
index 0000000..57262be
--- /dev/null
@@ -0,0 +1,28 @@
+##parameters=
+from Products.CMFCore.utils import getToolByName
+from ZTUtils import make_query as mq
+from Products.CMFDefault.utils import Message as _
+
+req = context.REQUEST
+resp = req.RESPONSE
+came_from = req.form.get('came_from')
+
+if came_from :
+       urlQs = came_from.split('?', 1)
+       if len(urlQs) == 1 :
+               came_from = '%s?%s' % (urlQs[0], mq(portal_status_message=_('Login success')))
+       else :
+               url, qs=  urlQs
+               came_from = '%s?%s&%s' % (url, qs, mq(portal_status_message=_('Login success')))
+       return resp.redirect(came_from)
+
+else :
+       from Products.realis.utils import searchContentsWithLocalRolesForAuthenticatedUser as search
+       results = search(context, portal_type='Portfolio')
+       if results :
+               atool = getToolByName(context, 'portal_actions')
+               return context.setRedirect(atool, 'user/my_albums', portal_status_message=_('Login success'))
+       else :
+               utool = getToolByName(context, 'portal_url')
+               return resp.redirect('%s?%s' % (utool(), mq(portal_status_message=_('Login success'))))
+       
\ No newline at end of file
diff --git a/skins/photo_theme/imagerotator.swf b/skins/photo_theme/imagerotator.swf
new file mode 100644 (file)
index 0000000..0156f0e
Binary files /dev/null and b/skins/photo_theme/imagerotator.swf differ
diff --git a/skins/photo_theme/info.gif b/skins/photo_theme/info.gif
new file mode 100644 (file)
index 0000000..472921c
Binary files /dev/null and b/skins/photo_theme/info.gif differ
diff --git a/skins/photo_theme/loading_progress.gif b/skins/photo_theme/loading_progress.gif
new file mode 100755 (executable)
index 0000000..c2f0e7c
Binary files /dev/null and b/skins/photo_theme/loading_progress.gif differ
diff --git a/skins/photo_theme/logo.gif b/skins/photo_theme/logo.gif
new file mode 100755 (executable)
index 0000000..75e0264
Binary files /dev/null and b/skins/photo_theme/logo.gif differ
diff --git a/skins/photo_theme/logout.py b/skins/photo_theme/logout.py
new file mode 100755 (executable)
index 0000000..f3ec6fe
--- /dev/null
@@ -0,0 +1,17 @@
+## Script (Python) "logout"
+##title=Logout handler
+##parameters=ajax=''
+from Products.CMFCore.utils import getToolByName
+from Products.CMFDefault.utils import translate
+def _(msg) : return translate(msg, context)
+utool = getToolByName(context, 'portal_url')
+REQUEST = context.REQUEST
+if REQUEST.has_key('portal_skin'):
+       context.portal_skins.clearSkinCookie()
+REQUEST.RESPONSE.expireCookie('__ac', path='/')
+session = REQUEST.SESSION
+for k in session.keys() :
+       del session[k]
+context.setStatus(True, _('You have been logged out.'))
+portal = utool.getPortalObject()
+return context.setRedirect(portal, 'object/view')
\ No newline at end of file
diff --git a/skins/photo_theme/main_template_macros.pt b/skins/photo_theme/main_template_macros.pt
new file mode 100644 (file)
index 0000000..71c04a0
--- /dev/null
@@ -0,0 +1,123 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+  <head>
+    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+    <title></title>
+  </head>
+
+  <body>
+
+<div metal:define-macro="global_defines" tal:omit-tag=""
+tal:define="
+global utool nocall:here/portal_url;
+global mtool here/portal_membership;
+global atool here/portal_actions;
+global wtool here/portal_workflow;
+global portal_object utool/getPortalObject;
+global portal_title portal_object/Title;
+global object_title here/title_or_id;
+global portal_url utool;
+global member mtool/getAuthenticatedMember;
+global membersfolder mtool/getMembersFolder;
+global isAnon mtool/isAnonymousUser;
+global actions python: atool.listFilteredActionsFor( here );
+global user_actions actions/user;
+global object_actions actions/object;
+global workflow_actions actions/workflow;
+global folder_actions actions/folder;
+global global_actions actions/global;
+global wf_state python:wtool.getInfoFor(here,'review_state','');
+global locale_date_fmt here/locale_date_fmt;
+global dummy python:request.RESPONSE.setHeader('Content-Type', 'text/html;;charset=utf-8');
+Iterator python:modules['Products.Plinn'].IndexIterator ;
+global tabindex python:Iterator();
+global specialCtxHeader options/specialCtxHeader|nothing"
+               />
+
+
+<div metal:define-macro="top_bar">
+       <table id="Masthead" cellspacing="0" border="0">
+               <tr>
+                       <td id="PortalLogo" width="215"><a href="#" tal:attributes="href string:${portal_url}?noajax=1; title portal_object/title_or_id"><img src="logo.gif" tal:define="logo here/logo.gif" tal:attributes="src logo/absolute_url; alt portal_object/title_or_id; height logo/height; width logo/width" /></a></td>
+                       <td>
+                               <div id="site_menu"
+                                    tal:define="menu actions/site_menu|nothing"
+                                    tal:condition="menu">
+          <span tal:repeat="a menu" tal:omit-tag="">
+            <a tal:content="a/title" tal:attributes="href a/url">Site Menu</a>
+            <span tal:condition="not:repeat/a/end" tal:omit-tag=""> |</span>
+          </span>
+                         </div>
+                       </td>
+                       <td>
+                         <img tal:attributes="src here/loading_progress.gif/absolute_url" width="32" height="32" id="loading_progress" alt="Loading progress..." i18n:attributes="alt" style="display:none" />
+                       </td>
+                       <td style="vertical-align:top">
+                               <div id="site_related"
+                                    tal:define="menu actions/site_related|nothing"
+                                    tal:condition="menu">
+          <span tal:repeat="a menu" tal:omit-tag="">
+           <a tal:content="a/title" tal:attributes="href a/url">Site Menu</a>
+           <span tal:condition="not:repeat/a/end" tal:omit-tag=""> |</span>
+          </span>
+                               </div>
+                       </td>
+               </tr>
+       </table>
+</div>
+
+  
+<div tal:define="uname python: (isAnon and [''] or [member.getMemberFullName(nameBefore=0)])[0]" metal:define-macro="user_menu_bar">
+       <table id="MemberActionsBox" border="0" cellspacing="0" i18n:domain="cmf_default">
+               <tr>
+                       <td class="ActionTitle" tal:content="uname">Guest</td>
+                       <td><img tal:attributes="src here/loading_progress.gif/absolute_url" width="82" height="7" id="loading_progress" alt="Loading progress..." i18n:attributes="alt" style="display:none" /></td>
+                       <td class="ActionLink" align="right">
+                               <span tal:repeat="action user_actions">
+                                       <a href="#" tal:attributes="href action/url" tal:content="action/name" i18n:translate="">Login</a>
+                                       <span tal:condition="not: repeat/action/end"> | </span> 
+                               </span>
+                               <span tal:condition="nothing"><a href="join_form" i18n:translate="">Join</a></span>
+                       </td>
+               </tr>
+       </table>
+</div>
+
+
+<div metal:define-macro="Breadcrumbs" tal:omit-tag="">
+       <span tal:content="here/absolute_url" id="BC_Object_URL" style="display:none"></span>
+  <span i18n:translate="">You are here:</span> <span tal:omit-tag="" tal:repeat="bc options/breadcrumbs|here/breadcrumbs"><a href="." tal:attributes="href bc/url" tal:content="python:bc['title'] or bc['id']">ID</a><span tal:condition="not: repeat/bc/end" tal:omit-tag=""> / </span> </span>
+</div>
+
+
+<div id="leftCell" class="boxes_container" width="15%" metal:define-macro="leftCell"
+                tal:define="block python:getattr(here.global_settings, 'left_boxes', None) ;
+                                                                displayAction python:request.SESSION.get('editBoxes') and 'edit' or 'view'"
+                tal:omit-tag="">
+               <div tal:condition="python:displayAction == 'edit' and here.cb_dataValid() and block.haveRules()">
+                       <a title="Paste" href="#" tal:attributes="href string:${block/absolute_url}/pasteBlocks" i18n:attributes="title"><img src="paste.png" alt="Paste" height="14" width="16" tal:attributes="src string:paste.png" border="0" i18n:attributes="alt" /></a>
+               </div>
+               <div metal:use-macro="here/block_canvas/macros/canvas">left boxes</div>
+</div>
+
+<div metal:define-macro="rightCell" 
+                tal:define="block python:getattr(here.global_settings, 'right_boxes', None) ;
+                                                                displayAction python:request.SESSION.get('editBoxes') and 'edit' or 'view'"
+                tal:condition="python:block is not None">
+       <div tal:condition="python:displayAction=='edit'" style="text-align:right">
+               <a tal:attributes="href string:$portal_url/manage_boxes?exitMode:boolean=True" i18n:domain="plinn" i18n:translate="">Exit boxes editing</a><br/>
+       </div>
+       <div tal:condition="python:displayAction == 'edit' and here.cb_dataValid() and block.haveRules()">
+               <a title="Paste" href="#" tal:attributes="href string:${block/absolute_url}/pasteBlocks" i18n:attributes="title"><img src="paste.png" alt="Paste" height="14" width="16" tal:attributes="src string:paste.png" border="0" i18n:attributes="alt" /></a>
+       </div>
+       
+       <div metal:use-macro="here/block_canvas/macros/canvas">right boxes</div>
+
+       <div metal:use-macro="here/widgets/macros/clipboard">Clipboard</div>
+</div>
+
+  </body>
+
+</html>
\ No newline at end of file
diff --git a/skins/photo_theme/main_template_standard.pt b/skins/photo_theme/main_template_standard.pt
new file mode 100755 (executable)
index 0000000..724b156
--- /dev/null
@@ -0,0 +1,168 @@
+<metal:block define-macro="master">
+  <tal:block define="global main_macros here/main_template_macros/macros"/>
+  <metal:block use-macro="main_macros/global_defines"/>
+  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+  <html xmlns="http://www.w3.org/1999/xhtml">
+
+    <head>
+      <title tal:content="here/expanded_title">Title goes here</title>
+      <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+      <meta name="description"
+            tal:attributes="content python:here.Description().strip() or portal_object.description" />
+      <meta name="keywords"
+            tal:define="keywords python:here.Subject() or portal_object.keywords or []"
+            tal:attributes="content python:', '.join(keywords)" />
+      <base tal:omit-tag="" metal:define-slot="base" />
+
+      <link rel="Shortcut Icon" type="image/x-icon" href="favicon.ico" tal:attributes="href string:$portal_url/favicon.ico" />
+      <link rel="alternate" type="application/rss+xml"
+            tal:define="stool nocall:here/portal_syndication"
+            tal:attributes="title here/title_or_id ; href string:${here/absolute_url}/RSS"
+            tal:condition="python:stool.isSyndicationAllowed(here)" />
+      
+      <link rel="stylesheet" media="screen" tal:attributes="href here/global_plinn_style.css/absolute_url" />
+      <style type="text/css" media="all" tal:content="string:@import url(${here/calendar-system.css/absolute_url});"></style>
+
+      <link metal:define-slot="css_slot" tal:replace="nothing" />
+      <script type="text/javascript" tal:attributes="src here/epoz_script_detect.js/absolute_url"></script>
+      <script type="text/javascript" tal:attributes="src here/javascript_events_api.js/absolute_url"></script>
+      <script type="text/javascript" tal:attributes="src here/sarissa.js/absolute_url"></script>      
+      <script type="text/javascript">
+        //<!--
+        function absolute_url() {
+          var e = document.getElementById("Object_URL");
+          if (e)
+            return e.innerHTML;
+          else {
+            e = document.getElementById("BC_Object_URL");
+            if (e)
+              return e.innerHTML;
+            else
+              return document.location.href;
+          }
+        }
+
+        function portal_url() {
+          var e = document.getElementById("Portal_URL");
+          return e.innerHTML;
+        }
+
+        var startupFunctions = new Array();
+
+        function registerStartupFunction(fct) {
+          startupFunctions.push(fct);
+        }
+
+        function runAjaxStartup() {
+          for (var i = 0 ; i < startupFunctions.length ; i++)
+            startupFunctions[i]();
+        }
+        
+        addListener(window, 'load', runAjaxStartup);
+        
+        var progressImage;
+        function _initLoadingStatus() {
+          progressImage = document.getElementById('loading_progress');
+        }
+        registerStartupFunction(_initLoadingStatus);
+        
+        function showProgressImage() { progressImage.style.display = 'inline'; }
+        function hideProgressImage() { progressImage.style.display = 'none'; }
+
+
+        // -->
+      </script>
+      <script type="text/javascript" tal:attributes="src here/base_properties.js/absolute_url"></script>
+      <script type="text/javascript" tal:attributes="src here/fragment_importer.js/absolute_url"></script>
+      <script type="text/javascript" tal:attributes="src here/ajax_form_manager.js/absolute_url"></script>
+      <script type="text/javascript" tal:attributes="src here/root_handlers.js/absolute_url"></script>
+      <script type="text/javascript" tal:attributes="src here/plinn_script_loader.js/absolute_url"></script>
+      
+      <script type="text/javascript" metal:define-slot="javascript_head_slot" tal:replace="nothing"></script>
+    </head>
+
+    <body>
+      <span style="display:none">
+        <span id="Portal_URL" tal:content="portal_url"></span>
+        <span id="ajax_config"  tal:content="python:request.get('ajaxConfig', request.SESSION.get('ajaxConfig', portal_object.getProperty('ajax_config')))"></span>
+        <script type="text/javascript">
+        // <!--
+          AJAX_CONFIG = document.getElementById('ajax_config');
+          AJAX_CONFIG = parseInt(AJAX_CONFIG.innerHTML);
+        // -->
+        </script>
+      </span>
+      <a href="#documentContent" i18n:translate="" i18n:domain="plinn" class="hidden">Skip to content</a>
+      <div metal:use-macro="main_macros/top_bar">Top bar</div>
+      <div id="search_bar">
+        <div metal:use-macro="here/realis_main_macros/macros/search_bar">Barre de recherche réalis</div>
+      </div>
+      <div id="Breadcrumbs"><div metal:use-macro="main_macros/Breadcrumbs">Breadcrumbs</div></div>
+
+      <div id="main_body">
+        <table id="Forematter" width="100%" cellspacing="0">
+          <tr>
+            <td class="boxes_container" width="15%" tal:condition="python:member.has_role(['photographe', 'Manager'])">
+              <div id="leftCell">
+                <span metal:use-macro="main_macros/leftCell">Left cell</span>
+              </div>
+              <div id="rightCell">
+                <span metal:use-macro="main_macros/rightCell">Right cell</span>
+              </div>
+            </td>
+
+            <td id="mainCell" width="85%">
+
+              <div class="DesktopStatusBar" tal:condition="request/portal_status_message|nothing">
+                <img src="info.gif" alt="Information" tal:attributes="src here/info.gif/absolute_url" i18n:attributes="alt" />
+                <span tal:content="request/portal_status_message" i18n:translate="">Status message.</span>
+              </div>
+
+              <a name="documentContent"></a>
+              <div metal:define-slot="main_no_tabs" tal:omit-tag="">
+                <div tal:condition="specialCtxHeader" tal:content="structure specialCtxHeader">special context header</div>
+                <div id="ContentTabs" tal:condition="not:specialCtxHeader">
+                  <div class="tabs" metal:use-macro="here/tabs/macros/tabs">Content tabs</div>
+                  <div metal:use-macro="here/tabs/macros/additional_tabs">Additional tabs</div>
+                </div>
+                <div id="ForematterCell">
+                  <div class="header">
+                    <div tal:omit-tag="" metal:define-slot="header">
+                      <h1 id="DesktopTitle">
+                        <span tal:replace="here/title_or_id">Page Title</span>
+                      </h1>
+                      <div id="DesktopDescription" tal:content="structure here/Description">
+                        Description of the resource goes here, perhaps even wrapping lines; this is to make it long enough to test.
+                      </div>
+                    </div>
+                  </div>
+
+                  <div id="Desktop">
+                    <div metal:define-slot="main">
+                      <h2>Section Header</h2>
+                      <p>The content of the object is <a href=".">rendered</a>
+                      hre. Lorem ipsum dolorem. Nihil obstat imprimatur. Semper ubi sub ubi.
+                      Non illegitimi carborundum. In vino veritas. E pluribus unam.
+                      </p>
+                    </div>
+                  </div>
+                  <div tal:condition="not:isAnon" tal:omit-tag="">
+                    <div id="ContentByLine" metal:use-macro="here/content_byline/macros/byline">
+                      Content by me
+                    </div>
+                  </div>
+                  <div metal:define-slot="footer" tal:replace="nothing">footer slot</div>
+                </div>
+              </div>
+
+            </td>
+            <!-- end_main_column -->
+          </tr>
+        </table>
+      </div>
+    </body>
+
+  </html>
+
+</metal:block>
\ No newline at end of file
diff --git a/skins/photo_theme/member_albums.py b/skins/photo_theme/member_albums.py
new file mode 100755 (executable)
index 0000000..9425f2b
--- /dev/null
@@ -0,0 +1,6 @@
+##parameters=
+
+from Products.realis.utils import searchContentsWithLocalRolesForAuthenticatedUser as search
+
+results = search(context, portal_type='Portfolio')
+return context.member_albums_template(results = results)
\ No newline at end of file
diff --git a/skins/photo_theme/member_albums_template.pt b/skins/photo_theme/member_albums_template.pt
new file mode 100644 (file)
index 0000000..eceee09
--- /dev/null
@@ -0,0 +1,42 @@
+<html metal:use-macro="here/main_template/macros/master"
+      xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal">
+  <head>
+    <title>Member albums' template</title>
+    <metal:block metal:fill-slot="javascript_head_slot">
+      
+    </metal:block>
+  </head>
+  <body>
+    <div metal:fill-slot="main_no_tabs" tal:omit-tag=""
+         tal:define="Batch python:modules['Products.Plinn'].Batch;
+                     b_start python:request.get('b_start',0);
+                     batch python:Batch(options['results'], 16, b_start, orphan=1, quantumleap=1);"
+         i18n:domain="portfolio">
+      <h2 i18n:translate="">My albums</h2>
+      <div tal:condition="not:batch" i18n:translate="">You don't have any album yet.</div>
+      <div tal:condition="batch">
+        <div metal:use-macro="here/batch_macros/macros/navigation">batch navigation</div>
+        <div class="portfolio_lightbox">
+          <a tal:repeat="brain batch"
+             tal:attributes="href brain/getURL">
+            <span tal:define="portfolio brain/getObject;
+                              sphoto portfolio/samplePhoto" tal:omit-tag="">
+              <span tal:condition="sphoto" tal:omit-tag="">
+                <img tal:attributes="src sphoto/src;
+                                     alt sphoto/alt;
+                                     height sphoto/height;
+                                     width sphoto/width;"/>
+              </span>
+              <span tal:condition="not:sphoto" tal:omit-tag="">
+                <img tal:attributes="src here/empty_portfolio.gif/absolute_url;
+                                     alt portfolio/title_or_id"/>
+              </span>
+              <h3 tal:content="portfolio/title_or_id">Portfolio title or id</h3>
+              <div tal:content="portfolio/Description"></div>
+            </span>
+          </a>
+        </div>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/skins/photo_theme/mi.gif b/skins/photo_theme/mi.gif
new file mode 100644 (file)
index 0000000..cb71f7e
Binary files /dev/null and b/skins/photo_theme/mi.gif differ
diff --git a/skins/photo_theme/mi_ani.gif b/skins/photo_theme/mi_ani.gif
new file mode 100644 (file)
index 0000000..10c759a
Binary files /dev/null and b/skins/photo_theme/mi_ani.gif differ
diff --git a/skins/photo_theme/pl.gif b/skins/photo_theme/pl.gif
new file mode 100644 (file)
index 0000000..26268f6
Binary files /dev/null and b/skins/photo_theme/pl.gif differ
diff --git a/skins/photo_theme/pl_ani.gif b/skins/photo_theme/pl_ani.gif
new file mode 100644 (file)
index 0000000..773202c
Binary files /dev/null and b/skins/photo_theme/pl_ani.gif differ
diff --git a/skins/photo_theme/portfolio_properties.props b/skins/photo_theme/portfolio_properties.props
new file mode 100644 (file)
index 0000000..44d3744
--- /dev/null
@@ -0,0 +1,19 @@
+medium_image_background:string=#727272
+metadata_bar_background:string=#555
+photographer_font_color:string=#fff
+title_font_color:string=#2b2b2b
+metadata_edit_label_color:string=#9da097
+metadata_edit_panel_background:string=#3e3e3e
+metadata_panel_border_sep_color:string=#484848
+metadata_input_font_color:string=#d9d9d9
+metadata_input_background:string=#3a3a3a
+metadata_input_border_color:string=#3a3a3a
+metadata_input_hover_background:string=#4c4c4c
+metadata_input_focus_font_color:string=#000
+metadata_input_focus_background:string=#fff
+metadata_input_border_focus_color:string=#313131
+portfolio_slide_background:string=#1b1b1b
+portfolio_slide_hover_background:string=#2b2b2b
+slide_background:string=#555
+slide_hover_background:string=#606060
+slide_selected_background:string=#727272
diff --git a/skins/photo_theme/realis_main_macros.pt b/skins/photo_theme/realis_main_macros.pt
new file mode 100644 (file)
index 0000000..c5e1bfa
--- /dev/null
@@ -0,0 +1,33 @@
+<html xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal">
+  <head>
+    <title>Macros realis</title>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
+  </head>
+  <body>
+    <div metal:define-macro="search_bar"
+         style="vertical-align:middle">
+      <form action="search" method="get" tal:attributes="action string:${portal_url}/search">
+        <div id="quicksearch" i18n:domain="cmf_default">
+          <span i18n:translate="" tal:omit-tag="">Search</span>
+          <input name="SearchableText" type="text" size="16" />
+          <input name="portal_type:list" type="hidden" value="Photo" />
+          <input type="image" tal:attributes="src string:${portal_url}/topic_icon.gif"
+                 width="16" height="16" alt="Search" i18n:attributes="alt"/>
+          <!--
+            <a tal:attributes="href string:${portal_url}/search_form" i18n:translate="">Advanced search</a>
+          -->
+        </div>
+      </form>
+      <div id="quickuser">
+          <span tal:define="uname python: (isAnon and [''] or [member.getMemberFullName(nameBefore=0)])[0]" tal:content="uname" style="font-weight:bold">bob</span>
+          &nbsp;&nbsp;&nbsp;&nbsp;
+          <span tal:repeat="action user_actions">
+          <a href="#" tal:attributes="href action/url" tal:content="action/title">Login</a>
+          <span tal:condition="not: repeat/action/end" tal:omit-tag=""> | </span>
+          </span>
+          <span tal:condition="nothing"><a href="join_form" i18n:translate="">Join</a></span>
+      </div>
+      <br clear="all"/>
+    </div>
+  </body>
+</html>
diff --git a/skins/photo_theme/realis_style.css.dtml b/skins/photo_theme/realis_style.css.dtml
new file mode 100644 (file)
index 0000000..76a4f20
--- /dev/null
@@ -0,0 +1,169 @@
+/* <dtml-with base_properties>
+
+
+*/
+
+h1, h2, h3, h4, h5, h6 {
+       color:#fff
+}
+
+.ActionTitle {
+  color: #fff;
+}
+
+.ActionLink a:link,
+.ActionLink a:visited,
+.ActionLink a:active { 
+  color: #fff;
+}
+
+.ActionLink a:hover { color: #ef8e32}
+
+#NavBar a,
+#NavBar a:link,
+#NavBar a:visited,
+#NavBar a:active { 
+  color: #fff;
+}
+
+#NavBar a:hover {
+  color: #ef8e32;
+}
+
+#Footer {
+  color: #e6eadd;
+}
+
+#quicksearch, #quickuser {
+       padding:2px;
+       font-size: 90%;
+}
+
+#quicksearch {
+       float:left;
+}
+
+
+#quickuser {
+       float:right;
+}
+
+#quicksearch input {
+       /*height:16px;*/
+       vertical-align:middle;
+}
+
+#quicksearch span {
+       vertical-align:middle;
+}
+#quickuser span {
+       padding-top:5px;
+       vertical-align: middle;
+}
+
+body {
+       padding: 0 40px;
+}
+
+img {
+       border:0;
+}
+
+#search_bar {
+       padding: 1px 8px ;
+       color:#f0f0f0;
+       background: #707070;
+}
+#search_bar input {
+       font-size:90%;
+       background:#e4e4e4;
+       border: 1px solid #2d2d2d;
+}
+
+
+#Masthead {
+       padding:4px;
+}
+
+#site_menu {
+       float:left;
+       font-size:130%;
+       margin-left:2em;
+}
+
+#site_related {
+       font-size:90%;
+       float:right;
+}
+
+#mainCell {
+       padding:4px 0 0 0;
+}
+
+.contentTabs a,
+.contentTabs a:visited
+{
+  border-left : none;
+  border-top : none;
+  border-right : none;
+}
+
+#DesktopDescription {
+  font-size: &dtml-fontSmallSize;;
+  color: &dtml-descriptionColor;;
+}
+
+#Desktop {
+  padding: 0;
+}
+
+#DesktopTitle {
+  padding: 0;
+}
+
+.header {
+  padding: 0;
+}
+
+.boxes_container li {
+  list-style:square inside;
+}
+
+table.home {
+       background:#111;
+       font-size:95%;
+}
+table.home td {
+       margin:0;
+       padding:0;
+}
+
+.home_menu a {
+       background:#111;
+       color: &dtml-fontColor;;
+       display:block;
+       width: 186px;
+       height: 216px;
+       display:block;
+       text-align:center;
+       overflow:hidden;
+}
+
+.home_menu a:hover {
+       background:#222;
+}
+
+.home_menu a h3 {
+       color:#fff;
+}
+
+.home_menu a:hover h3 {
+       color:&dtml-linkHoverColor;;
+}
+
+.home_menu p {
+       font-weight:bold;
+       font-size:10px;
+}
+
+/* </dtml-with> */
\ No newline at end of file
diff --git a/skins/photo_theme/search.pt b/skins/photo_theme/search.pt
new file mode 100644 (file)
index 0000000..8d90e1b
--- /dev/null
@@ -0,0 +1,52 @@
+<html xmlns:tal="http://xml.zope.org/namespaces/tal"
+      xmlns:metal="http://xml.zope.org/namespaces/metal"
+      metal:use-macro="here/main_template/macros/master">
+  <head>
+    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+    <metal:block metal:fill-slot="javascript_head_slot">
+      <script type="text/javascript" tal:attributes="src string:${portal_url}/photo_lightbox_viewer.js"></script>
+    </metal:block>
+  </head>
+  <body>
+    <div metal:fill-slot="main_no_tabs" i18n:domain="cmf_default">
+      <div class="Desktop">
+
+      <h2 i18n:translate="">Search Results</h2>
+
+      <div tal:define="b_start python:0;b_start request/b_start | b_start;
+                       results python:here.doFormSearch( REQUEST=request );
+                       searchArgs results/searchArgs;
+                       results results/results;
+                       stext request/SearchableText|nothing;
+                       resultsLength python:len(results);
+                       Batch python:modules['Products.Plinn'].Batch;
+                       global batch python:Batch(results, here.default_batch_size, b_start, orphan=1, quantumleap=1);
+                       macro python:request.form.get('portal_type') == ['Photo'] and 'photo' or 'normal';
+                      ">
+
+      <div tal:condition="resultsLength" tal:omit-tag="">
+      <p i18n:translate=""
+         tal:condition="stext">Found <span tal:replace="python:len(results)"
+         i18n:name="count">100</span> <span i18n:name="item_s_match"
+         tal:content="python:resultsLength > 1 and 'items matching' or 'item matching'"
+         i18n:translate=""
+         tal:omit-tag="">items matching</span> '<span
+         tal:replace="request/SearchableText"
+         i18n:name="text">search term</span>'.
+      </p>
+      <div tal:condition="not:stext">
+        <p tal:condition="python:resultsLength==1" i18n:translate="">Found 1 item.</p>
+        <p tal:condition="python:resultsLength>1" i18n:translate="">Found <span i18n:name="count" tal:content="resultsLength" tal:omit-tag="">2</span> items.</p>
+      </div>
+      </div>
+        <div tal:condition="results" tal:omit-tag="">
+          <div metal:use-macro="python:here.search_results_macros.macros[macro]"></div>
+        </div>
+        <p tal:condition="not:results" i18n:translate="">
+          There are no items matching your specified criteria.
+        </p>
+        </div>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/skins/photo_theme/search_results_macros.pt b/skins/photo_theme/search_results_macros.pt
new file mode 100644 (file)
index 0000000..a45d22b
--- /dev/null
@@ -0,0 +1,62 @@
+<html xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal">
+  <head>
+    <title>Macros utilisées pour l'affichage des résultats</title>
+    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+  </head>
+  <body>
+    <div metal:use-macro="here/batch_macros/macros/navigation">batch navigation</div>
+    <table metal:define-macro="normal" class="listing" cellspacing="0">
+     <thead>
+      <tr>
+       <td width="16">&nbsp;</td>
+       <th i18n:translate="">Title</th>
+                    <th i18n:translate="">Creator</th>
+                    <th i18n:translate="">Type</th>
+       <th i18n:translate="">Date</th>
+      </tr>
+     </thead>
+     <tbody tal:repeat="result batch" tal:omit-tag="">
+      <tr tal:define="objURL result/getURL;
+                                                               oddrow repeat/result/odd"
+               tal:attributes="class python:test(oddrow, 'even', 'odd')">
+       <td><a href=""
+         tal:condition="result/getIcon|nothing"
+             tal:attributes="href objURL"><img src="" border="0" alt="" title=""
+                 tal:define="alt result/Type"
+                 tal:attributes="src result/getIcon;
+                                 alt alt;
+                                 title alt" /></a></td>
+       <td><a href=""
+         tal:attributes="href objURL"><span
+             tal:condition="result/Title"
+                 tal:replace="result/Title">Title</span><span
+             tal:condition="not:result/Title"
+                 tal:omit-tag=""
+                 i18n:translate="">(No title)</span></a></td>
+                    <td tal:content="python:mtool.getMembers([result.Creator])[0].getMemberFullName(nameBefore=0)"
+                        tal:on-error="result/Creator"></td>
+                    <td tal:content="result/Type" i18n:translate="">Type</td>
+       <td tal:content="python:modules['DateTime'].DateTime(result.Date).strftime(locale_date_fmt)">Date</td>
+      </tr>
+      <tr>
+       <td>&nbsp;</td>
+       <td colspan="4"><em
+         tal:condition="result/Description"
+             tal:content="structure result/Description">Description</em><em
+         tal:condition="not:result/Description"
+             i18n:translate="">(No description)</em></td>
+      </tr>
+     </tbody>
+    </table>
+    
+    <div metal:define-macro="photo"
+         tal:define="slide_size python:portal_object.slide_size">
+      <div tal:define="contextInfo python:here.getPhotoBrainsInfos(batch, searchArgs);
+                       infos contextInfo/infos;
+                       features contextInfo/features"
+           tal:omit-tag="">
+        <div metal:use-macro="here/photo_layout_macros/macros/grid"></div>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/skins/photo_theme/tabs.pt b/skins/photo_theme/tabs.pt
new file mode 100644 (file)
index 0000000..c7a57cb
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+  <head>
+    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+    <title>tabs</title>
+    <link href="zpt_stylesheet.css" rel="stylesheet" media="screen" />
+    <link href="plinn_style.css" rel="stylesheet" media="screen" />
+  </head>
+
+  <body i18n:domain="plinn">
+
+    <div metal:define-macro="tabs"
+         tal:define="filteredActionsList python:[];
+                     dummy python:[ filteredActionsList.extend(l) for l in [ actions.get(key, []) for key in ['folder', 'object', 'workflow'] ] ]"
+         tal:condition="python:len(filteredActionsList) > 1" tal:omit-tag="">
+               <div metal:define-macro="standalone_tabs" tal:define="forceTab forceTab|nothing">
+      <ul class="contentTabs">
+        <li  class="selected" tal:replace="nothing">
+          <a href=".">View</a>
+        </li>
+        <li tal:repeat="action filteredActionsList"
+            tal:attributes="class python:( (forceTab == action['id']) or (request['URL0'].strip() == action['url'].strip() or request['URL0'].strip().split('/')[-1] == action['id']) ) and 'selected' or nothing">
+          <a href="#" tal:attributes="href action/url ; name action/id"
+             tal:content="action/title" i18n:translate="">Edit</a>
+        </li>
+      </ul>
+               </div>
+    </div>
+
+    <div metal:define-macro="additional_tabs"
+         tal:define="filteredActionsList python:actions.get('additional_tabs', [])"
+         tal:condition="filteredActionsList" tal:omit-tag="">
+       <div metal:define-macro="standalone_additional_tabs" tal:define="forceTab forceTab|nothing">
+             <ul class="additionalTabs">
+               <li  class="selected" tal:replace="nothing">
+                 <a href=".">View</a>
+               </li>
+               <li tal:repeat="action filteredActionsList"
+                   tal:attributes="class python:( (forceTab == action['id']) or (request['URL0'].strip() == action['url'].strip() or request['URL0'].strip().split('/')[-1] == action['id']) ) and 'selected' or nothing">
+                 <a href="#" tal:attributes="href action/url ; name action/id"
+                    tal:content="action/title" i18n:translate="">Edit</a>
+               </li>
+             </ul>
+           </div>
+    </div>
+    
+  </body>
+</html>
diff --git a/skins/photo_theme/validatePrivateAccess.py b/skins/photo_theme/validatePrivateAccess.py
new file mode 100755 (executable)
index 0000000..19e3a7d
--- /dev/null
@@ -0,0 +1,16 @@
+##parameters=**kw
+kg = lambda name : kw.get(name,'').strip()
+
+weddingId = kg('wedding_id')
+if not weddingId :
+       return True
+
+else :
+       password = kg('wedding_password')
+       confirm = kg('wedding_password_confirm')
+       memberId = kg('member_id')
+       msg = context.grantAccess(context, weddingId, password, confirm, memberId)
+       if msg :
+               return context.setStatus(False, msg)
+       else :
+               return True