Merge branch 'search_actions'

This commit is contained in:
Helmut Merz 2011-05-29 15:57:38 +02:00
commit b0c54ddd1b
6 changed files with 186 additions and 58 deletions

View file

@ -416,6 +416,13 @@ img.notselected {
font-weight: bold; font-weight: bold;
} }
.message {
font-weight: bold;
background-color: #c3d9ff;
padding: 4px;
margin-bottom: 4px;
}
/* comments */ /* comments */
div.comment { div.comment {
@ -440,10 +447,6 @@ div.comment {
padding: 2px; padding: 2px;
} }
.searchForm input.submit {
font-weight: bold;
}
/* blog */ /* blog */
.blog .description { .blog .description {

View file

@ -417,6 +417,13 @@ img.notselected {
font-weight: bold; font-weight: bold;
} }
.message {
font-weight: bold;
background-color: #c3d9ff;
padding: 4px;
margin-bottom: 4px;
}
/* lobo layout-specific classes */ /* lobo layout-specific classes */
.legend { .legend {
@ -447,10 +454,6 @@ div.comment {
padding: 2px; padding: 2px;
} }
.searchForm input.submit {
font-weight: bold;
}
/* blog */ /* blog */
.blog .description { .blog .description {

View file

@ -6,41 +6,52 @@
i18n_domain="loops"> i18n_domain="loops">
<zope:adapter <zope:adapter
name="action_query.html" name="action_query.html"
for="loops.interfaces.IConcept for="loops.interfaces.IConcept
zope.publisher.interfaces.browser.IBrowserRequest" zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface" provides="zope.interface.Interface"
factory="loops.expert.browser.base.BaseQueryView" factory="loops.expert.browser.base.BaseQueryView"
permission="zope.View" /> permission="zope.View" />
<browser:page <browser:page
name="search.html" name="search.html"
for="loops.interfaces.INode" for="loops.interfaces.INode"
class="loops.expert.browser.search.QuickSearchResults" class="loops.expert.browser.search.QuickSearchResults"
permission="zope.View" /> permission="zope.View" />
<zope:adapter <zope:adapter
name="search" name="search"
for="loops.interfaces.IConcept for="loops.interfaces.IConcept
zope.publisher.interfaces.browser.IBrowserRequest" zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface" provides="zope.interface.Interface"
factory="loops.expert.browser.search.Search" factory="loops.expert.browser.search.Search"
permission="zope.View" permission="zope.View" />
/>
<browser:page <browser:page
name="listConceptsForComboBox.js" name="listConceptsForComboBox.js"
for="loops.interfaces.ILoopsObject" for="loops.interfaces.ILoopsObject"
class="loops.expert.browser.search.Search" class="loops.expert.browser.search.Search"
attribute="listConcepts" attribute="listConcepts"
permission="zope.View" permission="zope.View" />
/>
<browser:page <browser:page
name="searchresults.html" name="searchresults.html"
for="loops.interfaces.ILoopsObject" for="loops.interfaces.ILoopsObject"
class="loops.expert.browser.search.SearchResults" class="loops.expert.browser.search.SearchResults"
permission="zope.View" permission="zope.View" />
/>
<zope:adapter
name="execute_query_action"
for="loops.browser.node.NodeView
zope.publisher.interfaces.browser.IBrowserRequest"
factory="loops.expert.browser.base.ActionExecutor"
permission="zope.ManageContent" />
<zope:adapter
name="execute_search_action"
for="loops.browser.node.NodeView
zope.publisher.interfaces.browser.IBrowserRequest"
factory="loops.expert.browser.search.ActionExecutor"
permission="zope.ManageContent" />
</configure> </configure>

View file

@ -33,11 +33,15 @@
tal:content="item/title"> tal:content="item/title">
Search Search
</h1> </h1>
<div class="message"
tal:define="message request/message|nothing"
tal:condition="message"
tal:content="message" />
<div metal:define-macro="search_form" class="searchForm"> <form action="." method="post" id="1.search.form"
<fieldset class="box"> tal:attributes="id formId">
<form action="." method="post" id="1.search.form" <div metal:define-macro="search_form" class="searchForm">
tal:attributes="id formId"> <fieldset class="box">
<input type="hidden" name="search.submitted" value="yes" /> <input type="hidden" name="search.submitted" value="yes" />
<input type="hidden" name="search.resultsId" value="1.results" <input type="hidden" name="search.resultsId" value="1.results"
tal:attributes="value resultsId" /> tal:attributes="value resultsId" />
@ -56,23 +60,24 @@
<td></td> <td></td>
<td colspan="3"><br /> <td colspan="3"><br />
<input type="submit" name="button.search" value="Search" class="submit" <input type="submit" name="button.search" value="Search" class="submit"
i18n:attributes="value" i18n:attributes="value" />
tal:attributes="xx_onclick python:
item.submitReplacing(resultsId, formId, view)" />
</td> </td>
</tr> </tr>
</table> </table>
</form> </fieldset>
</fieldset> </div>
</div> <tal:results condition="request/search.submitted|nothing">
<tal:results condition="request/search.submitted|nothing"> <metal:results use-macro="item/search_macros/search_results" />
<metal:results use-macro="item/search_macros/search_results" /> </tal:results>
</tal:results> </form>
</div> </div>
</metal:search> </metal:search>
<div metal:define-macro="search_results" id="search.results" <div metal:define-macro="search_results" id="search.results"
tal:define="item nocall:item|nocall:view"> tal:define="item nocall:item|nocall:view">
<input type="hidden" name="form.action"
tal:attributes="value item/form_action" />
<fieldset class="box"> <fieldset class="box">
<h2 i18n:translate="">Search results</h2> <h2 i18n:translate="">Search results</h2>
<metal:results define-macro="results"> <metal:results define-macro="results">
@ -80,6 +85,12 @@
i18n:attributes="summary"> i18n:attributes="summary">
<thead> <thead>
<tr> <tr>
<th tal:condition="item/showActions"
class="checkbox">
<input type="checkbox"
onchange="checked = this.checked;
dojo.query('.select_item').forEach(function(n) {
n.checked = checked;});" /></th>
<th i18n:translate="">Title</th> <th i18n:translate="">Title</th>
<th i18n:translate="">Type</th> <th i18n:translate="">Type</th>
<th i18n:translate="" <th i18n:translate=""
@ -95,8 +106,16 @@
<tal:items tal:repeat="row item/results"> <tal:items tal:repeat="row item/results">
<tal:item define="class python: repeat['row'].odd() and 'even' or 'odd'; <tal:item define="class python: repeat['row'].odd() and 'even' or 'odd';
description row/description; description row/description;
targetUrl python:view.getUrlForTarget(row)"> targetUrl python:view.getUrlForTarget(row);
selected_uids request/selection|python:[]">
<tr tal:attributes="class class"> <tr tal:attributes="class class">
<td tal:condition="item/showActions|nothing"
tal:define="uid row/uniqueId"
class="checkbox">
<input type="checkbox" name="selection:list" class="select_item"
tal:attributes="value uid;
checked python:
uid in selected_uids" /></td>
<td> <td>
<a tal:attributes="href string:$targetUrl?version=this; <a tal:attributes="href string:$targetUrl?version=this;
title description"> title description">
@ -134,6 +153,7 @@
</tbody> </tbody>
</table> </table>
</metal:results> </metal:results>
<metal:actions use-macro="item/search_macros/actions" />
</fieldset> </fieldset>
</div> </div>
@ -374,4 +394,49 @@
param not in ['type', 'text', 'concept', 'state']" />&nbsp; param not in ['type', 'text', 'concept', 'state']" />&nbsp;
</td> </td>
<div metal:define-macro="actions"
tal:condition="item/showActions">
<div id="search_actions_plus"
onclick="dojo.query('#search_actions').style('display', 'block');
dojo.query('#search_actions_plus').style('display', 'none')" >
<img src="/++resource++cybertools.icons/plus.gif" />Show Actions</div>
<div id="search_actions" style="display: none">
<h4 onclick="dojo.query('#search_actions_plus').style('display', 'block');
dojo.query('#search_actions').style('display', 'none')">
<img src="/++resource++cybertools.icons/minus.gif" />Actions for Selected Objects</h4>
<div class="buttons">
<div tal:define="stateDefs item/statesDefinitions;"
tal:condition="stateDefs">
<table>
<tr tal:repeat="def stateDefs">
<td>
<input type="submit" name="action.change_state"
value="Change state" class="submit"
tal:condition="repeat/def/start"
i18n:attributes="value" /></td>
<td valign="top"
tal:content="def/name"
i18n:translate=""></td>
<td tal:define="transitions def/transitions">
<select tal:attributes="name string:trans.${def/name}">
<option i18n:translate="" value="-">No change</option>
<option tal:repeat="trans transitions"
tal:attributes="value trans/name"
tal:content="trans/title">publish</option>
</select>
</td>
</tr>
</table><br />
</div>
<div>
<input type="submit" name="action.delete"
value="Delete objects" class="submit"
onClick="confirm('Do you really want to ... the selected objects?')"
i18n:attributes="value; onclick" /></div>
</div>
</div>
</div>
</html> </html>

View file

@ -28,6 +28,7 @@ from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.traversing.api import getName, getParent from zope.traversing.api import getName, getParent
from cybertools.browser.form import FormController
from cybertools.stateful.interfaces import IStateful, IStatesDefinition from cybertools.stateful.interfaces import IStateful, IStatesDefinition
from loops.browser.common import BaseView from loops.browser.common import BaseView
from loops.browser.node import NodeView from loops.browser.node import NodeView
@ -35,6 +36,7 @@ from loops.common import adapted, AdapterBase
from loops.expert.concept import ConceptQuery, FullQuery from loops.expert.concept import ConceptQuery, FullQuery
from loops.interfaces import IResource from loops.interfaces import IResource
from loops.organize.personal.browser.filter import FilterView from loops.organize.personal.browser.filter import FilterView
from loops.security.common import canWriteObject, checkPermission
from loops import util from loops import util
from loops.util import _ from loops.util import _
@ -45,6 +47,8 @@ search_template = ViewPageTemplateFile('search.pt')
class QuickSearchResults(NodeView): class QuickSearchResults(NodeView):
""" Provides results listing """ """ Provides results listing """
showActions = False
@Lazy @Lazy
def search_macros(self): def search_macros(self):
return self.controller.getTemplateMacros('search', search_template) return self.controller.getTemplateMacros('search', search_template)
@ -72,6 +76,7 @@ class QuickSearchResults(NodeView):
class Search(BaseView): class Search(BaseView):
form_action = 'execute_search_action'
maxRowNum = 0 maxRowNum = 0
@Lazy @Lazy
@ -82,6 +87,11 @@ class Search(BaseView):
def macro(self): def macro(self):
return self.search_macros['search'] return self.search_macros['search']
@Lazy
def showActions(self):
return checkPermission('loops.ManageSite', self.context)
#return canWriteObject(self.context)
@property @property
def rowNum(self): def rowNum(self):
""" Return the rowNum to be used for identifying the current search """ Return the rowNum to be used for identifying the current search
@ -261,9 +271,8 @@ class Search(BaseView):
return True return True
#class SearchResults(BaseView):
class SearchResults(NodeView): class SearchResults(NodeView):
""" Provides results as inner HTML """ """ Provides results as inner HTML - not used any more (?)"""
@Lazy @Lazy
def search_macros(self): def search_macros(self):
@ -315,3 +324,46 @@ class SearchResults(NodeView):
result = sorted(result, key=lambda x: x.title.lower()) result = sorted(result, key=lambda x: x.title.lower())
return self.viewIterator(result) return self.viewIterator(result)
class ActionExecutor(FormController):
def update(self):
form = self.request.form
actions = [k for k in form.keys() if k.startswith('action.')]
if actions:
action = actions[0].split('.', 1)[1]
uids = form.get('selection', [])
if uids:
method = self.actions.get(action)
if method:
method(self, uids)
return True
def delete(self, uids):
self.request.form['message'] = _(
u'The objects selected have been deleted.')
for uid in uids:
obj = util.getObjectForUid(uid)
if not canWriteObject(obj):
continue
parent = getParent(obj)
del parent[getName(obj)]
def change_state(self, uids):
stdefs = dict([(k.split('.', 1)[1], v)
for k, v in self.request.form.items()
if k.startswith('trans.') and self.request.form[k] != '-'])
if not stdefs:
return
for uid in uids:
obj = util.getObjectForUid(uid)
if not canWriteObject(obj):
continue
for stdef, trans in stdefs.items():
stf = component.getAdapter(obj, IStateful, name=stdef)
if trans in [t.name for t in stf.getAvailableTransitions()]:
stf.doTransition(trans)
self.request.form['message'] = _(
u'The state of the objects selected has been changed.')
actions = dict(delete=delete, change_state=change_state)

View file

@ -13,12 +13,6 @@
set_schema="loops.expert.concept.IQueryConcept" /> set_schema="loops.expert.concept.IQueryConcept" />
</class> </class>
<adapter name="execute_query_action"
for="loops.browser.node.NodeView
zope.publisher.interfaces.browser.IBrowserRequest"
factory="loops.expert.browser.base.ActionExecutor"
permission="zope.ManageContent" />
<adapter factory="loops.expert.setup.SetupManager" <adapter factory="loops.expert.setup.SetupManager"
name="expert" /> name="expert" />