diff --git a/browser/common.py b/browser/common.py index 1e400cb..ef4ef49 100644 --- a/browser/common.py +++ b/browser/common.py @@ -269,7 +269,10 @@ class BaseView(GenericView, I18NView): for c in cr: try: principal = pau.getPrincipal(c) - creators.append(principal.title) + if principal is None: + creators.append(c) + else: + creators.append(principal.title) except PrincipalLookupError: creators.append(c) return creators diff --git a/browser/concept_macros.pt b/browser/concept_macros.pt index 76083e0..3c700bc 100644 --- a/browser/concept_macros.pt +++ b/browser/concept_macros.pt @@ -173,7 +173,7 @@

Resources

+ + + + + + diff --git a/expert/field.py b/expert/field.py index 5664c54..d87165a 100644 --- a/expert/field.py +++ b/expert/field.py @@ -20,7 +20,10 @@ Field definitions for reports. """ +from zope.app.form.browser.interfaces import ITerms +from zope import component from zope.i18n.locales import locales +from zope.schema.interfaces import IVocabularyFactory, IContextSourceBinder from cybertools.composer.report.field import Field from cybertools.composer.report.result import ResultSet @@ -41,7 +44,9 @@ class TextField(Field): class DecimalField(Field): - format = '###,###,##0.##' + format = 'decimal' + pattern = u'#,##0.00;-#,##0.00' + renderer = 'right' def getDisplayValue(self, row): value = self.getRawValue(row) @@ -53,8 +58,8 @@ class DecimalField(Field): langInfo = nv and getattr(nv, 'languageInfo', None) or None if langInfo: locale = locales.getLocale(langInfo.language) - fmt = locale.numbers.getFormatter('decimal') - return fmt.format(value) + fmt = locale.numbers.getFormatter(self.format) + return fmt.format(value, pattern=self.pattern) return '%.2f' % value @@ -78,6 +83,52 @@ class DateField(Field): return value.isoformat()[:10] +class VocabularyField(Field): + + vocabulary = None + + def getDisplayValue(self, row): + value = self.getRawValue(row) + if self.vocabulary is None: + return value + items = self.getVocabularyItems(row) + for item in items: + if item['token'] == value: + return item['title'] + + def getVocabularyItems(self, row): + context = row.context + request = row.parent.context.view.request + voc = self.vocabulary + if isinstance(voc, basestring): + terms = self.getVocabularyTerms(voc, context, request) + if terms is not None: + return terms + voc = voc.splitlines() + return [dict(token=t, title=t) for t in voc if t.strip()] + elif IContextSourceBinder.providedBy(voc): + source = voc(row.parent.context) + terms = component.queryMultiAdapter((source, request), ITerms) + if terms is not None: + termsList = [terms.getTerm(value) for value in source] + return [dict(token=t.token, title=t.title) for t in termsList] + else: + return [] + return [dict(token=t.token, title=t.title or t.value) for t in voc] + + def getVocabularyTerms(self, name, context, request): + if context is None or request is None: + return None + source = component.queryUtility(IVocabularyFactory, name=name) + if source is not None: + source = source(context) + terms = component.queryMultiAdapter((source, request), ITerms) + if terms is not None: + termsList = [terms.getTerm(value) for value in source] + return [dict(token=t.token, title=t.title) for t in termsList] + return None + + class UrlField(Field): renderer = 'target' diff --git a/external/element.py b/external/element.py index 5c48146..1490dd2 100644 --- a/external/element.py +++ b/external/element.py @@ -93,7 +93,7 @@ class ConceptElement(Element): formState = self.getInstance().applyTemplate(data=kw, ignoreValidation=True) # simple hack for resolving interface definition: pi = self.get('predicateInterface') - if pi is not None: + if pi: adapted(self.object).predicateInterface = resolve(pi) def getInstance(self, omit=['title']):