April
Apr 24, 2010
Cool as Cooliris
Come inserire una galleria fotografica in Plone dalla spiaggia sorseggiando un drink
Cooliris ti permette di ottenere info da una risorsa multimediale web e di creare da queste una galleria fotografica estremamente attraente. Cooliris è stato pensato per le fonti più famose (flickr, youtube, picasa e facebook). In generale però ti permette di utilizzare un media rss generico.
Non è un tool plone, non è fortemente integrato, è tutto bellamente esterno. Se ne occupa qualcun altro a farlo funzionare. ahhh, relax.
Ma perchè ci interessa in ambito Plone?
Plone può essere utilizzato come portale, come blog, come intranet ecc. chiaramente inserire una galleria Cooliris vien comodo.
Questo blog è ovviamente realizzato in plone (what else? :) ed è stato banale inserire la gallery qui sopra. Ho semplicemente utilizzato il sistema Express di Cooliris e generato quello che loro chiamano "wall". Poi l'ho incluso in questo post.
D'altro canto, Plone è anche un generatore di contenuti.
Tutti sappiamo che possiamo inserire immagini in un portale plone, ma anche inserirle all'interno di una news o anche creare tipi ad-hoc che le prevedano.
Chiaramente anche eventuali video possono essere gestiti, così come (ad esempio se si utilizza redturtle.video) ottenere riferimenti a contenuti che sono su youtube.
Vien facile quindi pensare che, con un po' di programmazione, si possa dire a plone di generare, magari a partire da una collezione, un media rss che cooliris possa lavorare per noi. Un po' come si fa per il classico rss della collezione stessa.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"
xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<item>
<title>Picture A</title>
<media:description> This one's my favorite.</media:description>
<link>pl_images/A.jpg</link>
<media:thumbnail url="http://example.com/pl_thumbs/A.jpg"/>
<media:content url="http://example.com/pl_images/A.jpg"/>
</item>
<item>
<title>Video B</title>
<link>http://example.com/pl_images/B.jpg</link>
<media:thumbnail url="http://example.com/pl_thumbs/B.jpg"/>
<media:content type="video/x-flv"
url="http://example.com/pl_images/B.flv"/>
</item>
</channel>
</rss>
In questo modo puoi:
- avere contenuti "social" aggregati in qualche modo sul tuo portale
- avere contenuti del tuo portale che diventano "social" via i media rss
- avere i tuoi contenuti in una gallery "cool" nel tuo stesso portale (o in altri che tu stesso gestisci)
In aggiunta al servizio Express hai anche a disposizione un po' di API (se non hai delle API non sei nessuno :) e scegliere se utilzzare javascript o flash per realizzare la tua gallery. Chiaramente non è un lavoro per comuni mortali, serve sempre almeno tuo cugino, quello che sa di internet, o forse magari un bravo professionista :D
Tutto facile, tutto già pronto?
Un buon uomo di marketing ti direbbe: "thatì's all folks! enjoy"
Per vostra fortuna non sono ancora passato al lato oscuro della forza. Mi piace, quindi, ricordarvi che, per un sacco di buone ragioni, il buon Plone non ti permette di inserire tag object all'interno del corpo della pagina.
Niente di devastate comunque, occorre che vi ricordiate di abilitarlo esplicitamente. E il nostro amico Sam Knox ci ricorda come.
Chiaramente questo settaggio farà sì che ogni utente (si tutti, anche quello cui stai pensando e che fa sempre dei danni) abilitato sul vostro portale o blog Plone potrà effettuare questa operazione. Be careful :)
L'altro punto da tenere in considerazione è proprio il fatto che si tratta di un sistema esterno, che non controllo, che ha le sue politiche, che da un giorno all'altro potrebbe variarle.
Ma anche questo è questo il web 2.0, no? Occorre conoscere, pensare e valutare se un tool fa al caso nostro o meno. Una volta fatto, si vive tranquilli.
Document Actions
Apr 22, 2010
Il World Plone day secondo RedTurtle
Come tutti gli anni, ma diverso da sempre: RedTurtle sventola la bandiera plone su due fronti chiave
A rischio di strafare, quest'anno noi di Redturtle abbiamo provato a fare le cose in grande. Il bello è che ci pare di esserci riusciti, e le vostre gradite adesioni agli eventi programmati, entrambi con iscrizione online, ce lo stanno già confermando.
- abbiamo guidato AUSL Ferrara a organizzare un evento unico nel suo genere (e, si spera, destinato a ripetersi ogni anno): il primo World Plone Day di PloneGov Italia, organizzato da AUSL Ferrara a nome e per conto dell'intera community www.plonegov.it. Evento a molte facce, con alcuni dei nostri più quotati Clienti (AUSL Ferrara, appunto, ma anche la locale Azienda Ospedaliera, il Comune, la Provincia, la Camera di Commercio, l'Università: tutti Enti che ci onoriamo di annoverare tra i nostri Clienti, come anche la Regione Emilia Romagna e, da Genova, Ospedali Galliera Genova). A legare queste esperienze, oltre a Plone, l'afferenza al mondo sanitario e in generale a PloneGov.
- abbiamo collocato nella data del World Plone day la tappa milanese del nostro Contént Tour, il seminario itinerante sul software libero e sul nostro CMS preferito, che rivolgiamo alle aziende e agli Enti Locali: la tappa sarà ospitata allo UNA Hotel Century di Milano, iscrizioni online sul sito del Contént Tour.
Ci riproponiamo di rendere sistematico questo modo di celebrare il WPD: il crescente successo nel settore Pubblica Amministrazione ci consentirà di portare avanti in parallelo, anche a costo di correre, un evento di taglio più celebrativo, in cui chi già conosce e usa Plone può alzare un altro piano su già solide fondamenta, e uno di taglio più evangelico.
Contiamo sul vostro aiuto per un'ulteriore crescita: conosciamoci, conosciamo Plone!
Document Actions
Apr 13, 2010
GDIP: Integration of Google Docs services in Plone
Packages for integration of Google Docs services in Plone were released on pypi and on plone.org
The purpose of GDIP is to provide the Google Docs services to Plone users.
-
Plone users can save their files on Google servers, instead of in the ZODB;
-
Plone users have multiple access points to your files: they can manage their documents using two systems: Plone and Google Docs;
-
Plone users can edit their documents directly from the Google Docs application, embedding that page in the current window of the Plone application;
The products collective.googleauthentication, collective.googlesystemstorage, collective.googlesharing and collective.googlemodifycontent provide the integration of Google Docs services in Plone.
Packages were released on pypi:
http://pypi.python.org/pypi/collective.googleauthentication
http://pypi.python.org/pypi/collective.googlesystemstorage
http://pypi.python.org/pypi/collective.googlesharing
http://pypi.python.org/pypi/collective.googlemodifycontent
and on plone.org:
http://plone.org/products/collective.googleauthentication
http://plone.org/products/collective.googlesystemstorage
http://plone.org/products/collective.googlesharing
http://plone.org/products/collective.googlemodifycontent
The system integrates Google Docs services in Plone using the gdata-python library provided by Google, which in turn uses the Google API.
GOOGLE AUTHENTICATION collective.googleauthentication
To let the Plone application access the documents stored on Google servers, it is necessary to complete the authentication procedure for Web applications provided by Google Docs. The procedure allows Web applications to authenticate users through their Google accounts. For security reasons, the application acquires an authentication token which will later be used to dowload or upload documents from Google servers without explicitly providing the user's credentials. The Plone user is redirected to a Google page that invites him to insert his credentials. Once he logs in with his Google account, the user is asked to authorize the Plone application to access his documents. Then, if the user grants access, he is pointed again to the Plone site. The URL of the last redirection embeds the authentication token which, as mentioned above, allows the Plone application to access the user's documents on Google servers for the following requests. GA inititates the authentication procedure upon Google Docs immediately after the user has logged into the Plone application. The procedure will be executed just once, as when the Plone application obtains the authentication token, it will store as an attribute, google_token, in the user profile.
GOOGLE SYSTEM STORAGE collective.googlesystemstorage
GSS
saves the document types supported by the Google Docs service on the
Google servers, while storing all the other files in the local
filesystem, so that Plone users to access their files from both the
Plone application and their Google Docs account. GSS extends FSS
through a meta ZCML directive
will trigger the adoption of GSS as storage.
GSS provides several utility methods: a method that takes an
authentication token and returns a client for Google Docs, methods
that take care of uploading, downloading and deleting the documents
on Google servers, and a method that performs queries on documents
stored on Google servers.
GOOGLE SHARING collective.googlesharing
GS manages the sharing of documents stored in the Google servers and their synchronization from the Plone application to Google Docs service. In this way, when a Plone user changes the roles of other users on a specific document, GS changes the document sharing attributes in the Google Docs service accordingly. So, if a Plone user assigns another user the Editor role on one of his documents, the other user will be able to read and modify that document through his Google account. To associate Plone and Google accounts, the system assumes that the email address attribute of Plone users corresponds to their Google account. The sharing attributes of documents stored in Google servers is managed through the feed access control list (ACL), a list that shows the Google users that have access to a specific resource. GS redefines the googlesharing view to perform the mapping of roles and the ACL feed retrieval and changing operations.
GOOGLE MODIFY CONTENT collective.googlemodifycontent
GMC extends the Plone content Edit function by adding the GoogleModify operation, which only applies to documents stored on Google servers. GMC embeds the Google Docs application inside the GoogleModify panel, allowing Plone users to edit their documents directly from the Google Docs application. GMC provides the new googlemodifycontent view, that takes care of discovering the specific URL of the Google Docs document function and of embedding that page in the current window of the Plone application.
One idea for improving the system is using the workflow, instead of directly manipulating roles and permissions associated with content.
Document Actions
Apr 11, 2010
Change navigation behaviour with jQuery: collective.navigationtoggle
A requirement from one of our customer lead us to develop a very tiny Plone add-ons... After all jQuery make all the dirty work!
One of the navigation portlet in the main site of our customer is done like the one you see on the left.
The element with arrow icon is unique and very important, but is not the element itself that links to an important document. The real useful information for end users are elements inside the section with this special icon (the subelements).
If facts the different icon itself is not enough so the customer asked us to develop an expand/collapse feature to make possible to users to not be forced to visit the not-important-section, then choose one of the subelements. For user experience the first click is only a waste of time (it's matter of usability) as the general element you see in the navigation is only a way to keep together and categorize the real infos.
Question: how many not-important-section you have in your Plone sites? Folder that only show folder_listing view or useless welcome pages?
However: what we developed in the first version of this site was a very simple (and not configurable) expand/collapse feature, you'll see on the right.
This was a Plone 2.1 site and what you see wasn't a real Plone navigation portlet. Important subelements were all loaded with the page and a simple Javascript script make them visible/invisible.
As we recently migrated this site to Plone 3, the question was: can we reproduce the same effect keeping the Plone real navigation... and this time make the feature more reusable?
Some of you can say at this point that there are already other dynamic Javascript/AJAX navigation system for Plone (for example, I well remember collective.portlet.explore) but the problem here is different... we don't want to make all navigation(s) entries expansible/collapsible but only one (or few).
Another important fact: this is the site of an italian public company, so it must follow the Stanca Act accessibility requirements (so very restrictive in matter of client side scripts technology) and a complete Javascript UI is not a good choice.
The role of jQuery
Instead of developing some new funny navigation system, our work was focused on making the most possible client side (whit an eye on graceful degradation like the Law say).
We used jQuery to obtain a cross-browser, configurable and simple plugin for Plone that make possible to chose on which navigation elements apply the expand/collapse feature. All this client side!
Welcome to collective.navigationtoggle.
The only server side component is a simple view that query the Plone catalog to show all element inside a given folder, and return all information needed by jQuery to generate navigation sub-elements on the fly (quite simple, isn't it?).
The view return only a JSON data structure, so the HTML is generated client side. How? The code create new navigation elements cloning existing ones from the navigation itself (using parents of the trigger element), then filling them using response data.
Is this way is possible that even a non-standard Plone navigation could works normally with this product (not so sure of this... to be honest some assumption are done, like the main element structure of the navigation that must be composed of UL and LI elements).
Cache
Two different problem there: prevent browser from caching server response for a too long time, but also prevent that if a user begin to click 10.000 times onto the navigation element this will send to the server one non cached request for every click.
The first problem is quite simple playing a little bit with HTTP header sent by the server, and adding timestamps with the client side request.
For the second problem we rely on jQuery.data() fantastic method, caching the generated HTML and preventing that expand/collapse actions will ask the server for the same data.
Configuration
Right now we have a real well-know problem to solve, so the product is targeted on developers. To configure it you must provide a tiny Javascript with line(s) of code like this:
jq.collective_navigationtoggle.toggle_elements.push("/foo1/foo2");
This is a simple Javascript array stored in the jQuery plugin namespace. Data provided must be the final part of the href attribute of links inside navigations portlet. This link will no more move the user to the target page but will be gifted with the expand/collapse feature.
All the magic left is done by the power of jQuery.
Plone 4 and jQuery 1.4
The product works on Plone 4 also... no problems with jQuery 1.4 (delivered with the next version of our favorite CMS, while Plone 3.3 still rely on jQuery 1.3), in facts dropping jQuery 1.3 support can reduce the Javascript code size and complexity (jQuery 1.4 has new fantastic features... take a look!).
However a real and pretty integration like with the Plone 3 theme right now is not available in Plone 4 also. Maybe in future I can work on this (Plone 4 Sunburst is not using anymore the IMG tag, instead it generate icon usin CSS classes). If you are interested and wanna help, you are welcome!
Document Actions
Apr 02, 2010
One of the Devil's APIs!
A tale about the importance of the name. When the name of a piece of code is important, and when a not well chosen API's name can lead to problems... at least for me.
The same bug! For the second time I found the same bug in an old piece of code... again the same silly bug!
Ok, that's my fault... again...
What I can say? I was young and zope.interface was a new entry in the Plone world... often when you begin playing with a new APIs you don't read documentation before... why read how to use a method called "getNameOfCurrentUser" or "convertToUnicode"?
I think that the name says all I need!
Even worst: you try the command and... it runs! You got the expected result, so why investigate further with documentation?
What I'm talking about? I'm talking of the Evil directlyProvides method!

Let's go back to those sad days
I have an object... I need the API that make possible to provide an additional interface... this is for sure a simple task for zope.interface library...
What I only know is this: a class implements an interface, and object provide it...
When I find an API called directlyProvides I try to understand it's meaning using it's name... may be calling this I'll make possible that my object provide my interface (why directly? I don't know... maybe because the interface is not inherited by the class... it's not implemented... I really don't know!).
Is my first idea right or not? Let's try. I can use this:
>>> from zope.interface import Interface, directlyProvides >>> >>> class IMyClass(Interface): ... pass ... >>> class MyClass(object): ... pass ... >>> o = MyClass() >>> IMyClass.providedBy(o) False >>> directlyProvides(o, IMyClass) >>> IMyClass.providedBy(o) True
So it works! I found my API!
The Devil, revealed
Going back to the real life... today I know the truth:
>>> print directlyProvides.__doc__ Declare interfaces declared directly for an object The arguments after the object are one or more interfaces or interface specifications (``IDeclaration`` objects). The interfaces given (including the interfaces in the specifications) replace interfaces previously declared for the object.
I'm not really sure of why this API exists (I hope for some good reason, of course...).
Today I also know that the real API I need is alsoProvides (you know... also this name is right... the problem is that I found directlyProvides before the last one...).
Only a doubt about the name itself... why they didn't called it like one of those?
- onlyProvides
- exclusivelyProvides
- willProvideThisAndNoMoreInterfaces
Lessons learned?
- Read the documentation! Check for the __doc__!
- Probably you don't need directlyProvides in Plone!