add custom content tree to navigate in pfwbged folders

This commit is contained in:
Frédéric Péters 2014-02-09 14:16:16 +01:00
parent 1e9751e431
commit 3b319974db
4 changed files with 185 additions and 8 deletions

View File

@ -56,4 +56,11 @@
editview=".portlet.EditForm"
/>
<browser:page
name="foldertree-fetch"
for="plone.formwidget.contenttree.interfaces.IContentTreeWidget"
permission="zope.Public"
class=".link.Fetch"
/>
</configure>

View File

@ -92,7 +92,7 @@ class Folder(Container):
parents.append(item.folder.to_object)
return parents
def child_folders(self):
def child_folders_brains(self):
intids = component.getUtility(IIntIds)
intid_catalog = component.getUtility(ICatalog)
try:
@ -118,9 +118,13 @@ class Folder(Container):
uuids.append(IUUID(document))
portal_catalog = api.portal.get_tool('portal_catalog')
children = portal_catalog.searchResults({'UID': uuids})
return portal_catalog.searchResults({'UID': uuids})
return [IContentListingObject(x) for x in children]
def child_folders(self):
return [IContentListingObject(x) for x in self.child_folders_brains()]
def child_folders_objects(self):
return [x.getObject() for x in self.child_folders_brains()]
def intid(self):
intids = component.getUtility(IIntIds)

View File

@ -0,0 +1,29 @@
<tal:master define="level options/level|python:0; children options/children | nothing;">
<tal:navitem repeat="node children">
<li tal:define="show_children node/show_children;
children node/children;
item_url node/getURL;
item_token node/getPath;
selectable node/selectable;
li_folder_class python:show_children and ' navTreeFolderish' or '';
li_selectable_class python:selectable and ' selectable' or '';
li_collapsed_class python:(len(children) > 0 and show_children) and ' expanded' or ' collapsed';
li_class string:${li_folder_class}${li_selectable_class}${li_collapsed_class}"
tal:attributes="class string:navTreeItem visualNoMarker${li_class}">
<tal:level define="item_class string:contenttype-${node/portal_type}">
<tal:block define="item_class item_class">
<a tal:attributes="href item_token; rel level;
title node/Description;
class string:$item_class">
<img width="16" height="16" src="++resource++pfwbgedfolder_icon.png" alt=""/>
<span tal:content="node/Title">Selected Item Title</span>
</a>
</tal:block>
<ul tal:attributes="class python:'navTree navTreeLevel'+str(level)"
tal:condition="python: len(children) > 0 and show_children">
<span tal:replace="structure python:view.recurse_template(children=children, level=level+1)" />
</ul>
</tal:level>
</li>
</tal:navitem>
</tal:master>

View File

