[gen] Allow for ajax-based master-slave relationships within the search screen for Ref fields.
This commit is contained in:
		
							parent
							
								
									584e38abef
								
							
						
					
					
						commit
						6d6c842f12
					
				
					 16 changed files with 79 additions and 88 deletions
				
			
		| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
#  "edit"   represents a given page for a given Appy class, in edit mode.
 | 
			
		||||
#  "cell"   represents a cell in a table, like when we need to render a field
 | 
			
		||||
#           value in a query result or in a reference table.
 | 
			
		||||
#  "search" represents an advanced search screen.
 | 
			
		||||
 | 
			
		||||
# Layout elements for a class or page ------------------------------------------
 | 
			
		||||
#  s - The page summary, containing summarized information about the page or
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +114,7 @@ class Table:
 | 
			
		|||
    '''Represents a table where to dispose graphical elements.'''
 | 
			
		||||
    simpleParams = ('style', 'css_class', 'cellpadding', 'cellspacing', 'width',
 | 
			
		||||
                    'align')
 | 
			
		||||
    derivedRepls = {'view': 'hrvd', 'cell': 'ldc'}
 | 
			
		||||
    derivedRepls = {'view': 'hrvd', 'search': '', 'cell': 'ldc'}
 | 
			
		||||
    def __init__(self, layoutString=None, style=None, css_class='',
 | 
			
		||||
                 cellpadding=0, cellspacing=0, width='100%', align='left',
 | 
			
		||||
                 other=None, derivedType=None):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -648,6 +648,8 @@ class ToolMixin(BaseMixin):
 | 
			
		|||
        for attrName in rq.form.keys():
 | 
			
		||||
            if attrName.startswith('w_') and \
 | 
			
		||||
               not self._searchValueIsEmpty(attrName):
 | 
			
		||||
                field = self.getAppyType(attrName[2:], rq.form['className'])
 | 
			
		||||
                if not field.persist: continue
 | 
			
		||||
                # We have a(n interval of) value(s) that is not empty for a
 | 
			
		||||
                # given field.
 | 
			
		||||
                attrValue = rq.form[attrName]
 | 
			
		||||
