From f8baeee4f718b96c4f096bb4098c46793927089a Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Wed, 30 Dec 2009 17:12:18 +0100 Subject: [PATCH] Ready for an 'advanced search' functionality. --- gen/plone25/generator.py | 87 +++++++++++++++++--------------- gen/plone25/mixins/ToolMixin.py | 45 ++++++++++++++--- gen/plone25/skin/macros.pt | 7 ++- gen/plone25/skin/search.gif | Bin 0 -> 433 bytes gen/plone25/skin/search.pt | 44 ++++++++++++++++ gen/plone25/skin/widgets.pt | 39 ++++++++++++++ gen/po.py | 4 ++ version.py | 2 + 8 files changed, 178 insertions(+), 50 deletions(-) create mode 100755 gen/plone25/skin/search.gif create mode 100644 gen/plone25/skin/search.pt create mode 100644 gen/plone25/skin/widgets.pt create mode 100644 version.py diff --git a/gen/plone25/generator.py b/gen/plone25/generator.py index 5d1eaae..a55674e 100644 --- a/gen/plone25/generator.py +++ b/gen/plone25/generator.py @@ -90,47 +90,52 @@ class Generator(AbstractGenerator): # Some global i18n messages poMsg = msg(app, '', app); poMsg.produceNiceDefault() self.labels += [poMsg, - msg('workflow_state', '', msg.WORKFLOW_STATE), - msg('data_change', '', msg.DATA_CHANGE), - msg('modified_field', '', msg.MODIFIED_FIELD), - msg('previous_value', '', msg.PREVIOUS_VALUE), - msg('phase', '', msg.PHASE), - msg('root_type', '', msg.ROOT_TYPE), - msg('workflow_comment', '', msg.WORKFLOW_COMMENT), - msg('choose_a_value', '', msg.CHOOSE_A_VALUE), - msg('choose_a_doc', '', msg.CHOOSE_A_DOC), - msg('min_ref_violated', '', msg.MIN_REF_VIOLATED), - msg('max_ref_violated', '', msg.MAX_REF_VIOLATED), - msg('no_ref', '', msg.REF_NO), - msg('add_ref', '', msg.REF_ADD), - msg('ref_name', '', msg.REF_NAME), - msg('ref_actions', '', msg.REF_ACTIONS), - msg('move_up', '', msg.REF_MOVE_UP), - msg('move_down', '', msg.REF_MOVE_DOWN), - msg('query_create', '', msg.QUERY_CREATE), - msg('query_import', '', msg.QUERY_IMPORT), - msg('query_no_result', '', msg.QUERY_NO_RESULT), - msg('query_consult_all', '', msg.QUERY_CONSULT_ALL), - msg('import_title', '', msg.IMPORT_TITLE), - msg('import_show_hide', '', msg.IMPORT_SHOW_HIDE), - msg('import_already', '', msg.IMPORT_ALREADY), - msg('import_many', '', msg.IMPORT_MANY), - msg('import_done', '', msg.IMPORT_DONE), - msg('ref_invalid_index', '', msg.REF_INVALID_INDEX), - msg('bad_int', '', msg.BAD_INT), - msg('bad_float', '', msg.BAD_FLOAT), - msg('bad_email', '', msg.BAD_EMAIL), - msg('bad_url', '', msg.BAD_URL), - msg('bad_alphanumeric', '', msg.BAD_ALPHANUMERIC), - msg('select_delesect', '', msg.SELECT_DESELECT), - msg('no_elem_selected', '', msg.NO_SELECTION), - msg('delete_confirm', '', msg.DELETE_CONFIRM), - msg('delete_done', '', msg.DELETE_DONE), - msg('goto_first', '', msg.GOTO_FIRST), - msg('goto_previous', '', msg.GOTO_PREVIOUS), - msg('goto_next', '', msg.GOTO_NEXT), - msg('goto_last', '', msg.GOTO_LAST), - msg('goto_source', '', msg.GOTO_SOURCE), + msg('workflow_state', '', msg.WORKFLOW_STATE), + msg('data_change', '', msg.DATA_CHANGE), + msg('modified_field', '', msg.MODIFIED_FIELD), + msg('previous_value', '', msg.PREVIOUS_VALUE), + msg('phase', '', msg.PHASE), + msg('root_type', '', msg.ROOT_TYPE), + msg('workflow_comment', '', msg.WORKFLOW_COMMENT), + msg('choose_a_value', '', msg.CHOOSE_A_VALUE), + msg('choose_a_doc', '', msg.CHOOSE_A_DOC), + msg('min_ref_violated', '', msg.MIN_REF_VIOLATED), + msg('max_ref_violated', '', msg.MAX_REF_VIOLATED), + msg('no_ref', '', msg.REF_NO), + msg('add_ref', '', msg.REF_ADD), + msg('ref_name', '', msg.REF_NAME), + msg('ref_actions', '', msg.REF_ACTIONS), + msg('move_up', '', msg.REF_MOVE_UP), + msg('move_down', '', msg.REF_MOVE_DOWN), + msg('query_create', '', msg.QUERY_CREATE), + msg('query_import', '', msg.QUERY_IMPORT), + msg('query_no_result', '', msg.QUERY_NO_RESULT), + msg('query_consult_all', '', msg.QUERY_CONSULT_ALL), + msg('import_title', '', msg.IMPORT_TITLE), + msg('import_show_hide', '', msg.IMPORT_SHOW_HIDE), + msg('import_already', '', msg.IMPORT_ALREADY), + msg('import_many', '', msg.IMPORT_MANY), + msg('import_done', '', msg.IMPORT_DONE), + msg('search_title', '', msg.SEARCH_TITLE), + msg('search_button', '', msg.SEARCH_BUTTON), + msg('search_objects', '', msg.SEARCH_OBJECTS), + msg('search_results', '', msg.SEARCH_RESULTS), + msg('search_results_descr', '', ' '), + msg('ref_invalid_index', '', msg.REF_INVALID_INDEX), + msg('bad_int', '', msg.BAD_INT), + msg('bad_float', '', msg.BAD_FLOAT), + msg('bad_email', '', msg.BAD_EMAIL), + msg('bad_url', '', msg.BAD_URL), + msg('bad_alphanumeric', '', msg.BAD_ALPHANUMERIC), + msg('select_delesect', '', msg.SELECT_DESELECT), + msg('no_elem_selected', '', msg.NO_SELECTION), + msg('delete_confirm', '', msg.DELETE_CONFIRM), + msg('delete_done', '', msg.DELETE_DONE), + msg('goto_first', '', msg.GOTO_FIRST), + msg('goto_previous', '', msg.GOTO_PREVIOUS), + msg('goto_next', '', msg.GOTO_NEXT), + msg('goto_last', '', msg.GOTO_LAST), + msg('goto_source', '', msg.GOTO_SOURCE), ] # Create basic files (config.py, Install.py, etc) self.generateTool() diff --git a/gen/plone25/mixins/ToolMixin.py b/gen/plone25/mixins/ToolMixin.py index 894a5b3..20299b1 100644 --- a/gen/plone25/mixins/ToolMixin.py +++ b/gen/plone25/mixins/ToolMixin.py @@ -1,5 +1,6 @@ # ------------------------------------------------------------------------------ import re, os, os.path, Cookie +from appy.gen import Type from appy.gen.utils import FieldDescr, SomeObjects from appy.gen.plone25.mixins import AbstractMixin from appy.gen.plone25.mixins.FlavourMixin import FlavourMixin @@ -111,12 +112,19 @@ class ToolMixin(AbstractMixin): '''Executes a query on a given p_contentType (or several, separated with commas) in Plone's portal_catalog. Portal types are from the flavour numbered p_flavourNumber. If p_searchName is specified, it - corresponds to a search defined on p_contentType: additional search - criteria will be added to the query. We will retrieve objects from - p_startNumber. If p_search is defined, it corresponds to a custom - Search instance (instead of a predefined named search like in - p_searchName). If both p_searchName and p_search are given, p_search - is ignored. This method returns a list of objects in the form of the + corresponds to: + 1) a search defined on p_contentType: additional search criteria + will be added to the query, or; + 2) "_advanced": in this case, additional search criteria will also + be added to the query, but those criteria come from the session + and were created from search.pt. + + We will retrieve objects from p_startNumber. If p_search is defined, + it corresponds to a custom Search instance (instead of a predefined + named search like in p_searchName). If both p_searchName and p_search + are given, p_search is ignored. + + This method returns a list of objects in the form of the __dict__ attribute of an instance of SomeObjects (see in appy.gen.utils). We return the __dict__ attribute instead of real instance: that way, it can be used in ZPTs without security problems. @@ -143,8 +151,9 @@ class ToolMixin(AbstractMixin): # In this case, contentType must contain a single content type. appyClass = self.getAppyClass(contentType) if searchName: - search = ArchetypesClassDescriptor.getSearch( - appyClass, searchName) + if searchName != '_advanced': + search = ArchetypesClassDescriptor.getSearch( + appyClass, searchName) if search: # Add additional search criteria for fieldName, fieldValue in search.fields.iteritems(): @@ -362,6 +371,26 @@ class ToolMixin(AbstractMixin): else: return False + def getSearchableFields(self, contentType): + '''Returns the list of fields that may be searched on objects on type + p_contentType (=indexed fields).''' + appyClass = self.getAppyClass(contentType) + res = [] + for attrName in dir(appyClass): + attr = getattr(appyClass, attrName) + if isinstance(attr, Type) and attr.indexed: + dAttr = self._appy_getTypeAsDict(attrName, attr, appyClass) + res.append((attrName, dAttr)) + return res + + def onSearchObjects(self): + '''This method is called when the user triggers a search from + search.pt.''' + rq = self.REQUEST + backUrl = '%s/query?type_name=%s&flavourNumber=%d&search=_advanced' % \ + (os.path.dirname(rq['URL']), rq['type_name'], rq['flavourNumber']) + return self.goto(backUrl) + def getJavascriptMessages(self): '''Returns the translated version of messages that must be shown in Javascript popups.''' diff --git a/gen/plone25/skin/macros.pt b/gen/plone25/skin/macros.pt index 1debd72..9e4e297 100644 --- a/gen/plone25/skin/macros.pt +++ b/gen/plone25/skin/macros.pt @@ -639,7 +639,7 @@ startNumber request/startNumber|python:'0'; startNumber python: int(startNumber); searchName request/search; - searchLabel python: '%s_search_%s' % (contentType, searchName); + searchLabel python: test(searchName=='_advanced', 'search_results', '%s_search_%s' % (contentType, searchName)); searchDescr python: '%s_descr' % searchLabel; severalTypes python: contentType and (contentType.find(',') != -1); queryResult python: tool.executeQuery(contentType, flavourNumber, searchName, startNumber, remember=True); @@ -909,6 +909,11 @@ tal:attributes="onClick python: 'href: window.location=\'%s/skyn/import?type_name=%s\'' % (appFolder.absolute_url(), rootClass); src string: $portal_url/skyn/import.png; title python: tool.translate('query_import')"/> + Search objects of this type (todo: update flavourNumber) + diff --git a/gen/plone25/skin/search.gif b/gen/plone25/skin/search.gif new file mode 100755 index 0000000000000000000000000000000000000000..ccdee1d37f9bea828abe28a4c740de241a4a4552 GIT binary patch literal 433 zcmZ?wbhEHb6kyI>if{QNFnym;sJuNR;G z9K8K={>iWZ|NlSv;OEja-|oEred58-19yI`KL35so;~09m(EI2c~&d?>-wsL+m-;8 zVFCtP0>%H_ey$ + +Disable standard Plone green tabs +
+ +
+
+ +Fill main slot of Plone main_template + + + + Search title +