@ -1,9 +1,14 @@
from AccessControl import getSecurityManager
from zope.interface import Interface, implements, implementer
from zope.cachedescriptors.property import CachedProperty
from zope.component import getMultiAdapter, getUtility
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.utils import base_hasattr
from five import grok
from plone.directives import form
from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile
from plone.dexterity.content import Item
from plone.supermodel import model
@ -12,24 +17,156 @@ from plone.formwidget.contenttree import ObjPathSourceBinder
from plone import api
from z3c.relationfield.schema import RelationChoice
from plone.app.contentlisting.realobject import RealContentListingObject
from . import _
from plone.formwidget.contenttree.widget import ContentTreeWidget
from plone.app.layout.navigation.interfaces import INavtreeStrategy
from plone.formwidget.contenttree.utils import closest_content
import plone.formwidget.contenttree.widget
import z3c.form.widget
from zc.relation.interfaces import ICatalog
from zope.app.intid.interfaces import IIntIds
class FolderListingObject(RealContentListingObject):
children = []
selectable = True
show_children = True
def intid(self):
intids = getUtility(IIntIds)
intid_catalog = getUtility(ICatalog)
intid = intids.getId(self.getObject())
return intid
class Fetch(plone.formwidget.contenttree.widget.Fetch):
recurse_template = ViewPageTemplateFile('input_recurse.pt')
def __call__(self):
# We want to check that the user was indeed allowed to access the
# form for this widget. We can only this now, since security isn't
# applied yet during traversal.
self.validate_access()
widget = self.context
context = widget.context
# Update the widget before accessing the source.
# The source was only bound without security applied
# during traversal before.
widget.update()
source = widget.bound_source
# Convert token from request to the path to the object
token = self.request.form.get('href', None)
level = self.request.form.get('rel', 0)
children = []
if level == '0':
current_user = api.user.get_current()
current_user_id = current_user.getId()
members_folder = getattr(api.portal.get(), 'Members')
if base_hasattr(members_folder, current_user_id):
folder = members_folder[current_user_id]
children.append(FolderListingObject(folder))
children[-1].Title = _('Home Folder')
dossiers_folder = getattr(api.portal.get(), 'dossiers')
for group in api.group.get_groups(user=current_user):
if base_hasattr(dossiers_folder, group.id):
folder = dossiers_folder[group.id]
children.append(FolderListingObject(folder))
else:
parent_folder = api.portal.get().restrictedTraverse(str(token))
for folder in parent_folder.child_folders_objects():
children.append(FolderListingObject(folder))
self.request.response.setHeader('X-Theme-Disabled', 'True')
if not children:
return ''
return self.fragment_template(children=children, level=int(level))
class ContentTreeWidget(plone.formwidget.contenttree.widget.ContentTreeWidget):
show_all_content_types = False
def js_extra(self):
# this is copied from parent class, the only difference is the URL
# used for Ajax requests.
source = self.bound_source
form_url = self.request.getURL()
url = "%s/++widget++%s/@@foldertree-fetch" % (form_url, self.name)
return """\
$('#%(id)s-widgets-query').each(function() {
if($(this).siblings('input.searchButton').length > 0) { return; }
$(document.createElement('input'))
.attr({
'type': 'button',
'value': '%(button_val)s'
})
.addClass('searchButton')
.click( function () {
var parent = $(this).parents("*[id$='-autocomplete']")
var window = parent.siblings("*[id$='-contenttree-window']")
window.showDialog('%(url)s', %(expandSpeed)d);
$('#' + parent.attr('id').replace('autocomplete', 'contenttree')).contentTree(
{
script: '%(url)s',
folderEvent: '%(folderEvent)s',
selectEvent: '%(selectEvent)s',
expandSpeed: %(expandSpeed)d,
collapseSpeed: %(collapseSpeed)s,
multiFolder: %(multiFolder)s,
multiSelect: %(multiSelect)s,
rootUrl: '%(rootUrl)s'
},
function(event, selected, data, title) {
// alert(event + ', ' + selected + ', ' + data + ', ' + title);
}
);
}).insertAfter($(this));
});
$('#%(id)s-contenttree-window').find('.contentTreeAdd').unbind('click').click(function () {
$(this).contentTreeAdd();
});
$('#%(id)s-contenttree-window').find('.contentTreeCancel').unbind('click').click(function () {
$(this).contentTreeCancel();
});
$('#%(id)s-widgets-query').after(" ");
""" % dict(url=url,
id=self.name.replace('.', '-'),
folderEvent=self.folderEvent,
selectEvent=self.selectEvent,
expandSpeed=self.expandSpeed,
collapseSpeed=self.collapseSpeed,
multiFolder=str(self.multiFolder).lower(),
multiSelect=str(self.multi_select).lower(),
rootUrl=source.navigation_tree_query['path']['query'],
name=self.name,
klass=self.klass,
title=self.title,
button_val=_(u'Browse...'))
@implementer(z3c.form.interfaces.IFieldWidget)
def ContentTreeFieldWidget(field, request):
tree_widget = ContentTreeWidget(request)
tree_widget.show_all_content_types = False
return z3c.form.widget.FieldWidget(field, tree_widget)
return z3c.form.widget.FieldWidget(field, ContentTreeWidget(request))
class ILink(model.Schema):
""" """
folder = RelationChoice(title=_(u'Folder'), required=True,
source=ObjPathSourceBinder(
navigation_tree_query={'portal_type': ('Folder', 'pfwbgedfolder',)}))
navigation_tree_query={'portal_type': ('pfwbgedfolder',)}))
form.widget(folder=ContentTreeFieldWidget)