| 
						 | 
				
			
			@ -1384,18 +1386,6 @@ class ToolMixin(BaseMixin):
 | 
			
		|||
            res = self.goto(siteUrl, self.translate('wrong_password_reinit'))
 | 
			
		||||
        return res
 | 
			
		||||
 | 
			
		||||
    def getSearchValues(self, name, className):
 | 
			
		||||
        '''Gets the possible values for selecting a value for searching field
 | 
			
		||||
           p_name belonging to class p_className.'''
 | 
			
		||||
        klass = self.getAppyClass(className, wrapper=True)
 | 
			
		||||
        method = getattr(klass, name).searchSelect
 | 
			
		||||
        tool = self.appy()
 | 
			
		||||
        if method.__class__.__name__ == 'function':
 | 
			
		||||
            objects = method(tool)
 | 
			
		||||
        else:
 | 
			
		||||
            objects = method.__get__(tool)(tool)
 | 
			
		||||
        return [(o.uid, o) for o in objects]
 | 
			
		||||
 | 
			
		||||
    def getGoogleAnalyticsCode(self):
 | 
			
		||||
        '''If the config defined a Google Analytics ID, this method returns the
 | 
			
		||||
           Javascript code to be included in every page, allowing Google
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -690,6 +690,7 @@ class BaseMixin:
 | 
			
		|||
        '''Returns the database value of field named p_name for p_self.
 | 
			
		||||
           If p_onlyIfSync is True, it returns the value only if appyType can be
 | 
			
		||||
           retrieved in synchronous mode.'''
 | 
			
		||||
        if layoutType == 'search': return # No object in search screens.
 | 
			
		||||
        field = self.getAppyType(name)
 | 
			
		||||
        if not onlyIfSync or (onlyIfSync and field.sync[layoutType]):
 | 
			
		||||
            # We must really get the field value.
 | 
			
		||||
| 
						 | 
				
			
			@ -699,11 +700,6 @@ class BaseMixin:
 | 
			
		|||
            listType = self.getAppyType(listName)
 | 
			
		||||
            return listType.getInnerValue(self, outerValue, name, int(i))
 | 
			
		||||
 | 
			
		||||
    def getFormattedFieldValue(self, name, value, showChanges=False):
 | 
			
		||||
        '''Gets a nice, string representation of p_value which is a value from
 | 
			
		||||
           field named p_name.'''
 | 
			
		||||
        return self.getAppyType(name).getFormattedValue(self,value,showChanges)
 | 
			
		||||
 | 
			
		||||
    def getRequestFieldValue(self, name):
 | 
			
		||||
        '''Gets the value of field p_name as may be present in the request.'''
 | 
			
		||||
        # Return the request value for standard fields.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,8 @@ from appy.gen.wrappers.TranslationWrapper import TranslationWrapper as WT
 | 
			
		|||
from appy.gen.wrappers.PageWrapper import PageWrapper as WPage
 | 
			
		||||
from Globals import InitializeClass
 | 
			
		||||
from AccessControl import ClassSecurityInfo
 | 
			
		||||
tfw = {"edit":"f","cell":"f","view":"f"} # Layout for Translation fields
 | 
			
		||||
# Layouts for Translation fields
 | 
			
		||||
tfw = {"edit":"f","cell":"f","view":"f","search":"f"}
 | 
			
		||||
<!imports!>
 | 
			
		||||
 | 
			
		||||
<!User!>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,6 +93,7 @@ input.button { border-width: 0 !important; color: #666666; height: 23px;
 | 
			
		|||
                margin: 0.1em 0 0.3em ; border-bottom: 1px dashed grey }
 | 
			
		||||
.portletSearch { font-size: 90%; font-style: italic }
 | 
			
		||||
.inputSearch { height: 15px; width: 132px; margin: 3px 3px 2px 3px !important }
 | 
			
		||||
td.search { padding-top: 8px }
 | 
			
		||||
.content { padding: 14px 14px 9px 15px; background-color: #f1f1f1 }
 | 
			
		||||
.grey { display: none; position: absolute; left: 0px; top: 0px; z-index:2;
 | 
			
		||||
        background:grey; opacity:0.5; -moz-opacity:0.5; -khtml-opacity:0.5;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -244,15 +244,16 @@ function askComputedField(hookId, objectUrl, fieldName) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
function askField(hookId, objectUrl, layoutType, showChanges, masterValues,
 | 
			
		||||
                  requestValue, error){
 | 
			
		||||
                  requestValue, error, className){
 | 
			
		||||
  // Sends an Ajax request for getting the content of any field.
 | 
			
		||||
  var fieldName = hookId.split('_')[1];
 | 
			
		||||
  var params = {'layoutType': layoutType, 'showChanges': showChanges};
 | 
			
		||||
  if (masterValues) params['masterValues'] = masterValues.join('*');
 | 
			
		||||
  if (requestValue) params[fieldName] = requestValue;
 | 
			
		||||
  if (error) params[fieldName + '_error'] = error;
 | 
			
		||||
  askAjaxChunk(hookId, 'GET', objectUrl, fieldName+':pxRender', params, null,
 | 
			
		||||
               evalInnerScripts);
 | 
			
		||||
  var px = fieldName + ':pxRender';
 | 
			
		||||
  if (className) px = className + ':' + px;
 | 
			
		||||
  askAjaxChunk(hookId, 'GET', objectUrl, px, params, null, evalInnerScripts);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Function used by checkbox widgets for having radio-button-like behaviour
 | 
			
		||||
| 
						 | 
				
			
			@ -354,6 +355,8 @@ function getSlaves(master) {
 | 
			
		|||
  allSlaves = getElementsHavingName('table', 'slave');
 | 
			
		||||
  res = [];  
 | 
			
		||||
  masterName = master.attributes['name'].value;
 | 
			
		||||
  // Remove leading 'w_' if the master is in a search screen.
 | 
			
		||||
  if (masterName.indexOf('w_') == 0) masterName = masterName.slice(2);
 | 
			
		||||
  if (master.type == 'checkbox') {
 | 
			
		||||
    masterName = masterName.substr(0, masterName.length-8);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -370,7 +373,8 @@ function getSlaves(master) {
 | 
			
		|||
  return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateSlaves(master,slave,objectUrl,layoutType,requestValues,errors){
 | 
			
		||||
function updateSlaves(master, slave, objectUrl, layoutType, requestValues,
 | 
			
		||||
                      errors, className){
 | 
			
		||||
  /* Given the value(s) in a master field, we must update slave's visibility or
 | 
			
		||||
     value(s). If p_slave is given, it updates only this slave. Else, it updates
 | 
			
		||||
     all slaves of p_master. */
 | 
			
		||||
| 
						 | 
				
			
			@ -401,7 +405,8 @@ function updateSlaves(master,slave,objectUrl,layoutType,requestValues,errors){
 | 
			
		|||
      var err = null;
 | 
			
		||||
      if (errors && (slaveName in errors))
 | 
			
		||||
        err = errors[slaveName];
 | 
			
		||||
      askField(slaveId,objectUrl,layoutType,false,masterValues,reqValue,err);
 | 
			
		||||
      askField(slaveId, objectUrl, layoutType, false, masterValues, reqValue,
 | 
			
		||||
               err, className);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -495,6 +495,7 @@ class ToolWrapper(AbstractWrapper):
 | 
			
		|||
             refInfo=req.get('ref', None);
 | 
			
		||||
             searchInfo=ztool.getSearchInfo(className, refInfo);
 | 
			
		||||
             cssJs={};
 | 
			
		||||
             layoutType='search';
 | 
			
		||||
             x=ztool.getCssJs(searchInfo.fields, 'edit', cssJs)">
 | 
			
		||||
 | 
			
		||||
      <!-- Include type-specific CSS and JS. -->
 | 
			
		||||
| 
						 | 
				
			
			@ -506,7 +507,6 @@ class ToolWrapper(AbstractWrapper):
 | 
			
		|||
      <!-- Search title -->
 | 
			
		||||
      <h1><x>:_('%s_plural'%className)</x> –
 | 
			
		||||
          <x>:_('search_title')</x></h1>
 | 
			
		||||
      <br/>
 | 
			
		||||
      <!-- Form for searching objects of request/className. -->
 | 
			
		||||
      <form name="search" action=":ztool.absolute_url()+'/do'" method="post">
 | 
			
		||||
       <input type="hidden" name="action" value="SearchObjects"/>
 | 
			
		||||
| 
						 | 
				
			
			@ -516,13 +516,11 @@ class ToolWrapper(AbstractWrapper):
 | 
			
		|||
       <table width="100%">
 | 
			
		||||
        <tr for="searchRow in ztool.getGroupedSearchFields(searchInfo)"
 | 
			
		||||
            valign="top">
 | 
			
		||||
         <td for="field in searchRow"
 | 
			
		||||
         <td for="field in searchRow" class="search"
 | 
			
		||||
             var2="scolspan=field and field.scolspan or 1"
 | 
			
		||||
             colspan=":scolspan"
 | 
			
		||||
             width=":'%d%%' % ((100/searchInfo.nbOfColumns)*scolspan)">
 | 
			
		||||
           <x if="field"
 | 
			
		||||
              var2="name=field.name;
 | 
			
		||||
                    widgetName='w_%s' % name">:field.pxSearch</x>
 | 
			
		||||
           <x if="field">:field.pxRender</x>
 | 
			
		||||
           <br class="discreet"/>
 | 
			
		||||
         </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -575,7 +575,9 @@ class AbstractWrapper(object):
 | 
			
		|||
             lang=ztool.getUserLanguage();   q=ztool.quote;
 | 
			
		||||
             action=req.get('action', None);
 | 
			
		||||
             px=req['px'].split(':');
 | 
			
		||||
             field=(len(px) == 2) and zobj.getAppyType(px[0]) or None;
 | 
			
		||||
             className=(len(px) == 3) and px[0] or None;
 | 
			
		||||
             field=className and zobj.getAppyType(px[1], className) or None;
 | 
			
		||||
             field=(len(px) == 2) and zobj.getAppyType(px[0]) or field;
 | 
			
		||||
             dir=ztool.getLanguageDirection(lang);
 | 
			
		||||
             dleft=(dir == 'ltr') and 'left' or 'right';
 | 
			
		||||
             dright=(dir == 'ltr') and 'right' or 'left';
 | 
			
		||||
| 
						 | 
				
			
			@ -590,7 +592,7 @@ class AbstractWrapper(object):
 | 
			
		|||
 | 
			
		||||
      <!-- Then, call the PX on p_obj or on p_field. -->
 | 
			
		||||
      <x if="not field">:getattr(obj, px[0])</x>
 | 
			
		||||
      <x if="field">:getattr(field, px[1])</x>
 | 
			
		||||
      <x if="field">:getattr(field, px[-1])</x>
 | 
			
		||||
     </x>''')
 | 
			
		||||
 | 
			
		||||
    # --------------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue