Andreas Mantke 1
Referent Andreas Mantke Mitarbeit bei OpenOffice.org von Herbst 2002 bis 2010 Seit 9/2010 Projekt LibreOffice und The Document Foundation Plone-Seiten für das Projekt LibreOffice: ODFAuthors.org, Extensions-/Template-Site, LibreOffice-Conference-Seite Entwicklung: Anpassung des PloneSoftwareCenter, Plone- AddOn für Organisation der LibreOffice-Conference Ersatz-Vorstandsmitglied von The Document Foundation (Deputy member of the Board of Directors) 2
Inhalt Was ist Dexterity? Dexterity-Inhaltstypen in der GUI erstellen Dexterity-AddOn für die Konferenz-Organisation im Dateisystem Conference-AddOn: Probleme / Todos 3
Was ist Dexterity? 4
Was ist Dexterity? Plone Zwei Frameworks für Inhaltstypen : Archetypes Dexterity 5
Was ist Dexterity? Modernes Content-Type-Framework Ersetzt künftig Archetypes Gründet auf zope.schema und z3c.form Einfacheres Erstellen von Inhaltstypen im Web und im Dateisystem 6
Dexterity-Inhaltstypen in der GUI erstellen 7
Dexterity-Inhaltstypen in der GUI erstellen 8
Dexterity-Inhaltstypen in der GUI erstellen 9
Dexterity-Inhaltstypen in der GUI erstellen 10
Dexterity-Inhaltstypen in der GUI erstellen 11
Dexterity-Inhaltstypen in der GUI erstellen Probleme: Relationship nicht möglich Anzeige-Vorlage: kein automatisches Ausblenden Bilder: kein Scalieren 12
Dexterity-AddOn für die Konferenz- Organisation im Dateisystem 13
Im Dateisystem: Voraussetzungen Eggs: plone.app.dexterity, plone.app.referenceablebehavior, plone.app.relationfield, plone.formwidget.recaptcha, plone.principalsource, plone.namedfile [blobs], plone.formwidget.namedfile, collective.wtf 14
Im Dateisystem: Voraussetzungen Neues Plone-AddOn-Paket erstellen Ins Unterverzeichnis /src des buildout gehen../bin/paster create -t plone_basic collective.conference Fragen beantworten: generic setup yes setup.py: Abhängigkeiten ergänzen Als z3c.autoinclude definieren: entry_points=""" [z3c.autoinclude.plugin] target = plone """, 15
Im Dateisystem: Konfiguration <configure xmlns="http://namespaces.zope.org/zope" xmlns:grok="http://namespaces.zope.org/grok" xmlns:browser="http://namespaces.zope.org/browser" xmlns:genericsetup="http://namespaces.zope.org/genericsetup" i18n_domain="collective.conference"> <includedependencies package="." /> <include file="permissions.zcml" /> <grok:grok package="." /> <genericsetup:registerprofile name="default" title="collective.conference" directory="profiles/default" description="installs the Collective Conference Management package" provides="products.genericsetup.interfaces.extension" /> </configure> 16
Im Dateisystem: Konfiguration metadata.xml in profiles/default: <metadata> <version>1</version> <dependencies> <dependency>profile-plone.app.dexterity:default</dependency> </dependencies> </metadata> permissions.zcml im Grundverzeichnis Für künftige Internationalisierung Initialisierung einer Message Factory in init.py: from zope.i18nmessageid import MessageFactory _ = MessageFactory("collective.conference") 17
Im Dateisystem: Aktuelle Struktur Program Track Talk Call for Paper Workshop Speakerfolder Speaker Roomfolder Room 18
Im Dateisystem: Modul-Entwicklung Zwei Modultypen zur Erklärung des Prinzips: Speaker Program 19
Modul-Entwicklung: Speaker 20
Modul-Entwicklung: Speaker from five import grok from zope import schema from plone.directives import form, dexterity from plone.app.textfield import RichText from plone.namedfile.field import NamedBlobImage from zope.app.container.interfaces import IObjectAddedEvent from Products.CMFCore.utils import gettoolbyname from collective.conference import _ import re from zope.interface import Invalid checkemail = re.compile( r"[a-za-z0-9._%-]+@([a-za-z0-9-]+\.)+[a-za-z]{2,4}").match def validateemail(value): if not checkemail(value): raise Invalid(_(u"Invalid email address")) return True class ISpeaker(form.Schema): title = schema.textline( title=_(u"your complete name"), ) (...) email = schema.asciiline( title=_(u"your email address"), constraint=validateemail, required=true, ) 21
Modul-Entwicklung: Speaker description = schema.text( title=_(u"a short bio"), ) bio = RichText( title=_(u"bio"), required=false ) picture = NamedBlobImage( title=_(u"picture"), description=_(u"please upload an image"), required=false, ) 22
Modul-Entwicklung: Program 23
Modul-Entwicklung: Program import datetime from zope.interface import invariant, Invalid from zope.filerepresentation.interfaces import IFileFactory from DateTime import DateTime from plone.indexer import indexer from plone.directives import form from plone.app.textfield import RichText from plone.formwidget.autocomplete import AutocompleteFieldWidget from z3c.form.browser.textlines import TextLinesFieldWidget from collective.conference import _ from Acquisition import aq_inner from Products.CMFCore.utils import gettoolbyname from collective.conference.track import Itrack (...) class StartBeforeEnd(Invalid): doc = _(u"the start or end date is invalid") class IProgram(form.Schema): (...) start = schema.datetime( title=_(u"start date"), required=false, ) 24
Modul-Entwicklung: Program form.primary('details') details = RichText( title=_(u"details"), description=_(u"details about the program"), required=false, ) form.widget(organizer=autocompletefieldwidget) organizer = schema.choice( title=_(u"organiser"), vocabulary=u"plone.principalsource.users", required=false, ) @invariant def validatestartend(data): if data.start is not None and data.end is not None: if data.start > data.end: raise StartBeforeEnd(_( u"the start date must be before the end date.")) @form.default_value(field=iprogram['start']) def startdefaultvalue(data): return datetime.datetime.today() + datetime.timedelta(7) @form.default_value(field=iprogram['end']) def enddefaultvalue(data): return datetime.datetime.today() + datetime.timedelta(10) 25
Modul-Entwicklung: Relation- / RichText-Feld 26
FTI - Factory Type Information types.xml in profiles/default: <object name="portal_types"> <object name="collective.conference.speaker" meta_type="dexterity FTI" /> <object name="collective.conference.program" meta_type="dexterity FTI" /> </object> 27
FTI - Factory Type Information collective.conference.speaker.xml und collective.conference.program.xml in profiles/default/types: <?xml version="1.0"?> <object name="collective.conference.program" meta_type="dexterity FTI" i18n:domain="collective.conference" xmlns:i18n="http://xml.zope.org/namespaces/i18n"> <!-- Basic metadata --> <property name="title" i18n:translate="">program</property> <property name="description" i18n:translate="">a conference program</property> ( ) <property name="global_allow">true</property> (...) <property name="allowed_content_types"> <element value="collective.conference.track" /> </property> <!-- schema interface --> <property name="schema">collective.conference.program.iprogram</property> <!-- class used for content items --> <property name="klass">plone.dexterity.content.container</property> <!-- add permission --> <property name="add_permission">cmf.addportalcontent</property> <!-- enabled behaviors --> <property name="behaviors"> <element value="plone.app.content.interfaces.inamefromtitle" /> <element value="plone.app.referenceablebehavior.referenceable.ireferenceable" /> <element value="plone.app.dexterity.behaviors.metadata.ipublication" /> </property> 28
FTI - Factory Type Information collective.conference.program.xml in profiles/default/types: <!-- View information --> <property name="default_view">view</property> <property name="default_view_fallback">false</property> <property name="view_methods"> <element value="view"/> </property> <!-- Method aliases --> <alias from="(default)" to="(selected layout)"/> <alias from="edit" to="@@edit"/> <alias from="sharing" to="@@sharing"/> <alias from="view" to="@@view"/> <!-- Actions --> <action title="view" action_id="view" category="object" condition_expr="" url_expr="string:${object_url}" visible="true"> <permission value="view"/> </action> <action title="edit" action_id="edit" category="object" condition_expr="" url_expr="string:${object_url}/edit" visible="true"> <permission value="modify portal content"/> </action> </object> 29
View class View(grok.View): grok.context(iprogram) grok.require('zope2.view') Zeigt auf Standard-Template in: program_templates/view.pt view.pt ist noch anzulegen. 30
View.pt <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="collective.conference"> <body> <metal:main fill-slot="main"> <tal:main-macro metal:define-macro="main" tal:define="tolocalizedtime nocall:context/@@plone/tolocalizedtime"> (...) <h1 class="documentfirstheading" tal:content="context/title" /> <div class="discreet"> <tal:block condition="context/start"> <span i18n:translate="label_from">from:</span> <span tal:content="python:context.start.strftime('%d. %b %Y %H:%M')" /> </tal:block> <tal:block condition="context/end"> <span i18n:translate="label_to">to:</span> <span tal:content="python:context.end.strftime('%d. %b %Y %H:%M')" /> </tal:block> </div> <p class="documentdescription" tal:content="context/description" /> <div tal:content="structure context/details/output nothing" /> 31
View.pt <h2 i18n:translate="heading_tracks">tracks</h2> <table border="0" width="100%"> <thead> <td><h4 i18n:translate="track">track</h4> </td> <td> <h4 i18n:translate="description">description</h4> </td> <td> <h4 i18n:translate="room">room</h4> </td> <td> <h4 i18n:translate="from">from</h4> </td> <td> <h4 i18n:translate="to">to</h4> </td> </thead> <tbody tal:repeat="item container/values"> <tr bgcolor="#eeeeee" tal:condition="repeat/item/even"> <td><h4><a tal:attributes="href item/getid" tal:content="item/title" /></h4></td> <td tal:content="item/description">description</td> <td> <span tal:condition="item/room"> <span tal:content="item/room/to_object/title nothing" /> </span> </td> 32
Conference-AddOn: Probleme / Todos 33
Conference-AddOn: Probleme/Todos Dublin-Core fehlt Einstellung für Navigation Registrierungsformular seperates AddOn Registrierung mit Ticketing Mehrsprachigkeit Management für Zeitänderung bei Talk-/Workshop- Verschiebung Speaker: Übernahme Daten aus Benutzerdaten Speaker: Darstellung seiner Talks / Workshops 34
Projekt / Sourcecode https://github.com/andreasma/collective.conference 35
Fragen? 36
Vielen Dank!! All text and image content in this document is licensed under the Creative Commons Attribution-Share Alike 3.0 License (unless otherwise specified). "LibreOffice" and "The Document Foundation" are registered trademarks. Their respective logos and icons are subject to international copyright laws. The use of these therefore is subject to the trademark policy. 37