add custom content tree to navigate in pfwbged folders
This commit is contained in:
parent
1e9751e431
commit
3b319974db
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
|
@ -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)
|
||||
|
||||
|
|
Reference in New Issue