+ + Form for searching objects of request/type_name. +
+ + + + + + + + + + + Submit button +


+ +

+
+
+ + diff --git a/gen/plone25/skin/widgets.pt b/gen/plone25/skin/widgets.pt new file mode 100644 index 0000000..5d37efc --- /dev/null +++ b/gen/plone25/skin/widgets.pt @@ -0,0 +1,39 @@ + +

Hello

+
+ + +

Hello

+
+ + +

Hello

+
+ + +

Hello

+
+ + +

Hello

+
+ + +

Hello

+
+ + +

Hello

+
+ + +

Hello

+
+ + +

Hello

+
+ + +

Hello

+
diff --git a/gen/po.py b/gen/po.py index cc0a257..6c24ffb 100755 --- a/gen/po.py +++ b/gen/po.py @@ -57,6 +57,10 @@ class PoMessage: IMPORT_ALREADY = 'Already imported.' IMPORT_MANY = 'Import selected elements' IMPORT_DONE = 'Import terminated successfully.' + SEARCH_TITLE = 'Advanced search' + SEARCH_BUTTON = 'Search' + SEARCH_OBJECTS = 'Search objects of this type.' + SEARCH_RESULTS = 'Search results' WORKFLOW_COMMENT = 'Optional comment' WORKFLOW_STATE = 'state' DATA_CHANGE = 'Data change' diff --git a/version.py b/version.py new file mode 100644 index 0000000..c5737e7 --- /dev/null +++ b/version.py @@ -0,0 +1,2 @@ +short='dev' +verbose='dev'