# -*- coding: UTF-8 -*- import os.path from five import grok from zope import schema from plone.namedfile import field as namedfile from z3c.relationfield.schema import RelationChoice, RelationList from plone.formwidget.contenttree import ObjPathSourceBinder from plone.dexterity.browser.add import DefaultAddView, DefaultAddForm from plone.dexterity.browser.edit import DefaultEditForm from plone.dexterity.browser.view import DefaultView from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from plone.app.textfield.value import RichTextValue import plone.dexterity.browser from plone.directives import form, dexterity from plone.app.textfield import RichText from plone.app.z3cform.wysiwyg import WysiwygFieldWidget from plone.indexer import indexer from zope.lifecycleevent.interfaces import IObjectModifiedEvent from zope.schema.fieldproperty import FieldProperty from zope.schema.interfaces import IVocabularyFactory from zope.schema.vocabulary import SimpleVocabulary import unicodedata from zope.interface import invariant, Invalid, Interface from ageliaco.rd2 import MessageFactory from collective.z3cform.datagridfield import DataGridFieldFactory, DictRow import datetime import z3c.form # for debug purpose => log(...) from Products.CMFPlone.utils import log from zope.schema.interfaces import IContextSourceBinder from zope.lifecycleevent.interfaces import IObjectCreatedEvent from zope.app.container.interfaces import IObjectAddedEvent from Products.CMFCore.utils import getToolByName from plone.z3cform.textlines.textlines import TextLinesFieldWidget from plone.namedfile.field import NamedImage from plone.formwidget.autocomplete import AutocompleteMultiFieldWidget, AutocompleteFieldWidget from plone.formwidget.autocomplete import AutocompleteMultiFieldWidget from zope.interface import invariant, Invalid from Acquisition import aq_inner, aq_parent from zope.component import getUtility from Products.CMFCore.interfaces import ISiteRoot from zope.security import checkPermission from AccessControl.interfaces import IRoleManager import yafowil.plone import yafowil.loader from yafowil.base import factory, UNSET, ExtractionError from yafowil.controller import Controller from yafowil.plone.form import Form from AccessControl.interfaces import IRoleManager schools = {u"ECGGR":[u"EC Bougeries",u"CEC"], u"CEBOU":[u"Nicolas-Bouvier",u"CEC"], u"CECHA":[u"André-Chavanne",u"CEC"], u"CEGOU":[u"Emilie-Gourd",u"CEC"], u"ECASE":[u"Madame-de-Stael",u"CEC"], u"ECSTI":[u"EC Aimée-Stitelmann",u"CEC"], u"CALV":[u"Calvin",u"COLLEGES"], u"CAND":[u"Candolle",u"COLLEGES"], u"CLAP":[u"Claparède",u"COLLEGES"], u"COPAD":[u"Alice-Rivaz",u"COLLEGES"], u"ROUS":[u"Rousseau",u"COLLEGES"], u"SAUS":[u"Saussure",u"COLLEGES"], u"SISM":[u"Sismondi",u"COLLEGES"], u"VOLT":[u"Voltaire",u"COLLEGES"], u"ECBGR":[u"ECG RHONE",u"ECG"], u"DUNAN":[u"Henry-Dunand",u"ECG"], u"MAILL":[u"Ella-Maillart",u"ECG"], u"ECGJP":[u"Jean-Piaget",u"ECG"], u"CFPC":[u"CFPC",u"ECOLES PROFESSIONNELLES"], u"CFPS":[u"CFPS",u"ECOLES PROFESSIONNELLES"], u"CFPT":[u"CFPT",u"ECOLES PROFESSIONNELLES"], u"CFPSH":[u"CFPSHR-EGEI",u"ECOLES PROFESSIONNELLES"], u"BOUV":[u"CFPCOM-Bouvier",u"ECOLES PROFESSIONNELLES"], u"CFPNE":[u"CFPNE",u"ECOLES PROFESSIONNELLES"], u"CFPAA":[u"CFPAA",u"ECOLES PROFESSIONNELLES"], u"SCAI":[u"SCAI",u"INSERTION"], u"COUDR":[u"CO Coudriers",u"CYCLES"]} sponsorships = {u"0":[u"0",0], u"0.25":[u"0.25",0.25], u"0.50":[u"0.50",0.50], u"0.75":[u"0.75",0.75], u"1.00":[u"1.00",1.00], u"1.25":[u"1.25",1.25], u"1.50":[u"1.50",1.50], u"1.75":[u"1.75",1.75], u"2.00":[u"2.00",2.00], u"2.25":[u"2.25",2.25], u"2.50":[u"2.50",2.50], u"2.75":[u"2.75",2.75], u"3.00":[u"3.00",3.00], u"3.25":[u"3.25",3.25], u"3.50":[u"3.50",3.50], u"3.75":[u"3.75",3.75], u"4.00":[u"4.00",4.00]} class SchoolsVocabulary(object): grok.implements(IVocabularyFactory) def __call__(self, context): terms = [] for school in sorted(schools.keys()): terms.append(SimpleVocabulary.createTerm(unicodedata.normalize('NFKC',school).encode('ascii','ignore'), unicodedata.normalize('NFKC',schools[school][0]).encode('ascii','ignore'), unicodedata.normalize('NFKC',schools[school][0]).encode('ascii','ignore'))) return SimpleVocabulary(terms) grok.global_utility(SchoolsVocabulary, name=u"ageliaco.rd2.schools") class SponsorshipVocabulary(object): grok.implements(IVocabularyFactory) def __call__(self, context): terms = [] for sponsorship in sorted(sponsorships.keys()): terms.append(SimpleVocabulary.createTerm(unicodedata.normalize('NFKC',sponsorship).encode('ascii','ignore'), unicodedata.normalize('NFKC',sponsorships[sponsorship][0]).encode('ascii','ignore'), unicodedata.normalize('NFKC',sponsorships[sponsorship][0]).encode('ascii','ignore'))) return SimpleVocabulary(terms) grok.global_utility(SponsorshipVocabulary, name=u"ageliaco.rd2.sponsorship") class GroupMembers(object): """Context source binder to provide a vocabulary of users in a given group. """ grok.implements(IContextSourceBinder) def __init__(self, group_name): self.group_name = group_name def __call__(self, context): acl_users = getToolByName(context, 'acl_users') group = acl_users.getGroupById(self.group_name) terms = [] #terms.append(SimpleVocabulary.createTerm('', str(''), '')) if group is not None: for member_id in group.getMemberIds(): user = acl_users.getUserById(member_id) if user is not None: member_name = user.getProperty('fullname') or member_id terms.append(SimpleVocabulary.createTerm(member_id, str(member_id), member_name)) return SimpleVocabulary(terms) class ProjetsVoc(object): """Context source binder to provide a vocabulary of users in a given group. """ grok.implements(IContextSourceBinder) def __init__(self, projet_name): self.projet_name = projet_name def __call__(self, context): acl_users = getToolByName(context, 'acl_users') group = acl_users.getGroupById(self.projet_name) terms = [] terms.append(SimpleVocabulary.createTerm('', str(''), '')) if group is not None: for member_id in group.getMemberIds(): user = acl_users.getUserById(member_id) if user is not None: member_name = user.getProperty('fullname') or member_id terms.append(SimpleVocabulary.createTerm(member_id, str(member_id), member_name)) return SimpleVocabulary(terms) class IAuteur(form.Schema): """ Auteur de projet """ # removed because if user is removed from ldap it generates an error # # form.widget(id=AutocompleteFieldWidget) # id = schema.Choice( # title=MessageFactory(u"Pseudo"), # description=MessageFactory(u"Login p10"), # vocabulary=u"plone.principalsource.Users", # required=True, # ) id = schema.TextLine( title=MessageFactory(u"id"), description=MessageFactory(u"Identifiant (login)"), required=True, ) lastname = schema.TextLine( title=MessageFactory(u"Nom"), description=MessageFactory(u"Nom de famille"), required=True, ) firstname = schema.TextLine( title=MessageFactory(u"Prénom"), description=MessageFactory(u"Prénom"), required=True, ) school = schema.Choice( title=MessageFactory(u"Ecole"), description=MessageFactory(u"Etablissement scolaire de référence"), vocabulary=u"ageliaco.rd2.schools", default='', required=True, ) address = schema.Text( title=MessageFactory(u"Adresse"), description=MessageFactory(u"Adresse postale"), required=False, ) email = schema.TextLine( title=MessageFactory(u"Email"), description=MessageFactory(u"Adresse courrielle"), required=True, ) phone = schema.TextLine( title=MessageFactory(u"Téléphone"), description=MessageFactory(u"Téléphone"), required=False, ) sponsorasked = schema.Choice( title=MessageFactory(u"Dégrèvement demandé"), description=MessageFactory(u"Dégrèvement total demandé pour cet auteur"), vocabulary=u"ageliaco.rd2.sponsorship", required=True, ) dexterity.read_permission(sponsorSEM='cmf.ReviewPortalContent') dexterity.write_permission(sponsorSEM='cmf.ReviewPortalContent') sponsorSEM = schema.Choice( title=MessageFactory(u"Dégrèvement SEM"), description=MessageFactory(u"Dégrèvement SEM attribué pour cet auteur"), vocabulary=u"ageliaco.rd2.sponsorship", required=False, ) dexterity.read_permission(sponsorRD='cmf.ReviewPortalContent') dexterity.write_permission(sponsorRD='cmf.ReviewPortalContent') sponsorRD = schema.Choice( title=MessageFactory(u"Dégrèvement R&D"), description=MessageFactory(u"Dégrèvement R&D attribué pour cet auteur"), vocabulary=u"ageliaco.rd2.sponsorship", required=False, ) dexterity.read_permission(sponsorSchool='cmf.ReviewPortalContent') dexterity.write_permission(sponsorSchool='cmf.ReviewPortalContent') sponsorSchool= schema.Choice( title=MessageFactory(u"Dégrèvement Ecole"), description=MessageFactory(u"Dégrèvement école attribué pour cet auteur"), vocabulary=u"ageliaco.rd2.sponsorship", required=False, ) @grok.subscribe(IAuteur, IObjectAddedEvent) def setAuteur(auteur, event): portal_url = getToolByName(auteur, 'portal_url') acl_users = getToolByName(auteur, 'acl_users') #print "Nous y voici ::::>>>> ", auteur.id portal = portal_url.getPortalObject() cycles = auteur.aq_parent #print 'auteur id : ' + auteur.id user = acl_users.getUserById(auteur.id) class IProjet(form.Schema): """ Projet RD """ start = schema.TextLine( title=MessageFactory(u"Année"), description=MessageFactory(u"L'année à laquelle le projet a commencé ou devrait commencer"), required=True, ) duration = schema.Int( title=MessageFactory(u"Durée"), description=MessageFactory(u"Durée (en années) du projet, prévue ou effective"), required=True, ) presentation = RichText( title=MessageFactory(u"Présentation"), description=MessageFactory(u"Présentation synthétique du projet (présentation publiée)"), required=True, ) picture = NamedImage( title=MessageFactory(u"Chargez une image pour le projet"), required=False, ) lien = schema.TextLine( title=MessageFactory(u"Lien vers la réalisation"), description=MessageFactory(u"Lien extérieur vers la réalisation"), required=False, ) @grok.subscribe(IProjet, IObjectAddedEvent) def setRealisation(projet, event): admid = 'realisation' try: cycles = projet[admid] except KeyError: rea = projet.invokeFactory("Folder", id=admid, title=u'Réalisation') #projet[admid] = rea #projet.setContributors(projet.contributor) #request.response.redirect(cycles.absolute_url() + '++add++ageliaco.rd2.cycle') return #request.response.redirect(cycles.absolute_url() + '++add++ageliaco.rd2.cycle') @grok.provider(IContextSourceBinder) def activeProjects(context): catalog = getToolByName(context, 'portal_catalog') cat = catalog(portal_type='ageliaco.rd2.projet', review_state='encours', sort_on='sortable_title') log('catalogue : %s items'%len(cat)) terms = [] for brain in cat: #print dir(brain) #print "getURL : %s => getPath : %s " % (brain.getURL(),brain.getPath()) terms.append(SimpleVocabulary.createTerm(brain.getPath(), brain.id, brain.Title)) return SimpleVocabulary(terms) #SimpleVocabulary([SimpleVocabulary.createTerm(x.id, x.getURL(), x.Title) for x in cat]) cycle_default_projet_presentation = """ <h2><span style="color: rgb(204, 0, 0); ">Discipline(s) concernée(s) par le projet :<br /></span></h2> <p class="callout"> </p> <h2><span style="color: rgb(1, 40, 0); "><span style="color: rgb(204, 0, 0); ">Description synthétique de l'ensemble du projet :</span><br /></span></h2> <p><i><span class="discreet noprint">Décrire brièvement votre projet en vue de sa promotion sur le site Ressources et développement.</span></i></p> <p class="callout"> </p><br /> <h2><span style="color: rgb(204, 0, 0);">Thématique:</span></h2> <h3>Quel est le thème du projet ?</h3> <p><i><span class="discreet noprint">Expliciter en quelques lignes le(s) contenu(s) sur le(s)quel(s) les participants au projet souhaitent travailler.</span></i></p> <p class="callout"> </p><br /> <h2><span style="color: rgb(204, 0, 0); ">Contexte :</span></h2> <h3>a. Sur quelles expériences ou connaissances préalables repose le projet ?</h3> <p><i><span class="discreet noprint">Quels sont le travail et la réflexion déjà entamés dans le domaine de la recherche proposée : bibliographie, inventaire d'expérience, etc.</span></i></p> <p class="callout"> </p><br /> <h3>b. Quels éléments de la situation présente sont à l'origine du besoin exprimé ?</h3> <p><i><span class="discreet noprint">Justification et preuves du besoin : études, enquête, sondage, argumentaire précis, etc..</span></i></p> <p class="callout"> </p><br /> <h2><span style="color: rgb(204, 0, 0); ">Objectifs pédagogiques :</span></h2> <h3>Quels sont les objectifs généraux du projet ?</h3> <p><i><span class="discreet noprint">Changements et actions concrets auxquels on peut s'attendre à court et à long terme</span></i></p> <p class="callout"> </p><br /> <h2><span style="color: rgb(204, 0, 0); ">Résultats pédagogiques pour les élèves et les maîtres :</span></h2> <h3>a. Quels sont le public visé et les établissements concernés ?</h3> <p class="callout"> </p> <h3>b. Quelle forme prend le produit fini au terme du projet ?</h3> <p><i><span class="discreet noprint">Brochure, site, etc..</span></i></p> <p class="callout"> </p><br /> <h2><span style="color: rgb(204, 0, 0); ">Organisation :</span></h2> <h3>a. Quelle est la durée estimée du projet, en année(s) scolaire(s) ?</h3> <p class="callout"> </p> <h3>b. Quels sont les objectifs spécifiques du projet pour l'(es) année(s) scolaire(s) ?</h3> <p class="callout"> </p> """ cycle_default_problematique = """ <h2><span style="color: rgb(204, 0, 0); ">Planification et répartition des tâches pour l'année en cours :</span></h2> <h3>a. Quelle planification est prévue ? (étapes) :</h3> <p class="callout"> </p> <h3>b. Quel rôle et quelle répartition des tâches sont prévus par participant?</h3> <p class="callout"> </p> <p> </p> <h2><span style="color: rgb(204, 0, 0); ">Modalités de travail :</span></h2> <h3>Quelles sont les modalités de travail qui faciliteraient la réalisation de votre projet ?</h3> <p><i><span class="discreet noprint">Plateforme pour un travail à distance, horaire aménagé sur 2 heures hebdomadaires, etc. (à préciser également dans les vœux horaires dans votre établissement.)</span></i></p> <p class="callout"> </p><br /> <h2><span style="color: rgb(204, 0, 0); ">Ressources supplémentaires :</span></h2> <p><i><span class="discreet noprint">Accompagnement par des experts du Service Ecole Media, par des experts sous forme de demi-journées d'étude, par des séminaires de formation continue, etc.</span></i></p> <p class="callout"> </p> <br /> <p style="text-align: center; "><span style="color: rgb(204, 0, 0); "><strong> <img alt="Sourire" border="0" src="../plugins/emotions/img/smiley-smile.gif" title="Sourire" /> Le secteur Ressources et développement vous remercie d'avoir complété ce formulaire auquel il portera toute son attention</strong> </span><i><span> <img alt="Sourire" border="0" src="../plugins/emotions/img/smiley-smile.gif" title="Sourire" /><br /></span></i></p> <p> </p> """ class ICycle(form.Schema): """ Cycle de projet RD """ # -*- Your Zope schema definitions here ... -*- form.mode(id='hidden') id = schema.TextLine( title=MessageFactory(u"Identifiant"), description=MessageFactory(u"Ne pas changer celui donné par défaut! Merci!"), required=True, ) title = schema.TextLine( title=MessageFactory(u"Titre"), description=MessageFactory(u"Titre bref du projet"), required=True, ) description = schema.Text( title=MessageFactory(u"Sous-titre"), description=MessageFactory(u"Sous-titre du projet"), required=False, ) presentation = RichText( title=MessageFactory(u"Présentation succincte du projet"), description=MessageFactory(u"Présentation succincte du projet (synopsis)"), required=True, ) #form.widget(projet=AutocompleteFieldWidget) projet = schema.Choice( title=MessageFactory(u"Projet existant"), description=MessageFactory(u"Lien vers un projet existant"), source=activeProjects, required=False, ) dexterity.write_permission(supervisor='cmf.ReviewPortalContent') supervisor = schema.Choice( title=MessageFactory(u"Superviseur"), description=MessageFactory(u"Personne de R&D qui supervise ce projet"), source=GroupMembers('superviseur'), required=False, ) problematique = RichText( title=MessageFactory(u"Problématique"), description=MessageFactory(u"Problématique et contexte du projet"), required=False, ) # objectifs = RichText( # title=MessageFactory(u"Objectifs"), # description=MessageFactory(u"Objectifs, moyens nécessaires et résultats escomptés du projet pour l'année"), # required=False, # ) def idDefaultFromContext(context): """context must be a ageliaco.rd2.projet object""" newId = '' indice = 1 start = '' catalog = getToolByName(context, 'portal_catalog') cat = catalog.unrestrictedSearchResults(object_provides= ICycle.__identifier__, path={'query': '/'.join(context.getPhysicalPath()), 'depth': 1}, sort_on="modified", sort_order="reverse") if hasattr(context,'start'): start = context.start else: start = str(datetime.datetime.today().year) if len(cat): #first is last generated,if it is not a copy from an old cycle for cycle in cat: lastId = cycle.id index = lastId.find('-') if (index > -1) and (lastId[:index]==start): indice = int(lastId[index+1:]) indice+=1 break newId = "%s-%s" % (start,indice) while newId in context.objectIds(): indice+=1 newId = "%s-%s" % (start,indice) return newId @form.default_value(field=ICycle['id']) def idDefaultValue(data): # To get hold of the folder, do: context = data.aq_parent #import pdb; pdb.set_trace() context = data.context newId = idDefaultFromContext(context) return newId @form.default_value(field=ICycle['presentation']) def presentationDefaultValue(data): # To get hold of the folder, do: context = data.context return RichTextValue( raw=cycle_default_projet_presentation ) @form.default_value(field=ICycle['problematique']) def problematiqueDefaultValue(data): # To get hold of the folder, do: context = data.context return RichTextValue( raw=cycle_default_problematique ) @grok.subscribe(ICycle, IObjectModifiedEvent) def setSupervisor(cycle, event): if not cycle.supervisor: return if IRoleManager.providedBy(cycle): cycle.manage_addLocalRoles(cycle.supervisor, ['Reader', 'Contributor', 'Editor']) log("Role added to %s for %s"%(cycle.id,cycle.supervisor)) @grok.subscribe(ICycle, IObjectAddedEvent) def setAuteurs(cycle, event): #print "Projet lié à %s ==> %s ==> %s" % (cycle.id,cycle.projet,cycle.supervisor) if not cycle.projet: return catalog = getToolByName(cycle, 'portal_catalog') cat = catalog(portal_type='ageliaco.rd2.cycle', path={'query': cycle.projet, 'depth': 1}, sort_on="id",sort_order="reverse") log('catalogue des cycles : %s items'%len(cat)) #if there cycles, take the last one (first in reverse) and copy the authors if len(cat): lastCyclePath = cat[0].getPath() lastCycle = cat[0].getObject() auteurBrains = catalog(portal_type='ageliaco.rd2.auteur', path={'query': lastCyclePath, 'depth': 1}) for brain in auteurBrains: auteur = brain.getObject() cb_copy_data = lastCycle.manage_copyObjects([auteur.id]) cycle.manage_pasteObjects(cb_copy_data) #projet.setContributors(projet.contributor) #request.response.redirect(cycles.absolute_url() + '++add++ageliaco.rd2.cycle') return #request.response.redirect(cycles.absolute_url() + '++add++ageliaco.rd2.cycle') class InterfaceView(grok.View,Form): grok.context(Interface) grok.require('zope2.View') grok.name('interface') objectPath = '' degrevements = {} withTotal = False multikey = '@@keywordview' indx = 'Subject' searchType = IProjet.__identifier__ pathDepth = 0 allauthors = "cycle,author.id,author.lastname,author.firstname,author.school,ordre,author.sponsorasked,author.sponsorSEM,author.sponsorRD,author.sponsorSchool" def set2float(self,value): if not value: return 0.0 else: return float(value) # canReviewContent def canReviewContent(self): return checkPermission('cmf.ReviewPortalContent', self.context) def canAddContent(self): return checkPermission('cmf.AddPortalContent', self.context) def canModifyContent(self): return checkPermission('cmf.ModifyPortalContent', self.context) def setObjectPath(self, objectPath, withTotal = False): self.objectPath = objectPath self.withTotal = withTotal if withTotal: self.degrevements[objectPath] = [0.0, 0.0, 0.0, 0.0, 0.0] return self.objectPath def getObjectPath(self): return self.objectPath def authors(self, projectPath=''): """Return a catalog search result of authors from a project problem : same author appears several times """ auteurs = [] auteurIDs = [] context = aq_inner(self.context) #import pdb; pdb.set_trace() if not projectPath: projectPath = '/'.join(context.getPhysicalPath()) catalog = getToolByName(self.context, 'portal_catalog') #log( 'authors : ' + projectPath) cat = catalog(object_provides=[IAuteur.__identifier__], path={'query': projectPath, 'depth': 2}, sort_on="modified", sort_order="reverse") for auteur in cat: #print auteur.id, auteur.firstname, auteur.lastname, auteur.email if auteur.id not in auteurIDs: auteurs.append(auteur) auteurIDs.append(auteur.id) #import pdb; pdb.set_trace() return auteurs def getSponsoring(self): if self.withTotal: return self.degrevements[self.objectPath] else: return {} def sponsorasked(self,auteur): context = aq_inner(self.context) author = auteur.getObject() ordre = '' if author.school in schools.keys(): ordre = schools[author.school][1] oneauthor = "\n%s,%s,%s,%s,%s,%s,%s,%d,%d,%d"%(auteur.getPath().split('/')[-2],author.id,author.lastname, author.firstname,author.school,ordre, self.set2float(author.sponsorasked),self.set2float(author.sponsorSEM), self.set2float(author.sponsorRD),self.set2float(author.sponsorSchool)) self.allauthors += oneauthor if self.withTotal: self.degrevements[self.objectPath][0] += self.set2float(author.sponsorasked) self.degrevements[self.objectPath][1] += self.set2float(author.sponsorSEM) self.degrevements[self.objectPath][2] += self.set2float(author.sponsorRD) self.degrevements[self.objectPath][3] += self.set2float(author.sponsorSchool) self.degrevements[self.objectPath][4] += self.set2float(author.sponsorSchool) + \ self.set2float(author.sponsorRD) + self.set2float(author.sponsorSEM) return (author.sponsorasked,author.sponsorSEM,author.sponsorRD,author.sponsorSchool) def multiselect(self,indx='Subject',pathDepth=0): self.indx = indx self.pathDepth = pathDepth # 0 means everywhere catalog = getToolByName(self.context, 'portal_catalog') wtool = getToolByName(self.context, 'portal_workflow', None) if indx == 'Subject': keywords = catalog.uniqueValuesFor('Subject') self.multikey = '@@keywordview' label = u'Selectionner un ou plusieurs mots-clé' self.searchType = IProjet.__identifier__ else: keywords = catalog.uniqueValuesFor('review_state') self.multikey = '@@cyclesview' label = u'Selectionner un ou plusieurs états' self.searchType = ICycle.__identifier__ #print keywords form = factory('form', name='search', props={ 'action': self._form_action, }) form['searchterm'] = factory('#field:multiselect', props={ 'label': label, 'vocabulary': keywords, 'format': 'block', 'multivalued': True}) form['submit'] = factory( 'field:submit', props={ 'label': MessageFactory(u'Lancer la recherche'), 'submit.class': '', 'handler': self._form_handler, 'action': 'search' }) controller = Controller(form, self.request) return controller.rendered def results(self): if not hasattr(self,'searchterm') or not self.searchterm: return [] context = aq_inner(self.context) cat = getToolByName(self.context, 'portal_catalog') query = {} query[self.indx] = self.searchterm query['object_provides'] = self.searchType if self.pathDepth: localpath = {'query': '/'.join(context.getPhysicalPath()), 'depth': self.pathDepth} query['path'] = localpath #print query return cat(**query) def _form_action(self, widget, data): #import pdb; pdb.set_trace() #print "retour à ", self.context.absolute_url() return '%s/%s' % (self.context.absolute_url(),self.multikey) def _form_handler(self, widget, data): #import pdb; pdb.set_trace() self.searchterm = data['searchterm'].extracted def projets(self, wf_state='all'): """Return a catalog search result of projects to show """ context = aq_inner(self.context) catalog = getToolByName(context, 'portal_catalog') #log( "context's physical path : " + '/'.join(context.getPhysicalPath())) if wf_state == 'all': #log( "all projets") #log('/'.join(context.getPhysicalPath())) return catalog(portal_type='ageliaco.rd2.projet', path={'query': '/'.join(context.getPhysicalPath()), 'depth': 1}, sort_on="start", sort_order="reverse") #log('/'.join(context.getPhysicalPath())) cat = catalog(portal_type='ageliaco.rd2.projet', review_state=wf_state, path={'query': '/'.join(context.getPhysicalPath()), 'depth': 1}, sort_on='sortable_title') log('catalogue : %s items'%len(cat)) return cat def cycles(self, projectPath, wf_state='all'): """Return a catalog search result of cycles from a project """ #import pdb; pdb.set_trace() context = aq_inner(self.context) catalog = getToolByName(self.context, 'portal_catalog') #log( 'cycle : ' + projectPath) #log( wf_state + " state chosen") if wf_state == 'all': #log( "all cycles") cat = catalog(object_provides= ICycle.__identifier__, path={'query': projectPath, 'depth': 1}, sort_on="modified", sort_order="reverse") #print len(cat) return cat return catalog(object_provides=[ICycle.__identifier__], review_state=wf_state, path={'query': projectPath, 'depth': 2}, sort_on='sortable_title') def getPortal(self): return getSite()