Overriding another product's view template in Plone - plone

I am using Plone 4.1.2 and I am trying to override a view template provided by collective.contenleadimage. It is easy to edit the provided template via portal_view_customization but I want to try doing it from my policy product in the filesystem.
I would like to replace the folder_leadimage_view of c.contentleadimage.
This is what I have done in my policy product.
in interfaces.py
from zope.interface import Interface
class IExamplePolicy(Interface):
"""Marker interface that defines a Zope 3 browser layer.
"""
in profiles/default/browserlayer.xml
<?xml version="1.0"?>
<layers>
<layer name="example.policy"
interface="example.policy.interfaces.IExamplePolicy" />
</layers>
in browser/configure.zcml
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:i18n="http://namespaces.zope.org/i18n"
xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="example.policy">
<browser:page
for="Products.Archetypes.interfaces.IBaseFolder"
name="folder_leadimage_view"
class="collective.contentleadimage.browser.folder_leadimage_view.FolderLeadImageView"
template="folder_leadimage_view.pt"
layer="..interfaces.IExamplePolicy"
permission="zope2.View"
allowed_attributes="tag"
/>
<browser:page
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
name="folder_leadimage_view"
class="collective.contentleadimage.browser.folder_leadimage_view.FolderLeadImageView"
template="folder_leadimage_view.pt"
layer="..interfaces.IExamplePolicy"
permission="zope2.View"
/>
My policy product installs fine and I can see in portal_view_customization
Products.Archetypes.interfaces.base.IBaseFolder
folder_leadimage_view (example.policy.interfaces.IExamplePolicy)
folder_leadimage_view (collective.contentleadimage.interfaces.ILeadImageSpecific)
However, my new template is not the one rendered by Plone.
I would appreciate the assistance.

Change your interfaces.py to:
from collective.contentleadimage.interfaces import ILeadImageSpecific
class IExamplePolicy(ILeadImageSpecific):
"""Marker interface that overrides collective.contentleadimage's
browser layer.
"""
Browser layers are markers applied to the request. Both your IExamplePolicy and collective.contentleadimage's ILeadImageSpecific browser layers are applied, but by inheriting from ILeadImageSpecific for your browser layer you make your overridden folder_leadimage_view view more specific than collective.contentleadimage's own.
For more information on Zope Component Architecture interface resolution order see the "Customisation with more-specific adapters" section in the Dexterity manual.

Related

How can I add a custom Page to Alfresco share that copies the the look/feel of Alfresco Share?

