Personal tools
Skip to content. | Skip to navigation
The “IReferenceable” behavior is used for enabling UUID (plone.app.uuid) support for dexterity contents, like in archetypes content types. This allow for example references between archetypes and dexterity content types. Note: It can’t work with Plone==4.0 because it is based on plone.uuid integration in CMF. It is compatible with Plone>=4.1
The IStagingSupport behavior is used for enabling the plone.app.iterate functionality for Dexterity content. It allows you to perform the checkout and checkin operations to work on a copy of your original content.
The IVersionable behavior is used for enabling the CMFEditions functionality for dexterity contents. It adds a changeNote-field to the edit- and add-forms and creates a new version when the content is edited, if enabled for the content type. It's based on Products.CMFEditions. For listing the versions of an object use CMFEdtions' view versions_history_form or the history viewlet (see default @@view).
The goal of plone.app.widgets is to provide an implementation for a new set of javascript widgets being developed in the Plone Mockup project. It overrides existing widgets used in dexterity and archetypes to provide tested and modularized widgets based on the concept of patterns. The widgets that are provided currently are: Adjust Text Size -- Easily change text size on a page. Cookie Directive -- A pattern that checks cookies enabled and asks permission for the user to allow cookies or not. Expose -- Exposes the focused element by darkening everything else on the page. Useful to focus the user attention on a particular area. Form Unload Alert -- A pattern to warn user when changes are unsaved and they try to navigate away from page. Live Search -- Dynamically query the server and display results. Modal -- Creates a modal dialog (also called overlay). Pick A Date -- Allows the user to select a date (with or without time) through a calendar. Picture -- A responsive image widget. Prevent Double Submit -- A pattern to prevent submitting a form twice. Query String for Collections -- A widget for creating query's for collections Related Items -- An advanced widget for selecting related items. Select2 -- Autocompletes, multiple or single selections from any kind of data source (with search!). Table Sorter -- A pattern you can apply to a table so it can have its items rearranged when clicking the header. TinyMCE (v4!!!) -- Rich text editor. Table of Contents -- Automatically generate a table of contents. Tooltip -- A pattern to show a tooltip on hover. DropZone -- Drag 'n drop file upload Widgets that are overridden in Edit forms are: subject language effectiveDate expirationDate contributrors creators relatedItems query All client side code (javascript/css/images) is done and tested as part of Plone Mockup project.
This package provides a GUI for managing custom workflows in Plone. This is the successor of uwosh.northstar's workflow design tool (North* continues on as a file system product generator, given either a PloneFormGen or Dexterity prototype). Features * add/edit/delete new workflows * add content rule actions easily for a workflow transition * graph workflows * easily manipulate workflow permissions Graphing The package also supports graphing workflows. The inspiration for this piece was pretty much taken from DCWorkflowGraph. In order to enable this feature, you'll need to install the Graphviz library. Information can be found at http://www.graphviz.orga workflow manager for plone
Dexterity is a system for building content types, both through-the-web and as filesystem code. It is aimed at Plone, although this package should work with plain Zope + CMF systems. Key use cases Dexterity wants to make some things really easy. These are: * Create a "real" content type entirely through-the-web without having to know programming. * As a business user, create a schema using visual or through-the-web tools, and augment it with adapters, event handlers, and other Python code written on the filesystem by a Python programmer. * Create content types in filesystem code quickly and easily, without losing the ability to customise any aspect of the type and its operation later if required. * Support general "behaviours" that can be enabled on a custom type in a declarative fashion. Behaviours can be things like title-to-id naming, support for locking or versioning, or sets of standard metadata with associated UI elements. * Easily package up and distribute content types defined through-the-web, on the filesystem, or using a combination of the two. Philosophy Dexterity is designed with a specific philosophy in mind. This can be summarised as follows: Reuse over reinvention As far as possible, Dexterity should reuse components and technologies that already exist. More importantly, however, Dexterity should reuse concepts that exist elsewhere. It should be easy to learn Dexterity by analogy, and to work with Dexterity types using familiar APIs and techniques. Small over big Mega-frameworks be damned. Dexterity consists of a number of speciaised packages, each of which is independently tested and reusable. Furthermore, packages should has as few dependencies as possible, and should declare their dependencies explicitly. This helps keep the design clean and the code manageable. Natural interaction over excessive generality The Dexterity design was driven by several use cases (see docs/Design.txt) that express the way in which we want people to work with Dexterity. The end goal is to make it easy to get started, but also easy to progress from an initial prototype to a complex set of types and associated behaviours through step-wise learning and natural interaction patterns. Dexterity aims to consider its users - be they business analysts, light integrators or Python developers, and be they new or experienced - and cater to them explicitly with obvious, well-documented, natural interaction patterns. Real code over generated code Generated code is difficult to understand and difficult to debug when it doesn't work as expected. There is rarely, if ever, any reason to scribble methods or 'exec' strings of Python code. Zope 3 over Zope 2 Although Dexterity does not pretend to work with non-CMF systems, as many components as possible should work with plain Zope 3, and even where there are dependencies on Zope 2, CMF or Plone, they should - as far as is practical - follow Zope 3 techniques and best practices. Many operations (e.g. managing objects in a folder, creating new objects or manipulating objects through a defined schema) are better designed in Zope 3 than they were in Zope 2. Zope concepts over new paradigms We want Dexterity to be "Zope-ish" (and really, "Zope 3-ish"). Zope is a mature, well-designed (well, mostly) and battle tested platform. We do not want to invent brand new paradigms and techniques if we can help it. Automated testing over wishful thinking "Everything" should be covered by automated tests. Dexterity necessarily has a lot of moving parts. Untested moving parts tend to come lose and fall on people's heads. Nobody likes that.
Grok-like directives for creating Dexterity content
NOT in development. This package is beeing merged on plone.app.multilingual .. image:: https://travis-ci.org/plone/plone.multilingual.png :target: http://travis-ci.org/plone/plone.multilingual plone.multilingual ================== This package contains the core functionality for the next generation multilingual engine. These are the main artifacts and its purposes: canonical: * the canonical organizes the information about a "translation-group" * it's using a dictionary with language-codes as keys and uuids (provided by plone.uuid) as values storage: * persistent storage, which holds the canonicals in an IOBTree * the OOBTree's key is the UUID of the content, the according value is the canonical manager: * adapter for ITranslatable * provides the translations API adapters: * ITranslationLocator - where to put a translation * ITranslationIdChooser - generates a valid id for a translation * ITranslationCloner - copy the language-independent content to the translation * ITranslationFactory - creates the translation In order to have a test we have a type called Demo that has an adapter called DemoLanguage that will allow to get the language of the object:: >>> from plone.multilingual.interfaces import ITranslationManager >>> from plone.multilingual.interfaces import ILanguage >>> from plone.app.testing import setRoles, login, TEST_USER_ID, TEST_USER_NAME >>> from zope.lifecycleevent import modified >>> portal = layer['portal'] >>> setRoles(portal, TEST_USER_ID, ['Manager']) >>> login(portal, TEST_USER_NAME) >>> portal.invokeFactory('Folder', 'ob1', title=u"An archetypes based folder") 'ob1' >>> ILanguage(portal['ob1']).set_language('ca') >>> portal['ob1'].reindexObject() >>> modified(portal['ob1']) Ensuring that the new object gets its UUID:: >>> from plone.uuid.interfaces import IUUID >>> ob1_uuid = IUUID(portal['ob1']) >>> isinstance(ob1_uuid, str) True We create a new translation in 'en' language:: >>> ITranslationManager(portal['ob1']).add_translation('en') We try to create a new translation in 'ca' that already exists:: >>> ITranslationManager(portal['ob1']).add_translation('ca') Traceback (most recent call last): ... KeyError: 'Translation already exists' We try to create a new translation without language:: >>> ITranslationManager(portal['ob1']).add_translation(None) Traceback (most recent call last): ... KeyError: 'There is no target language' We get the 'en' translation:: >>> ITranslationManager(portal['ob1']).get_translation('en') <ATFolder at /plone/ob1-en> >>> ILanguage(ITranslationManager(portal['ob1']).get_translation('en')).get_language() == 'en' True let's get all the translations:: >>> ITranslationManager(portal['ob1']).get_translations() {'ca': <ATFolder at /plone/ob1>, 'en': <ATFolder at /plone/ob1-en>} let's get only the languages:: >>> ITranslationManager(portal['ob1']).get_translated_languages() ['ca', 'en'] has_translation:: >>> ITranslationManager(portal['ob1']).has_translation('en') True >>> ITranslationManager(portal['ob1']).has_translation('it') False register_translation with invalid language:: >>> ITranslationManager(portal['ob1']).remove_translation('en') >>> ITranslationManager(portal['ob1']).register_translation(None, portal['ob1-en']) Traceback (most recent call last): ... KeyError: 'There is no target language' register a translation with content:: >>> ITranslationManager(portal['ob1']).register_translation('en', portal['ob1-en']) >>> ITranslationManager(portal['ob1']).get_translations() {'ca': <ATFolder at /plone/ob1>, 'en': <ATFolder at /plone/ob1-en>} changing the content-language (there should act a subscriber):: >>> ILanguage(portal['ob1-en']).set_language('it') >>> from zope.event import notify >>> from zope.lifecycleevent import ObjectModifiedEvent >>> notify(ObjectModifiedEvent(portal['ob1-en'])) >>> ITranslationManager(portal['ob1']).get_translations() {'ca': <ATFolder at /plone/ob1>, 'it': <ATFolder at /plone/ob1-en>} test more translations:: >>> obj_it = ITranslationManager(portal['ob1']).get_translation('it') >>> ITranslationManager(obj_it).add_translation('fr') >>> ITranslationManager(obj_it).add_translation('pt') >>> ITranslationManager(portal['ob1']).get_translated_languages() ['ca', 'it', 'fr', 'pt'] >>> ITranslationManager(obj_it).get_translated_languages() ['ca', 'it', 'fr', 'pt'] test if canonicals objects are the same:: >>> obj_ca = ITranslationManager(obj_it).get_translation('ca') >>> canonical_it = ITranslationManager(obj_it).query_canonical() >>> canonical_ca = ITranslationManager(obj_ca).query_canonical() >>> canonical_it == canonical_ca True Messing up with content ----------------------- In case that we do mess up things with content (users always do):: >>> from zope.lifecycleevent import modified >>> portal.invokeFactory('Folder', 'ob2', title=u"An archetypes based doc") 'ob2' >>> ILanguage(portal['ob2']).set_language('it') >>> modified(portal['ob2']) >>> ILanguage(portal['ob2']).get_language() 'it' >>> ITranslationManager(portal['ob2']).add_translation('en') >>> ob2_en = ITranslationManager(portal['ob2']).get_translation('en') >>> portal.invokeFactory('Folder', 'ob3', title=u"An archetypes based doc") 'ob3' >>> ILanguage(portal['ob3']).set_language('it') >>> modified(portal['ob3']) >>> ILanguage(portal['ob3']).get_language() 'it' >>> ITranslationManager(portal['ob3']).add_translation('es') >>> ob3_es = ITranslationManager(portal['ob3']).get_translation('es') >>> from OFS.event import ObjectWillBeRemovedEvent >>> notify(ObjectWillBeRemovedEvent(portal['ob2'])) >>> portal.manage_delObjects('ob2') >>> notify(ObjectWillBeRemovedEvent(ob3_es)) >>> portal.manage_delObjects(ob3_es.id) >>> c_old = ITranslationManager(portal['ob3']).query_canonical() >>> c_new = ITranslationManager(ob2_en).query_canonical() >>> c_old == c_new False >>> isinstance(c_old, str) True >>> isinstance(c_new, str) True >>> ITranslationManager(ob2_en).register_translation('it', portal['ob3']) >>> c1 = ITranslationManager(portal['ob3']).query_canonical() >>> c2 = ITranslationManager(ob2_en).query_canonical() >>> c1 == c2 True Other use case, A('it' + 'en') and B('it' + 'es'), and we want A('en') -> B('es'):: >>> portal.invokeFactory('Folder', 'mess1', title=u"An archetypes based doc") 'mess1' >>> ILanguage(portal['mess1']).set_language('it') >>> modified(portal['mess1']) >>> ILanguage(portal['mess1']).get_language() 'it' >>> ITranslationManager(portal['mess1']).add_translation('en') >>> mess1_en = ITranslationManager(portal['mess1']).get_translation('en') >>> portal.invokeFactory('Folder', 'mess2', title=u"An archetypes based doc") 'mess2' >>> ILanguage(portal['mess2']).set_language('it') >>> ITranslationManager(portal['mess2']).add_translation('es') >>> mess2_es = ITranslationManager(portal['mess2']).get_translation('es') >>> ITranslationManager(mess1_en).register_translation('es', mess2_es) >>> ITranslationManager(portal['mess2']).get_translation('es') >>> ITranslationManager(portal['mess1']).get_translation('es') <ATFolder at /plone/mess2-es> Default-Adapters ---------------- id-chooser:: >>> from plone.multilingual.interfaces import ITranslationIdChooser >>> chooser = ITranslationIdChooser(portal['ob1-en']) >>> chooser(portal, 'es') 'ob1-es' locator:: >>> ITranslationManager(portal['ob1']).add_translation('es') >>> child_id = portal.ob1.invokeFactory('Folder', 'ob1_child', language="ca") >>> from plone.multilingual.interfaces import ITranslationLocator >>> locator = ITranslationLocator(portal['ob1-en']) >>> locator('es') == portal True >>> child_locator = ITranslationLocator(portal.ob1.ob1_child) >>> child_locator('es') == portal['ob1-es'] True >>> ITranslationManager(portal['ob1']).remove_translation('es') Convert intids to uuids upgrade step ------------------------------------ An upgrade step is available in case of having an existing site with the experimental 0.1 plone.multilingual version:: >>> from plone.multilingual.upgrades.to02 import upgrade .. note:: You must reinstall the plone.multilingual package in order to install the required new utility in place before upgrading. If you are using a version of Dexterity below 2.0, you must install the package plone.app.referenceablebehavior and enable the *Referenceable* (plone.app.referenceablebehavior.referenceable.IReferenceable) behavior for all your Dexterity content types before you attempt to upgrade your site. You can run the @@pml-upgrade view at the root of your site or follow the upgrade step in portal_setup > upgrades. If you can't see the upgrade step, press *Show old upgrades* and select the *Convert translation based intids to uuids (0.1 → 02)* Upgrade to catalog ------------------ :: >>> from plone.multilingual.upgrades.to03 import upgrade we shouldn't find the storage-utility anymore:: >>> from plone.multilingual.interfaces import IMultilingualStorage >>> gsm = portal.getSiteManager() >>> gsm.queryUtility(IMultilingualStorage) is None True
plone.multilingualbehavior adds multilingual behavior to content types built with Dexterity. It uses the next generation multilingual engine powered by five/Zope3 technologies, plone.multilingual. The behavior provides the Dexterity-driven content with a marker interface "ITranslatable", and makes available to that translation enabled type all the translation UI components such as menus, views, etc... To make your Dexterity content type translatable, add the following line to the <!-- enabled behaviors --> section in your type's profile: <!-- enabled behaviors --> <property name="behaviors"> <element value="plone.multilingualbehavior.interfaces.IDexterityTranslatable" /> </property> plone.multilingualbehavior implements language independent fields. The content of language independent fields is the same across all language versions. This is convenient, but also a little dangerous, because editing the field on any language version will change the content on all other language versions. For details on how to make fields language independent, see the examples in the test folder. tests/schemata.py shows how to make fields language independent when using the Grok framework; tests/samplecontent_type.xml shows how to achieve the same thing in an xml file. It is also possible to set a field to be language independent through the web, given a sufficiently new version of plone.schemaeditor.
The transmogrify.dexterity package provides a transmogrifier pipeline section for updating field values of dexterity content objects. The blueprint name is transmogrify.dexterity.schemaupdater. The schemaupdater section needs at least the path to the object to update. Paths to objects are always interpreted as being relative to the context. Any writable field who's id matches a key in the current item will be updated with the corresponding value. Fields that do not get a value from the pipeline are initialized with their default value or get a missing_value marker. This functionality will be moved into a separate constructor pipeline... The schmemaupdater section can also handle fields defined in behaviors.