Dexterity Container Type with Image Attribute - plone

environment: Plone 4.3.7, plone.app.contenttypes 1.1b5, eea.facetednavigation 8.7
I have a custom Dexterity Container type, Monument, that holds Image items only. My intention is to make Monument containing Image items behave just like News Item with the Image field. In case there are more than one Image items within Monument, the first one or a random one returned.
This way, I can display Monument items with their Image as thumbnails for eea.facetednavigation views.
FYI, there are 3 cases in eea.facetednavigation/views/preview-item.pt to show thumbnails:
is_namedimage python:getattr(getattr(context, 'image', None), 'getImageSize', None) is not None;
image_thumb exists:context/image_thumb;
image_tag python:getattr(context, 'tag', None)"
The example at plone.app.discussion/interfaces.py inspires me. So I try the following:
In models/monument.xml:
<schema>
...
<field name="image"
type="plone.namedfile.field.NamedBlobImage">
<title i18n:translate="">Image</title>
<readonly>True</readonly>
</field>
...
</schema>
In content.py:
#implementer(IMonument)
class Monument(Container):
"""Container Subclass for Monument
"""
#property
def image(self):
catalog = getToolByName(self, 'portal_catalog')
path = '/'.join(self.getPhysicalPath())
brain = catalog(path={"query": path}, portal_type=['Image'])
obj = brain[0].getObject()
return obj.image
But, it seems Monument item does not get image attribute accordingly. Am I moving toward the right direction? Any hints are appreciated.

Can you use the LeadImageBehavior for your Monument-Foldertype? In profiles/default/types/monument.xml add this if you need a image field.
Then you can register IObjectModifiedEvent for Monument and manipulate the imagefield in the event.
<?xml version="1.0"?>
<object name="Monument" meta_type="Dexterity FTI">
<property name="behaviors" purge="False">
<element value="plone.app.contenttypes.behaviors.leadimage.ILeadImage"/>
</property>
</object>

Related

Navigation Component set transition animation programmatically

yesterday i come across with a problem that i needed to set animation from nav_graph.xml in my baseFragment and programatically get action object from current node which includes enterAnim and exitAnim resource. Could not find solution here so here we go.
First we need to feed anim folder with our animations in res folder because its hungry.
slide_in_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="250"
android:fromXDelta="-100%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%" />
</set>
other animations you can easily found on github or stackoverflow.
Here is my nav_graph.xml fragment from which we gonna make transition
<fragment
android:id="#+id/kebabsFragment"
android:name="com.kebabkrabby.kebabapp.KebabFragment"
android:label="so many kebabs"
tools:layout="#layout/fragment_kebab">
<action
android:id="#+id/action_kebabs_to_kebab_detail"
app:destination="#id/kebabDetailFragment"
app:enterAnim="#anim/slide_in_right"
app:exitAnim="#anim/slide_out_left" />
</fragment>
now in KebabFragment.tk u gonna call baseFragment method for transition to get into detail of our desired kebab and then popFromBackStack
//navigateAndClean(actionId, cleanFragmentId)
navigateAndClean(R.id.action_kebabs_to_kebab_detail, R.id.kebabsFragment)
in our baseFragment.kt
internal fun navigateAndClean(actionId: Int, currentFragmentIdToClear: Int) {
val navBuilder = NavOptions.Builder()
val navController = Navigation.findNavController(getRootView())
val currNavigationNode = navController.graph.findNode(currentFragmentIdToClear) // NavDestination of kebabsFragment object in nav_graph.xml
val action = currNavigationNode?.getAction(actionId) // finally we get this action_kebabs_to_kebab_detail action object
action?.navOptions?.enterAnim?.let { //do we have animation or not?
navBuilder.setEnterAnim(it)
}
action?.navOptions?.exitAnim?.let {
navBuilder.setExitAnim(it)
}
navBuilder.setPopUpTo(currentFragmentIdToClear, true) //remove from backstack
navController.navigate(actionId, null, navBuilder.build())
}
Some people will ask. Hey, Mr. Kebab but how do i get getRootView()
and Mr. Kebab will look at u and say "buddy, look at this world, together we can achieve big things"
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(mContentLayoutResourceId, container, false)
return rootView
}
fun getRootView(): View {
return rootView
}
Durum kebab. Enjoy.
Navigation components provides built in animation options for entry and exit transitions, a sample code block is attached below for reference
Code block to add animations within java/kotlin
navigate(
navController, resId, bundle,
NavOptions.Builder()
.setPopUpTo(R.id.splashFragment, true)
.setEnterAnim(R.anim.fade_in)
.setExitAnim(R.anim.fade_out)
.setPopEnterAnim(R.anim.fade_in)
.setPopExitAnim(R.anim.fade_out)
.build()
)
Code block for adding animation in xml file
<fragment
android:id="#+id/kebabsFragment"
android:name="com.kebabkrabby.kebabapp.KebabFragment"
android:label="so many kebabs"
tools:layout="#layout/fragment_kebab">
<action
android:id="#+id/confirmationAction"
app:destination="#id/confirmationFragment"
app:enterAnim="#anim/slide_in_right"
app:exitAnim="#anim/slide_out_left"
app:popEnterAnim="#anim/slide_in_left"
app:popExitAnim="#anim/slide_out_right" />
</fragment>

React-big-calendar with bootstrap 4.0 alpha layout ugly