Link to Project: https://github.com/raystorm/Alfresco-Smalgyax
I am trying to:
Upload Documents into Alfresco/Share
Set a custom Document Type
Set Metadata
Use a Form that matches the Look/Feel of Alfresco/Share
I have Added a menu Item to the Create... menu.
The link points to the create-content Page. I was unable to upload the the file with that page. I set a custom file input field, but could not upload the file. I was unable to get a custom form template to work.
I have now switched tactics.
I have a custom share service that can:
Upload the file
Set Document Type
Set Metadata.
Bare-bones HTML page. Note: Does not match the Alfresco/Share look/feel.
How can I set the Share service page template to actually look like the create-content page?
UPDATE
I reset the get page to match the hello-world template.
the first line of the file:
<#include "/org/alfresco/include/alfresco-template.ftl" />
threw the following error:
smalgyax-share_1 | Caused by: freemarker.template.TemplateNotFoundException: Template not found for name "org/alfresco/include/alfresco-template.ftl".
smalgyax-share_1 | The name was interpreted by this TemplateLoader: MultiTemplateLoader(loader1 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#3471b524, loader2 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#e944270, loader3 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#4a121f1c, loader4 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#6aa5340e, loader5 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#53c474eb, loader6 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#7fef2b21, loader7 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#255f313f, loader8 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#661974de, loader9 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#168a37da, loader10 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#103ab009, loader11 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#4c30bdf8, loader12 = org.springframework.extensions.webscripts.ClassPathStore$ClassPathTemplateLoader#61228f24).
The error occurs from both
service: http//:localhost:8180/share/service/hayts
and
Page: http://localhost:8180/share/page/upload-smalgyax-document
I have downloaded your source code and customized the share project and added a custom share page, it works perfectly for me without any issues.
Your project doesn't have the required css files that's the reason it doesn't looks like as like other alfresco pages.
Please follow the below project in github it will work, let me know if you face any issues.
https://github.com/Alfresco/alfresco-sdk-samples/tree/alfresco-51/all-in-one/add-surf-dashlet-and-page-share
Update:
UPDATE:
Please add a entry in share-config-custom.xml and change the name from hayts.xml to helloworldhome.xml under /site-data/pages.
<config evaluator="string-compare" condition="SitePages">
<pages>
<page id="helloworldhome">helloworldhome</page>
</pages>
</config>
You can place below line in share-config-custom.xml or you can create share extension module.
Change item id as per your custom type instead of cm:content.
You custom type form control should be properly configured in share-config-custom.xml.
<config evaluator="string-compare" condition="DocumentLibrary">
<create-content>
<content id="acme-plain-text" label="Custom Menu" icon="text" type="pagelink">
<param name="page">create-content?destination={nodeRef}&itemId=cm:content&mimeType=text/plain</param>
</content>
</create-content>
</config>

How to customize the CSS of a theme generated with the ThemeBuilder?

I have used the ThemeBuilder to create a theme, but now I need to add an attribute in a CSS class so I can have a different font color in the selected element of a ListView, for example.
Ideally I would expect that the builder have support for specifying such a configuration in the .theme file, specially because font color is something that will not affect the image generation process that is used to support older browsers. In fact the builder should have support for all standard CSS3 attributes that don't affect the generated images.
Obviously it is possible to modify the ThemeBuilder jar to achieve this, but this is not a good idea.
I had a look in the appearance classes that are generated and my first try was to use the following constructor:
public Css3ContentPanelAppearance(Css3ContentPanelResources resources) {
this(resources, GWT.<Css3ContentPanelTemplate> create(Css3ContentPanelTemplate.class));
}
This did not work well, because all components using Css3ContentPanelAppearance are affected regardless of which Css3ContentPanelResources was used. I believe this happens because the CSS class name is based on the appearance class name and on the CssResource class name.
The solution was very simple: create a sub-class of the generated appearance class like this:
public class CustomCss3ListViewAppearance extends Css3ListViewAppearance {
public interface CustomCss3ListViewResources extends Css3ListViewAppearance.Css3ListViewResources {
// Load the original resources first and then the custom one, so the customizations will take precedence.
#ClientBundle.Source({"com/example/client/base/listview/Css3ListView.css","CustomCss3ListView.css"})
#Override
Css3ListViewAppearance.Css3ListViewStyle css();
}
public CustomCss3ListViewAppearance() {
super(GWT.<Css3ListViewAppearance.Css3ListViewResources>create(CustomCss3ListViewResources.class));
}
}
Then, you can create a separate JAR module that depends on the generated theme, specify some bindings in the .gwt.xml file and it will behave exactly as a plain generated theme (just need to add a dependency and import it in the application .gwt.xml file):
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='myCustomTheme'>
<inherits name="com.example.Theme"/>
<replace-with class="com.example.client.base.listview.CustomCss3ListViewAppearance">
<when-type-is class="com.sencha.gxt.widget.core.client.ListView.ListViewAppearance" />
<when-property-is name="gxt.theme" value="myTheme" />
</replace-with>
<source path="myCustomTheme/client"/>
</module>

EEA Faceted Navigation - How to create a new widget in our own product

I created a new widget 'Slider' for EEA Faceted Navigation.
It works fine but I made these changes directly in the original products.
For details, I added a new folder in eea/facetednavigation/widgets and modified eea/facetednavigation/widgets/configure.zcml.
I would like to move this new widget in my own product.
I've created some files and folder:
my/product/widgets
my/product/widgets/slider
my/product/widgets/configure.zcml
and included my new package 'widgets' in the root zcml.
But it doesn't work:
Module eea.facetednavigation.browser.app.view, line 89, in get_sections
Module eea.facetednavigation.browser.app.view, line 96, in get_view_widgets
Module eea.facetednavigation.browser.app.view, line 111, in get_widgets
TypeError: 'NoneType' object is not callable
Is there a way to do this?
I'm looking at https://github.com/eea/eea.facetednavigation since I don't know what version you have.
It looks like that <facet:widget /> directive (I assume you have in your my/products/widgets/configure.zcml file) attaches the widget to the widget registry class. They register all of their widgets, then instantiate the registry as a utility.
So, try re-instantiating that class by adding an overrides.zcml to your product at
my/product/overrides.zcml
with the following
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser">
<configure package="eea.facetednavigation">
<utility provides=".interfaces.IWidgetsInfo"
factory=".widgets.WidgetsInfo" />
</configure>
</configure>
You don't have to re-instantiate IWidgetsInfo :)
All you have to do is to register your widget:
<faceted:widget factory=".widget.Widget" />
See this faceted widget registered outside eea.facetednavigation namespace:
https://svn.eionet.europa.eu/repositories/Zope/trunk/eea.dataservice/trunk/eea/dataservice/facetednavigation/lastversion/configure.zcml
https://svn.eionet.europa.eu/repositories/Zope/trunk/eea.dataservice/trunk/eea/dataservice/facetednavigation/lastversion/

Plone: Shown default views on navtree

My question is quite simple....
In Plone 4 (4.2) what I need to setup to make a default view, for example a simple page, to be shown in the navigation tree.
The navigation tree uses the INavigationQueryBuilder component to find all elements shown. The default implementation filters out anything used as a default page.
You'll have to provide your own implementation instead; but you can re-use the original implementation. All you have to do is alter the generated query a little; normally, if no more specific query is present, the is_default_page index is used to filter out default pages. But if your altered query adds a search for that index, then it'll not try to add a more specific filter. Setting it to search for (True, False) means it'll return both default and non-default pages, effectively neutralizing the filter.
The implementation then becomes:
from plone.app.portlets.portlets.navigation import QueryBuilder, INavigationPortlet
from zope.component import adapts
from zope.interface import implements, Interface
class INonDefaultPageFilteringNavigationPortlet(INavigationPortlet):
pass
class DontFilterDefaultQueryBuilder(QueryBuilder):
implements(INavigationQueryBuilder)
adapts(Interface, INavigationPortlet)
def __init__(self, context, portlet):
super(DontFilterDefaultQueryBuilder, self).__init__(context, portlet)
self.query['is_default_page'] = (True, False) # Don't filter out default pages
You'll have to register this as an adapter, and add the INonDefaultPageFilteringNavigationPortlet to your portlet to 'activate' this builder:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five">
<adapter factory=".yourmodule.DontFilterDefaultQueryBuilder" />
<five:implements
class="plone.app.portlets.portlets.navigation.Assignment"
interface=".yourmodule.INonDefaultPageFilteringNavigationPortlet" />
</configure>
All with the caveat that this is untested, but it should work.
You might also create a link in the folder, set destination to './idOfPage1' and set the link as defaultview of the folder.
Users without editing-rights will be redirected to Page1 then and the page itself will be shown in the navportlet.

What are the rules plone works with to decide which menus to display, and when?

I'm using Plone 4.0.5, and I've spent the day trying to understand plone.app.contentmenu.
I have a custom folder based archetypes type, and I've written a view for it. When using the default base_view (site/MyObject/base_view), everything works as expected. Using my own custom view though, the menus start disappearing, and I haven't been able to figure it out.
First, my zcml,
<browser:page
for="my.product.interfaces.IMyType"
name="view"
class="my.product.browser.mytype.MyTypeViewView"
permission="zope.Public"
/>
The view itself is as simple as possible:
class MyTypeViewView(BrowserView):
template = ViewPageTemplateFile("templates/mytype_view.pt")
def __call__(self):
return self.template()
And the view template has also been slimmed down to nothing:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="context/main_template/macros/master"
i18n:domain="plone">
<body>
<metal:content-core fill-slot="content-core">
hi there.
</metal:content-core>
</body>
</html>
If I access site/MyObject/view, the template shows "hi there", but plone-contentmenu-actions and plone-contentmenu-workflow disappear. plone-contentmenu-factories however, remains. if I then modify the ZCML to set name="view_test", and visit site/MyObject/view_test, none of the menus at all display.
I have five different views for this type, and I want the workflow menu to display on all of them (or at the very least, my main view, so that I can test more easily until I figure it out).
If I rename my view to base_view and visit the object URL directly, I still don't have a workflow menu available.
I guess my question should be:
What exactly are the rules plone works with to decide which menus to display, and when? What code should I be reading?
-- edit:
I've added this function to my View:
def __init__(self, context, request):
super(MyTypeViewView, self).__init__(context, request)
alsoProvides(self, IViewView)
alsoProvides(self.context, IViewView)
if I place a breakpoint in my call code, I get this:
>>> IViewView.providedBy(self)
True
>>> IViewView.providedBy(self.context)
True
I'm pretty sure I only needed to apply IViewView to the view itself, but regardless, this doesn't change anything for me.
Plone applied the IViewView marker interface to the view which are canonical for an object - the one you get clicking the view tab. Certain parts of the interface are restricted to that interface - see the section "Restricting a viewlet to the canonical view" in http://plone.org/products/dexterity/documentation/manual/five.grok/browser-components/viewlets
Since you already have a view Class (MyTypeViewView) for your page it's more straight-forward to make it implement the interface instead of make instances of it provide it:
from plone.app.layout.globals.interfaces import IViewView
class MyTypeViewView(BrowserView):
interface.implements(IViewView)
...
Although I think that this won't solve your problem since I do have lots of custom views that do not implement IViewView but display all actions nicely.
I guess you simply need to add your views to the available default views for your type in portal_types tool and you're fine.

Resources