Changeset 1113

Show
Ignore:
Timestamp:
04/10/08 08:27:17
Author:
mylan
Message:

Merged trunk with branches/plone_3.0 version

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • qPloneSkinDump/trunk/Extensions/Install.py

    r503 r1113  
    11from Products.Archetypes.Extensions.utils import install_subskin 
    2 from Products.CMFCore.CMFCorePermissions import ManagePortal 
    32from Products.CMFCore.utils import getToolByName 
     3try: 
     4    from Products.CMFCore.permissions import ManagePortal 
     5except: 
     6    from Products.CMFCore.CMFCorePermissions import ManagePortal 
    47 
    58from Products.qPloneSkinDump.config import * 
  • qPloneSkinDump/trunk/HISTORY.txt

    r1111 r1113  
    1 qPloneSkinDump 0.7.4 
    2     - Prevent copying .svn directories on skin product creating 
     1qPloneSkinDump 0.8.4 
     2     
     3    - Implemented correct installation/uninstallation 
     4      for generated skin product 
     5    - Prevent copying .svn directory into generated skin product 
     6      from template 
     7    - Added "Destination directory" field to skin dump form. 
     8      Allow change destination directory for generated product 
     9 
     10 
     11qPloneSkinDump 0.8.1 
     12 
     13    - essential improvements of dumping portlets 
     14 
     15qPloneSkinDump 0.8.0 
     16    - configlet form improvement 
     17    - fixed migration bugs to plone3 
     18    - added support for plone_view_customizations dump 
     19    - refactor old-style installer to portal_setup 
    320 
    421qPloneSkinDump 0.7.3 
  • qPloneSkinDump/trunk/TODO.txt

    r503 r1113  
    1 *** Under consideration *** 
     1*** TODO LIST *** 
    22 
    3   - Create more usable interface. 
     3  - improvements in resource dumping 
     4  - refactor portal_view_customizations dump 
     5  - add dump of portal_properties 
     6  - add dump of viewlets.xml 
     7  - add dump of portlets.xml 
     8  - core refactorization, divide into small chunks all functionality (too difficult to upgrade current skindump structure) 
     9       * maybe using zope 3 component architecture 
     10maybe in future: 
     11  - refactor qPloneSkinDump to work with python paster package, for use ZopeSkel templates styling 
  • qPloneSkinDump/trunk/config.py

    r1107 r1113  
    11import re, os 
    22try: 
    3     from Products.CMFCore import CMFCorePermissions 
    4 except ImportError
    5     from Products.CMFCore import permissions as CMFCorePermissions 
     3    from Products.CMFCore import permissions 
     4except
     5    from Products.CMFCore import CMFCorePermissions as permissions 
    66 
    77## Base Product Constants 
    88GLOBALS = globals() 
    99PROJECTNAME = "qPloneSkinDump" 
    10 ADD_CONTENT_PERMISSION = CMFCorePermissions.AddPortalContent 
     10ADD_CONTENT_PERMISSION = permissions.AddPortalContent 
    1111CONFIGURATION_CONFIGLET = "qploneskindump_configuration" 
    1212 
     
    2727DEFAULT_IMPORTING_POLICY = "only_new" 
    2828FORBIDDEN_EXP_PREFIXES = re.compile('^(portal_)') 
    29 FORBIDDEN_EXP_NAMES = ["MailHost", "HTTPCache", "Members", "RAMCache", "acl_users",\ 
     29FORBIDDEN_EXP_NAMES = ["ResourceRegistryCache", "MailHost", "HTTPCache", "Members", "RAMCache", "acl_users",\ 
    3030                       "archetype_tool", "caching_policy_manager", "content_type_registry", \ 
    3131                       "cookie_authentication", "error_log", "kupu_library_tool",\ 
  • qPloneSkinDump/trunk/exportingObjects.py

    r503 r1113  
    66import os, os.path 
    77osp = os.path 
     8from config import PRODUCTS_PATH 
    89 
    910def copyFile(src_dir, dst_dir, f_name): 
     
    3334##                         EXPORTING                         ## 
    3435############################################################### 
    35 def exportObjects(context, doesExportObjects, exporting_objects, product_name): 
     36def exportObjects(context, doesExportObjects, exporting_objects, 
     37                  fs_dest_directory, product_name): 
    3638    # Check whether should perform exporting 
    3739    if not doesExportObjects: 
    3840        return None 
    3941    # Get Instance's exported and Product's imoprt pathes 
    40     instance_epath, product_epath = getImportedPathes(product_name) 
     42    instance_epath, product_epath = getImportedPathes(fs_dest_directory, product_name) 
    4143    # Move same named files from Instance export dir to Temp dir 
    4244    temp_dir_path, product_elist = moveSameFilesToTemp(instance_epath, product_epath, exporting_objects) 
     
    6264    return fail_export 
    6365 
    64 def getImportedPathes(product_name): 
     66def getImportedPathes(fs_dest_directory, product_name): 
    6567    # Based on instance path, construct import pathes  
    6668    cfg = getConfiguration() 
    6769    instance_epath = cfg.clienthome 
    68     product_epath = osp.join(cfg.instancehome, 'Products', product_name, "import") 
     70    product_epath = osp.join(fs_dest_directory, product_name, "import") 
    6971    # Check presence of Product import directory 
    7072    if not osp.isdir(product_epath):         
  • qPloneSkinDump/trunk/qPloneSkinDump.py

    r894 r1113  
    88 
    99security = ModuleSecurityInfo( 'Products.qPloneSkinDump.qPloneSkinDump' ) 
     10 
     11security.declarePublic('getProductsPath') 
     12def getProductsPath(): 
     13    return PRODUCTS_PATH 
    1014 
    1115security.declarePublic('getExportingData') 
     
    3539 
    3640security.declarePublic('isValidProductName') 
    37 def isValidProductName(product_name): 
     41def isValidProductName(product_name, fs_dest_directory): 
    3842    """ Check for product presence in installed products list""" 
    39     return (product_name not in get_product_listdirs() \ 
    40             and isValidDirName(product_name)) 
     43    if not fs_dest_directory==PRODUCTS_PATH: 
     44       return (not product_name in os.listdir(fs_dest_directory)) \ 
     45              and isValidDirName(product_name) 
     46 
     47    return (not product_name in get_product_listdirs()) \ 
     48           and isValidDirName(product_name) 
     49 
     50security.declarePublic('isValidDestinationDir') 
     51def isValidDestinationDir(destination_dir): 
     52    """ Check for existance of destination directory.""" 
     53    return os.path.isdir(destination_dir) 
    4154 
    4255DIR_NAME_PATTERN = re.compile("^[a-zA-Z]+[a-zA-Z0-9_]*[a-zA-Z0-9]$") 
     
    4962security.declarePublic('createProduct') 
    5063def createProduct(context, \ 
    51                   zmi_skin_name='custom', \ 
     64                  zmi_skin_names=['custom',], \ 
    5265                  zmi_base_skin_name='', \ 
    5366                  subdir=None,\ 
     67                  fs_dest_directory=PRODUCTS_PATH, \ 
    5468                  fs_skin_directory='custom',\ 
    5569                  fs_product_name='QSkinTemplate',\ 
     
    6478                  exporting_objects=[], \ 
    6579                  dump_CSS=True, \ 
    66                   dump_JS=True ): 
     80                  dump_JS=True, \ 
     81                  dump_portlets=0, \ 
     82                  dump_policy='root', \ 
     83                  dump_portlets_selection=[], \ 
     84                  dump_custom_views=False): 
    6785    """ Main Skin Product creating procedure.""" 
    68     makeNewProduct(context, fs_product_name, fs_skin_directory, \ 
    69                    zmi_skin_name, zmi_base_skin_name, subdir, \ 
     86    makeNewProduct(context, fs_dest_directory, fs_product_name, fs_skin_directory, \ 
     87                   zmi_skin_names, zmi_base_skin_name, subdir, \ 
    7088                   doesCustomizeSlots, left_slots, right_slots, slot_forming, main_column, \ 
    7189                   doesExportObjects, import_policy, \ 
    72                    dump_CSS, dump_JS ) 
    73     dumpSkin(context, zmi_skin_name, subdir, fs_skin_directory.lower(), 
    74              fs_product_name, erase_from_skin) 
    75     result = exportObjects(context, doesExportObjects, exporting_objects, fs_product_name) 
     90                   dump_CSS, dump_JS, dump_portlets, dump_policy, dump_portlets_selection, dump_custom_views) 
     91    dumpSkin(context, zmi_skin_names, fs_dest_directory, fs_product_name, erase_from_skin) 
     92    result = exportObjects(context, doesExportObjects, exporting_objects, fs_dest_directory, fs_product_name) 
    7693    return result 
    7794 
  • qPloneSkinDump/trunk/skin_template/Extensions/Install.py

    r503 r1113  
    1 import string 
    2 from StringIO import StringIO 
    3 from zLOG import LOG, INFO 
    41from Products.CMFCore.utils import getToolByName 
    5 from Products.%(SKIN_PRODUCT_NAME)s.config import * 
    6 from Products.%(SKIN_PRODUCT_NAME)s.Extensions.utils import * 
    72 
    8 CHECKED_MESSAGE = "The base installation checkings completed." 
     3from Products.%(product_name)s.config import GS_INSTALL_PROFILE 
     4from Products.%(product_name)s.config import GS_AFTERINSTALL_PROFILE 
     5from Products.%(product_name)s.config import GS_UNINSTALL_PROFILE 
    96 
    10 def prepareInstallation(portal, pp, product, out): 
    11     checkSuccessInstall(product) 
    12     uninstallOtherSkinProducts(portal) 
    13     if not ('uninstall_properties' in pp.objectIds()) : 
    14         pp.addPropertySheet(id='uninstall_properties', title= 'uninstall_properties') 
    15         print >> out, "Created 'portal_properties.uninstall_properties' PropertySheet (UP) for backup purpose" 
     7def install(self, reinstall=False): 
     8    """ Install skin with GenericSetup install profile 
     9    """ 
     10    ps = getToolByName(self, 'portal_setup') 
     11    (ps.aq_base).__of__(self).runAllImportStepsFromProfile(GS_INSTALL_PROFILE) 
    1612 
    17 def checkSuccessInstall(product): 
    18     # Check for successfully completed 1 installation step 
    19     transcript = getattr(product,'transcript',None) 
    20     if transcript: 
    21         msg = str(transcript[0]['msg']) 
    22         if msg.find(CHECKED_MESSAGE) < 0 : 
    23             product.log("First part installation procedure not completed - installation terminated.") 
    24             raise 
     13def afterInstall(self, reinstall, product): 
     14    """ Install zexp objects and other dependent objects. 
     15        Perform this step here for prevent removing objects on uninstallation. 
     16    """ 
     17    ps = getToolByName(self, 'portal_setup') 
     18    (ps.aq_base).__of__(self).runAllImportStepsFromProfile(GS_AFTERINSTALL_PROFILE) 
    2519 
    26 def uninstallOtherSkinProducts(portal): 
    27     qi=getToolByName(portal, 'portal_quickinstaller', None) 
    28     if not qi: 
    29         raise Exception("Can't work without QuickInstaller tool.") 
    30     # Get installed products 
    31     installed_products = [getattr(qi, p_dict['id']) \ 
    32                           for p_dict in qi.listInstalledProducts() 
    33                           if p_dict['id'] != PRODUCT_NAME] 
    34     seek_str = "%%s generated product" %% GENERATOR_PRODUCT 
    35     installed_skin_products = [] 
    36     # Looking for installed skin-products 
    37     for p in installed_products: 
    38         transcript = p.getTranscriptAsText() 
    39         if transcript.find(seek_str) >= 0 : 
    40             installed_skin_products.append(p.getId()) 
    41     # Uninstall found skin-products 
    42     if installed_skin_products: 
    43         qi.uninstallProducts(products=installed_skin_products) 
    44  
    45 def install(self): 
    46     # Checking base condition for installation 
    47     skinsTool = getToolByName(self, 'portal_skins') 
    48     # Checking for BASE_SKIN_NAME presenting in portal 
    49     skin_names = skinsTool.getSkinSelections() 
    50     if not BASE_SKIN_NAME in skin_names: 
    51         raise AttributeError("Impossible installation without %%s skin." %% BASE_SKIN_NAME) 
    52     # Checking for presenting lower_SKIN_NAME directory in portal skins 
    53     lower_SKIN_NAME = string.lower(SKIN_NAME) 
    54     if lower_SKIN_NAME in skinsTool.objectIds(): 
    55         raise AttributeError("%%s skin layer already exist in portal skins. Installation Impossible." %% lower_SKIN_NAME) 
    56     return CHECKED_MESSAGE 
    57  
    58 # For prevent quickInstaller's intervention in uninstall process - use afterInstall 
    59 def afterInstall(self,product,reinstall): 
    60     out=StringIO() 
    61     # get all needed tools and some portal's core objects 
    62     portal = getToolByName(self, 'portal_url').getPortalObject() 
    63     pp = getToolByName(portal, 'portal_properties') 
    64     portal_css = getToolByName(portal, 'portal_css', None) 
    65     portal_js = getToolByName(portal, 'portal_javascripts', None) 
    66     # Make main prepare procedures 
    67     prepareInstallation(portal, pp, product, out) 
    68     pp_up = pp.uninstall_properties 
    69     # Install skin 
    70     installSkin(portal, pp_up, out) 
    71     # Register css resources 
    72     if portal_css and DOES_COSTOMIZE_CSS: 
    73         registerResource(pp_up, portal_css, portal_css.registerStylesheet, out \ 
    74                         ,CSS_LIST, SKIN_CSS_REGDATA, 'q_registered_css', CSS_REG_PROPS) 
    75         print >> out, "Completed tuning CSS registry for new skin needs." 
    76     # Register js resources 
    77     if portal_js and DOES_COSTOMIZE_JS: 
    78         registerResource(pp_up, portal_js, portal_js.registerScript, out \ 
    79                         ,JS_LIST, SKIN_JS_REGDATA, 'q_registered_js', JS_REG_PROPS)#---installJS--- 
    80         print >> out, "Completed tuning JS registry for new skin needs." 
    81     # Customize slots     
    82     if LEFT_SLOTS or RIGHT_SLOTS: 
    83         customizeSlots(portal, pp_up, out) 
    84     # Import object(s) to portal 
    85     if checkIfImport(): 
    86         res_import = performImportToPortal(portal) 
    87         print >> out, res_import 
    88     # FINAL customization call additional functions from config  
    89     if FINAL_CUSTOMIZATION_FUNCTIONS: 
    90         dummy = [func(portal, out) for func in FINAL_CUSTOMIZATION_FUNCTIONS] 
    91     print >> out, "%%s generated product." %% GENERATOR_PRODUCT 
    92     print >> out, '=== Installation successfully completed. ===' 
    93     product.log(out.getvalue()) 
    94     product._p_changed = 1 #XXX:NEED for stable writing 'out' log to qi on afterinstallation. 
    95     return out.getvalue() 
    96  
    97 def uninstall(self): 
    98     # get all needed tools and some portal's core objects 
    99     portal = self.portal_url.getPortalObject() 
    100     skinsTool = getToolByName(portal, 'portal_skins') 
    101     pp = getToolByName(portal, 'portal_properties') 
    102     portal_css = getToolByName(portal, 'portal_css', None) 
    103     portal_js = getToolByName(portal, 'portal_javascripts', None) 
    104     # Get all properies, saving during installation, for uninstalling 
    105     actual_skin_name = getProperty(pp, 'uninstall_properties', 'q_actual_skin_name',default=SKIN_NAME) 
    106     initial_skin = getProperty(pp, 'uninstall_properties', 'q_default_skin',default="") 
    107     original_css_list = getProperty(pp, 'uninstall_properties', 'q_registered_css') 
    108     original_js_list = getProperty(pp, 'uninstall_properties', 'q_registered_js') 
    109     orig_left_slots = getProperty(pp, 'uninstall_properties','q_left_slots') 
    110     orig_right_slots = getProperty(pp, 'uninstall_properties','q_right_slots') 
    111     # Remove 'uninstall_properties' from portal_properties 
    112     if 'uninstall_properties' in pp.objectIds() : 
    113         pp.manage_delObjects(ids=['uninstall_properties',]) 
    114     # Uninstall skin 
    115     uninstallSkin(skinsTool, actual_skin_name, initial_skin) 
    116     # Unregister skin's CSS-es from portal_css. Only for Plone 2.1+ 
    117     if portal_css and DOES_COSTOMIZE_CSS: 
    118         uninstallResource(portal_css, original_css_list, CSS_LIST, portal_css.registerStylesheet) 
    119     # Unregister skin's JS-s from portal_javascripts. Only for Plone 2.1+ 
    120     if portal_js and DOES_COSTOMIZE_JS: 
    121         uninstallResource(portal_js, original_js_list, JS_LIST, portal_js.registerScript) 
    122     # Return site's column slots list unless Skin product installation 
    123     if orig_left_slots: 
    124         portal.left_slots = tuple(orig_left_slots) 
    125     if orig_right_slots: 
    126         portal.right_slots = tuple(orig_right_slots) 
     20def uninstall(self, reinstall=False): 
     21    """ Uninstall skin with GenericSetup uninstall profile 
     22    """ 
     23    ps = getToolByName(self, 'portal_setup') 
     24    (ps.aq_base).__of__(self).runAllImportStepsFromProfile(GS_UNINSTALL_PROFILE) 
     25     
  • qPloneSkinDump/trunk/skin_template/Extensions/__init__.py

    r130 r1113  
    1 # this file is here to make Install.py importable. 
    2 # we need to make it non-zero size to make winzip cooperate 
     1
  • qPloneSkinDump/trunk/skin_template/__init__.py

    r503 r1113  
    1 from Products.CMFCore.DirectoryView import registerDirectory 
    2 from config import GLOBALS 
    3  
    4 registerDirectory('skins', GLOBALS) 
     1
  • qPloneSkinDump/trunk/skin_template/config.py

    r503 r1113  
     1import os 
    12## PLONE AND SKIN PRODUCT SPECIFIC CONSTANTS 
    23GLOBALS = globals() 
     
    1415## ['some/portlet1','some/portlet2'] - will change appropriate (left or right) 
    1516##                                     slot to listed portlets 
    16 LEFT_SLOTS = %(LEFT_SLOTS)s 
    17 RIGHT_SLOTS = %(RIGHT_SLOTS)s 
     17#LEFT_SLOTS = %(LEFT_SLOTS)s 
     18#RIGHT_SLOTS = %(RIGHT_SLOTS)s 
    1819 
    1920## Slot's list forming procedure. 
     
    2425#SLOT_FORMING = "blend_with_site" 
    2526#SLOT_FORMING = "replace" 
    26 SLOT_FORMING = "%(SLOT_FORMING)s" 
     27#SLOT_FORMING = "%(SLOT_FORMING)s" 
    2728 
    2829## Favour column for slots forming procedure. IMPORTANT only for 'Blend with...'  
     
    3738#MAIN_COLUMN = "right" 
    3839#MAIN_COLUMN = "both" 
    39 MAIN_COLUMN = "%(MAIN_COLUMN)s" 
     40#MAIN_COLUMN = "%(MAIN_COLUMN)s" 
    4041 
    4142 
     
    100101from Products.CMFCore.utils import getToolByName 
    101102FINAL_CUSTOMIZATION_FUNCTIONS = [] 
     103 
     104# site portlets registry 
     105SLOT_STRUCTURE = %(slot_structure)s 
     106 
     107# portal_view_customization content 
     108CUSTOM_VIEWS = %(custom_views)s 
     109 
     110# absolute file system path to product 
     111from Globals import package_home 
     112PRODUCTS_PATH = os.sep.join(package_home(GLOBALS).split(os.sep)[:-1]) 
     113 
     114## GenericSetup constants 
     115GS_INSTALL_PROFILE      = "profile-Products.%(product_name)s:default" 
     116GS_AFTERINSTALL_PROFILE = "profile-Products.%(product_name)s:afterinstall" 
     117GS_UNINSTALL_PROFILE    = "profile-Products.%(product_name)s:uninstall" 
  • qPloneSkinDump/trunk/skins/qploneskindump/qploneskindump_config.cpt

    r503 r1113  
    99    <div metal:define-macro="main" 
    1010         tal:define="errors options/state/getErrors | nothing;"> 
    11         <h1 class="QSDFirstHeading"> 
    12             <img tal:replace="structure here/product_icon.gif" /> 
    13             <span tal:replace="here/title_or_id">Title or id</span> 
    14         </h1> 
    15  
    16         <div metal:use-macro="here/document_actions/macros/document_actions"> 
    17             Document actions (print, sendto etc) 
     11 
     12        <div metal:use-macro="here/global_statusmessage/macros/portal_message"> 
     13            Portal status message 
    1814        </div> 
     15 
     16        <h1 class="documentFirstHeading" 
     17            i18n:translate="heading_addremove_products">Skin Dump</h1> 
    1918 
    2019        <a href="" 
    2120           class="link-parent" 
    22            i18n:translate="label_up_to_product_page" 
    23            tal:define="parent_url python:here.navigationParent(here, template.getId())" 
    24            tal:condition="parent_url" 
    25            tal:attributes="href parent_url"> 
    26             Up to Product page 
     21           tal:attributes="href string: $portal_url/plone_control_panel" 
     22           i18n:translate="label_up_to_plone_setup"> 
     23            Up to Site Setup 
    2724        </a> 
    2825 
    29         <h2 i18n:translate="heading_portalactions_lists"> 
    30             qPloneSkinDump input FORM 
    31         </h2> 
     26        <p class="documentDescription" 
     27            i18n:translate="description_addremove_products"> 
     28            This is a form for dumping your zmi skin to filesystem based product. 
     29        </p> 
     30 
     31        <p class="discreet" i18n:translate="description_product_location"> 
     32            Navigate through all form tabs to set needed configuration for dump. 
     33        </p> 
     34 
    3235        <form name="edit_form" 
    3336              action="href" 
    3437              method="post" 
     38              class="enableFormTabbing" 
    3539              enctype="multipart/form-data" 
    3640              tal:attributes="action string:$here_url/$template_id"> 
    37             <fieldset tal:define="error_zmiSN python:errors.get('ZMISkinName'); 
    38                                   error_zmiBSN python:errors.get('ZMIBaseSkinName')"> 
    39                 <legend> 
    40                   <label style="font-size: 110%" i18n:translate="legend_ZMI"> ZMI:</label> 
    41                 </legend> 
    42                 <div class="ZMISkinName" 
    43                      tal:attributes="class python: test(error_zmiSN, 'ZMISkinName error', 'ZMISkinName');"> 
    44                 <!-- folder in ZMI .../portal_skins, from which will be copyed content --> 
    45                     <label class="ZMISkinName_title" 
    46                            i18n:translate="label_ZMISkinName">Source ZMI skin folder</label> 
     41 
     42            <fieldset id="fieldset-product" 
     43                      tal:define="error_fsSkinDir python:errors.get('FSSkinDirectory'); 
     44                                  error_fsProdName python:errors.get('FSProductName'); 
     45                                  error_fsDestinationDir python:errors.get('FSDestinationDirectory');"> 
     46                <legend id="fieldsetlegend-product"> 
     47                  <label style="font-size: 110%" i18n:translate="label_product">Product</label> 
     48                </legend> 
     49                <p /> 
     50                <div class="FSProductName" 
     51                     tal:attributes="class python: test(error_fsProdName, 'FSProductName error', 'FSProductName');"> 
     52                    <label class="FSProductName_title" 
     53                          i18n:translate="label_FSProductName">Product name</label> 
    4754                    <span class="fieldRequired" 
    4855                           title="Required" 
    4956                           i18n:translate="label_required" 
    50                            i18n:attributes="title title_required;"> 
    51                                 (Required) 
    52                     </span> 
    53                     <div i18n:translate="help_ZMISkinName" 
    54                          class="formHelp"> 
    55                         Select folder from portal_skins, which content should by copyed to FS product. 
    56                     </div> 
    57                     <div tal:condition="error_zmiSN" 
    58                          tal:content="error_zmiSN" i18n:translate="">Validation Error</div> 
    59  
    60                     <select class="ZMISkinName_input" id="ZMISkinName"  
    61                             size="1" name="ZMISkinName" 
    62                             tal:define="value request/ZMISkinName|string:custom; 
    63                                         p_skins_ids python:portal.portal_skins.objectIds(spec='Folder')" 
    64                             tal:attributes="value value; 
    65                                             tabindex tabindex/next;"> 
    66                         <option selected="" 
    67                                 value="#" 
    68                                 tal:repeat="ps_folder p_skins_ids" 
    69                                 tal:attributes="value nocall:ps_folder; 
    70                                                 selected python:test(ps_folder==value, 'selected', None);" 
    71                                 tal:content="ps_folder"/> 
    72                          
    73                     </select> 
    74                 </div> 
    75                 <p/> 
     57                           i18n:attributes="title title_required;">(Required)</span> 
     58                    <div i18n:translate="help_FSProductName" 
     59                         class="formHelp"> 
     60                        Name for dumped product. This name should be unique in Destination directory. The name must begin with alphabetical character, following with an alphanumeric combination, also underscore accepts, but not on boundaries. 
     61                    </div> 
     62                    <div tal:condition="error_fsProdName" 
     63                         tal:content="error_fsProdName" i18n:translate="">Validation Error</div> 
     64 
     65                    <input class="FSProductName_input" 
     66                           type="text" 
     67                           name="FSProductName" 
     68                           value="qPloneSkinTemplate" 
     69                           size="50" 
     70                           tal:attributes="value request/FSProductName|nothing" /> 
     71                </div> 
     72                <p /> 
     73                <div class="FSSkinDirectory" 
     74                     tal:attributes="class python: test(error_fsSkinDir, 'FSSkinDirectory error', 'FSSkinDirectory');"> 
     75                    <label class="FSSkinDirectory_title" 
     76                          i18n:translate="label_FSSkinDirectory">Skin name</label> 
     77                    <span class="fieldRequired" 
     78                           title="Required" 
     79                           i18n:translate="label_required" 
     80                           i18n:attributes="title title_required;">(Required)</span> 
     81                    <div i18n:translate="help_FSSkinDirectory" 
     82                         class="formHelp"> 
     83                         Skin name in dumped product. The name must begin with alphabetical character, following with an alphanumeric combination, also underscore accepts, but not on boundaries. 
     84                    </div> 
     85                    <div tal:condition="error_fsSkinDir" 
     86                         tal:content="error_fsSkinDir" i18n:translate="">Validation Error</div> 
     87 
     88                    <input class="FSSkinDirectory_input" 
     89                           type="text" 
     90                           name="FSSkinDirectory" 
     91                           value="" 
     92                           size="50" 
     93                           tal:attributes="value request/FSSkinDirectory|nothing" /> 
     94                </div> 
     95                <p /> 
     96                <div class="FSDestinationDirectory" 
     97                     tal:define="destinationDir python:modules['Products.qPloneSkinDump.qPloneSkinDump'].getProductsPath();" 
     98                     tal:attributes="class python: test(error_fsDestinationDir, 'FSDestinationDirectory error', 'FSDestinationDirectory');"> 
     99                    <label class="FSDestinationDirectory_title" 
     100                          i18n:translate="label_FSDestinationDirectory">Destination directory</label> 
     101                    <span class="fieldRequired" 
     102                           title="Required" 
     103                           i18n:translate="label_required" 
     104                           i18n:attributes="title title_required;">(Required)</span> 
     105                    <div i18n:translate="help_FSDestinationDirectory" 
     106                         class="formHelp"> 
     107                         Absolute path to directory, where SkinProduct will be created. 
     108                    </div> 
     109                    <div tal:condition="error_fsDestinationDir" 
     110                         tal:content="error_fsDestinationDir" i18n:translate="">Validation Error</div> 
     111 
     112                    <input class="FSDestinationDirectory_input" 
     113                           type="text" 
     114                           name="FSDestinationDirectory" 
     115                           value="" 
     116                           size="50" 
     117                           tal:attributes="value request/FSDestinationDirectory|destinationDir" /> 
     118                </div> 
     119            </fieldset> 
     120 
     121            <fieldset id="fieldset-zmi" 
     122                      tal:define="error_zmiSN python:errors.get('ZMISkinName'); 
     123                                  error_zmiBSN python:errors.get('ZMIBaseSkinName')"> 
     124                <legend id="fieldsetlegend-zmi"> 
     125                  <label style="font-size: 110%" i18n:translate="legend_ZMI">Skin</label> 
     126                </legend> 
     127                <p /> 
    76128                <div class="ZMIBaseSkinName" 
    77129                     tal:attributes="class python: test(error_zmiBSN, 'ZMIBaseSkinName error', 'ZMIBaseSkinName');"> 
    78130                <!-- base for building layers list --> 
    79131                    <label class="ZMIBaseSkinName_title" 
    80                            i18n:translate="label_ZMIBaseSkinName">ZMI base skin name</label> 
     132                           i18n:translate="label_ZMIBaseSkinName">Skin selection</label> 
    81133                    <span class="fieldRequired" 
    82134                           title="Required" 
    83135                           i18n:translate="label_required" 
    84                            i18n:attributes="title title_required;"> 
    85                                 (Required) 
    86                     </span> 
     136                           i18n:attributes="title title_required;">(Required)</span> 
    87137                    <div i18n:translate="help_ZMIBaseSkinName" 
    88138                         class="formHelp"> 
    89                         Select Skin name, which layers list will be used for creating new skin. 
     139                        Select skin selection from portal_skins, which layers list will be used for creating new skin. 
    90140                    </div> 
    91141                    <div tal:condition="error_zmiBSN" 
     
    94144                    <select tal:define="value request/ZMIBaseSkinName|string:Plone Tableless; 
    95145                                        skin_names portal/portal_skins/getSkinSelections" 
    96                             tal:attributes="value value; 
    97                                             name string:ZMIBaseSkinName; 
     146                            tal:attributes="name string:ZMIBaseSkinName; 
    98147                                            id string:ZMIBaseSkinName; 
    99148                                            size string:1; 
     
    105154                                                selected python:test(skin_name==value, 'selected', None);" 
    106155                                tal:content="skin_name"/> 
    107                          
    108156                    </select> 
    109157                </div> 
    110                 <p/> 
     158                <p /> 
     159                <div class="ZMISkinName" 
     160                     tal:attributes="class python: test(error_zmiSN, 'ZMISkinName error', 'ZMISkinName');"> 
     161                <!-- folder in ZMI .../portal_skins, from which will be copyed content --> 
     162                    <label class="ZMISkinName_title" 
     163                           i18n:translate="label_ZMISkinName">Skin folders</label> 
     164                    <span class="fieldRequired" 
     165                           title="Required" 
     166                           i18n:translate="label_required" 
     167                           i18n:attributes="title title_required;">(Required)</span> 
     168                    <div i18n:translate="help_ZMISkinName" 
     169                         class="formHelp"> 
     170                        Select folders from portal_skins, which should be dumped to FS product's skins folder. 
     171                    </div> 
     172                    <div tal:condition="error_zmiSN" 
     173                         tal:content="error_zmiSN" i18n:translate="">Validation Error</div> 
     174 
     175                    <select class="ZMISkinName_input" id="ZMISkinName"  
     176                            size="5" name="ZMISkinName" multiple="1" 
     177                            tal:define="value request/ZMISkinName|string:custom; 
     178                                        p_skins_ids python:portal.portal_skins.objectIds(spec='Folder')" 
     179                            tal:attributes="tabindex tabindex/next;"> 
     180                        <option selected="" 
     181                                value="#" 
     182                                tal:repeat="ps_folder p_skins_ids" 
     183                                tal:attributes="value nocall:ps_folder; 
     184                                                selected python:test(ps_folder==value, 'selected', None);" 
     185                                tal:content="ps_folder"/> 
     186                    </select> 
     187                </div> 
     188                <p /> 
    111189                <div class="EraseFromSkin"> 
    112190                <!-- erase content of folder in ZMI .../portal_skins after copying --> 
    113                     <div i18n:translate="help_Erase" 
    114                          class="formHelp"> 
    115                         Select for erase content of skin's source folder. 
    116                     </div> 
    117  
    118191                    <input class="EraseFromSkin_input" 
    119192                           type="checkbox" 
    120193                           name="EraseFromSkin" 
     194                           id="EraseFromSkin" 
    121195                           value="0" 
    122196                           tal:attributes="checked python:test(request.has_key('EraseFromSkin'), 'checked', nothing)" 
    123197                           /> 
    124                     <label class="EraseFromSkin_title" 
    125                           i18n:translate="label_Erace">Erace </label> 
    126                 </div> 
    127             </fieldset> 
    128  
    129             <fieldset tal:define="error_fsSkinDir python:errors.get('FSSkinDirectory'); 
    130                                   error_fsProdName python:errors.get('FSProductName')"> 
    131                 <legend> 
    132                   <label style="font-size: 110%" i18n:translate="label_FS"> File system:</label> 
    133                 </legend> 
    134                 <div class="FSSkinDirectory" 
    135                      tal:attributes="class python: test(error_fsSkinDir, 'FSSkinDirectory error', 'FSSkinDirectory');"> 
    136                     <label class="FSSkinDirectory_title" 
    137                           i18n:translate="label_FSSkinDirectory">Skin's name for new prodct</label> 
    138                     <span class="fieldRequired" 
    139                            title="Required" 
    140                            i18n:translate="label_required" 
    141                            i18n:attributes="title title_required;"> 
    142                                 (Required) 
    143                     </span> 
    144                     <div i18n:translate="help_FSSkinDirectory" 
    145                          class="formHelp"> 
    146                          Input skin's name for new prodct. <br/> 
    147                          This name in lower case will be used as skin's folder name and as layer name too.<br/> 
    148                          The name must begin with alphabetical character, following with an alphanumeric combination, also underscore accepts, but not on boundaries.<br/> 
    149                     </div> 
    150                     <div tal:condition="error_fsSkinDir" 
    151                          tal:content="error_fsSkinDir" i18n:translate="">Validation Error</div> 
    152  
    153                     <input class="FSSkinDirectory_input" 
    154                            type="text" 
    155                            name="FSSkinDirectory" 
    156                            value="" 
    157                            size="50" 
    158                            tal:attributes="value request/FSSkinDirectory|nothing" /> 
    159                 </div> 
    160                 <p/> 
    161                 <div class="FSProductName" 
    162                      tal:attributes="class python: test(error_fsProdName, 'FSProductName error', 'FSProductName');"> 
    163                     <label class="FSProductName_title" 
    164                           i18n:translate="label_FSProductName">Product name</label> 
    165                     <span class="fieldRequired" 
    166                            title="Required" 
    167                            i18n:translate="label_required" 
    168                            i18n:attributes="title title_required;"> 
    169                                 (Required) 
    170                     </span> 
    171                     <div i18n:translate="help_FSProductName" 
    172                          class="formHelp"> 
    173                          Input name of new product.  <br/> 
    174                          This name can't be identical with other, presenting in your Products directory of Plone's instance. <br/> 
    175                          The name must begin with alphabetical character, following with an alphanumeric combination, also underscore accepts, but not on boundaries. 
    176                     </div> 
    177                     <div tal:condition="error_fsProdName" 
    178                          tal:content="error_fsProdName" i18n:translate="">Validation Error</div> 
    179  
    180                     <input class="FSProductName_input" 
    181                            type="text" 
    182                            name="FSProductName" 
    183                            value="qPloneSkinTemplate" 
    184                            size="50" 
    185                            tal:attributes="value request/FSProductName|nothing" /> 
    186                 </div> 
    187             </fieldset> 
    188  
    189             <fieldset> 
    190                 <legend class="DoesCustomizeSlots"> 
     198                    <label class="EraseFromSkin_title" for="EraseFromSkin" 
     199                          i18n:translate="label_Erase">Erase folders from portal_skins after dump</label> 
     200                </div> 
     201            </fieldset> 
     202 
     203            <fieldset id="fieldset-portlets"> 
     204                <legend id="fieldsetlegend-portlets" class="DoesCustomizeSlots"> 
     205                    <label style="font-size: 110%" i18n:translate="label_portlets">Portlets</label> 
     206                </legend> 
     207                <p /> 
     208                <div class="customize-portlets"> 
    191209                    <input class="noborder" 
    192210                           type="checkbox" 
    193                            name="DoesCustomizeSlots" 
     211                           name="dump_portlets" 
    194212                           id="DoesCustomizeSlots" 
    195                            value="DOCustomizeSlots
    196