I am using bootstrap 4.0 alpha with no other styles. The layout is very ugly that, the calendar shows only a single column instead of a table. Any idea of why and how?
I notice the following from the website, but I don't understand what should I do:
note: The default styles use height: 100% which means your container must set an explicit height (feel free to adjust the styles to suit your specific needs).
This is my rendering code:
render() {
return (
<div className="container">
<TaskSearchBar
search={this.onSearch}
/>
<BigCalendar
selectable
events={[]}
defaultView='week'
scrollToTime={new Date(1970, 1, 1, 6)}
defaultDate={new Date(2015, 3, 12)}
onSelectEvent={event => alert(event.title)}
onSelectSlot={(slotInfo) => alert(
`selected slot: \n\nstart ${slotInfo.start.toLocaleString()} ` +
`\nend: ${slotInfo.end.toLocaleString()}`
)}
/>
<TaskList
queryUrl={this.state.queryUrl}
/>
</div>
);
}
This is the layout result
I found I missed this line:
require('react-big-calendar/lib/css/react-big-calendar.css');
Thanks to enter link description here
In case you still run into any issues, that snippet you copied says that the element containing BigCalendar needs to have a specific height set on it, like 420px or 60%. That'll keep the flexbox algorithm from greedily eating space. If you don't do that, you'll find that the day view renders every single hour at once, rather than providing a scrollable window.

Customize TinyMCE for an Dexterity RichWidget

I'm creating some custom content types using dexterity. I would like to "customize" the aspect of a RichText Field allowing only basic buttons of TinyMce on this field.
In Archetypes I could use
TextField('text',
allowable_content_types=('text/html',),
default_output_type='text/x-html-safe',
required=1,
widget=RichWidget
(label='Content',
allow_buttons=(
'bold',
'italic',
'justifyleft',
'justifyright',
),
),),
How would I do this with Dexerity based contenttypes?
There doesn't appear to be a "nice" way to do this right now. Even the Plone docs are currently at a loss. http://docs.plone.org/develop/plone/forms/wysiwyg.html#id9
The problem lies with Products.TinyMCE trying to get the WYSIWYG configuration from the widget attribute of the Field.
https://github.com/plone/Products.TinyMCE/blob/1.3.6/Products/TinyMCE/utility.py#L711-L713
# Get widget attributes
widget = getattr(field, 'widget', None)
filter_buttons = getattr(widget, 'filter_buttons', None)
allow_buttons = getattr(widget, 'allow_buttons', None)
But, as I understand, with Dexterity we instead map fields to widgets on the form object.
from plone.autoform import directives as form
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
class IExample(model.schema):
form.widget('body', WysiwygFieldWidget)
body = schema.Text(title=u"Body")
So, our body field possesses no widget attribute from which Products.TinyMCE can extract configurations.
At any rate, if you need it to work right now, I was able to hack it by doing the following:
In your ZMI, customize portal_skins/tinymce/tinymce_wysiwyg_support to change the line field field|nothing to field field|view/field|nothing.
Define your content type in a schema-driven fashion, and for your WYSIWYG field do the following:
class mywidg(object):
allow_buttons = ('bold',
'italic',
'justifyright',
'justifyleft',)
class IExample(model.schema):
form.widget('body', WysiwygFieldWidget)
body = schema.Text(title=u"Body")
body.widget = mywidg()

tabbedBar, showing different views titanium

Here is my code for tabbed bar:
<Alloy>
<Window class="container">
<Label id="label" onClick="doClick">Hello, World</Label>
<TabbedBar id="bb1" platform="ios" backgroundColor="#369" top="50" height="25" width="200">
<!-- The Labels tag sets the TabbedBar.labels property. -->
<Labels>
<!-- Specify text with node text or the title attribute. -->
<!-- Can also specify the enabled, image and width attributes. -->
<Label>One</Label>
<Label>Two</Label>
<Label>Three</Label>
</Labels>
<!-- Place additional views for the TabbedBar here. -->
<Views>
<View backgroundColor='red'>1</View>
<View>2</View>
<View><Label>Does this work!</Label></View>
</Views>
</TabbedBar>
</Window>
</Alloy>
When I click on a tab, how can I make sure that the view corresponds to the button pressed - I know how to do this in titanium but not alloy.
Cheers.
I had the same problem yesterday. I'm sure there must be a better way but I couldn't see anything in the documentation, this was my solution:
var animation = require('alloy/animation');
var previousIndex = $.tabbedBar.getIndex();
$.tabbedBar.addEventListener('click', function(){
var currentIndex = $.tabbedBar.getIndex();
var viewArr = [];
viewArr[0] = $.view1;
viewArr[1] = $.view2;
viewArr[2] = $.view3;
animation.crossFade(viewArr[previousIndex], viewArr[currentIndex], 700)
previousIndex = currentIndex;
});
EDIT:
(In case you don't know, on Android there's a module to give you similar functionality: https://github.com/ricardoalcocer/viewpager but check issue #5 on the original repo as you'll have to incorporate that into any build. On the Android version, you don't need to handle the clicks yourself.)

in flex my button appears in the line below a formitem

in flex my button appears in the line below a formitem. is there any other way of adding in a button so that it will appear on the same level as the rest of the formitem? There does not seem to be a button property on the formitem code. Attached is an example of a formitem and the code for a button underneath. Any suggestions most welcome, thank you.
<ch:FormItem label="Gym Dosier Type:" >
<pss:dossierFinder id="gymOriginFinder" displayLabel="true"
allowMultipleSelection="false"
autoContactServer="true"
initialAccountClass="{AccountClassConstants.gym}"
accountClassEnabled="false"
initialMultigym="{gymInterdossierchinder.model.selectedItem.code}"
initialgymsource="{gymsource.model.selectedItem.internalCode}"/>
<mx:Button id = "addLineButton" icon="{addIcon}" toolTip="Add new gym member" click="{addPack(event)}" enabled="true"/>
</ch:FormItem>
I am not clear if the <ch:FormItem/> is your own separate component or just extends mx:FormItem, but in latter case, uou can set the direction parameter of the FormItem component to horizontal.

Resources