From a301cc40368d78d71e8fbabed122066cccd2618f Mon Sep 17 00:00:00 2001 From: "david.henne" Date: Tue, 21 Mar 2023 13:05:33 -0500 Subject: [PATCH 1/6] define castle choice field to override easyform choice default. --- castle/cms/easyform/configure.zcml | 17 ++++ castle/cms/easyform/field.py | 147 ++++++++++++++++++++++++++++- castle/cms/easyform/supermodel.py | 59 +++++++++++- castle/cms/easyform/terms.py | 17 +++- castle/cms/widgets.py | 7 ++ 5 files changed, 242 insertions(+), 5 deletions(-) diff --git a/castle/cms/easyform/configure.zcml b/castle/cms/easyform/configure.zcml index 5e5cb3f48..cfc0c54ce 100644 --- a/castle/cms/easyform/configure.zcml +++ b/castle/cms/easyform/configure.zcml @@ -26,6 +26,23 @@ name="castle.cms.easyform.field.QueryChoice" /> + + + + + + + + + + - Date: Fri, 24 Mar 2023 14:26:23 -0500 Subject: [PATCH 3/6] handle vocabulary value, add form validation. --- castle/cms/easyform/field.py | 60 +++++++++++++++++++++++++----------- castle/cms/widgets.py | 7 ----- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/castle/cms/easyform/field.py b/castle/cms/easyform/field.py index 683f2ecf8..42ef8df7f 100644 --- a/castle/cms/easyform/field.py +++ b/castle/cms/easyform/field.py @@ -2,7 +2,7 @@ from plone.uuid.interfaces import IUUID from castle.cms.utils import parse_query_from_data -from castle.cms.widgets import CastleFieldWidget, QueryFieldWidget +from castle.cms.widgets import QueryFieldWidget from plone.autoform import directives as form from plone.schemaeditor.fields import FieldFactory from plone.schemaeditor.fields import TextLineChoiceField @@ -14,6 +14,8 @@ from zope.i18nmessageid import MessageFactory from zope.interface import alsoProvides from zope.interface import implementer +from zope.interface import Invalid +from zope.interface import invariant from zope.schema.interfaces import IChoice from zope.schema.interfaces import IContextSourceBinder from zope.schema.interfaces import IField @@ -180,7 +182,13 @@ def get_cache_key(self, context): def __call__(self, context): if self.field.possible_values == []: - return SimpleVocabulary([]) + if self.field.vocabulary_name == None: + return SimpleVocabulary([]) + else: + # TODO: use vocab selection if there are no fields input. + # get name of vocabulary from vocabulary_name value and lookup all vocab terms associated with it + thing = 'vocabulary: %s' % self.field.vocabulary_name + return SimpleVocabulary([SimpleVocabulary.createTerm(thing, thing, thing)]) else: default_none_val = SimpleVocabulary.createTerm(None, None, None) terms = [default_none_val] @@ -199,23 +207,31 @@ class ICastleChoice(IChoice): possible_values = schema.List( title=u'Possible values', description=u'Enter allowed choices one per line.', - value_type=schema.TextLine() + value_type=schema.TextLine(), + required=False + ) + + vocabulary_name = schema.Choice( + title=u'Vocabulary name', + description=u'Vocabulary name to lookup in the vocabulary registry', + default=u'', + vocabulary='plone.app.vocabularies.Groups', + required=False ) - # vocabulary_name = schema.Choice( - # title=u'Vocabulary name', - # description=u'Vocabulary name to lookup in the vocabulary registry', - # default=u'', - # vocabulary='castle.cms.vocabularies.MimeTypes' - # ) + @invariant + def validate(data): + if data.possible_values and data.vocabulary_name: + msg = 'You can not set a vocabulary name AND vocabulary values. Please clear values field or set "No value" for vocabulary name.' + raise Invalid(_(msg)) @implementer(ICastleChoice) class CastleChoice(schema.Choice): - def __init__(self, possible_values=[], **kw): + def __init__(self, possible_values=[], vocabulary_name=None, **kw): self.possible_values = possible_values - # self.vocabulary_name = vocabulary_name + self.vocabulary_name = vocabulary_name kw['source'] = CastleChoiceSource(self) # bind to field super(CastleChoice, self).__init__(**kw) @@ -229,15 +245,23 @@ class ICastleChoiceFieldSchema(IField): possible_values = schema.List( title=u'Possible values', description=u'Enter allowed choices one per line.', - value_type=schema.TextLine() + value_type=schema.TextLine(), + required=False + ) + + vocabulary_name = schema.Choice( + title=u'Vocabulary name', + description=u'Vocabulary name to lookup in the vocabulary registry', + default=u'', + vocabulary='plone.app.vocabularies.Groups', + required=False ) - # vocabulary_name = schema.Choice( - # title=u'Vocabulary name', - # description=u'Vocabulary name to lookup in the vocabulary registry', - # default=u'', - # vocabulary='castle.cms.vocabularies.MimeTypes' - # ) + @invariant + def validate(data): + if data.possible_values and data.vocabulary_name: + msg = 'You can not set a vocabulary name AND vocabulary values. Please clear values field or set "No value" for vocabulary name.' + raise Invalid(_(msg)) @implementer(IFieldEditFormSchema) diff --git a/castle/cms/widgets.py b/castle/cms/widgets.py index fcb309454..deede71c1 100644 --- a/castle/cms/widgets.py +++ b/castle/cms/widgets.py @@ -197,13 +197,6 @@ def QueryFieldWidget(field, request): return z3c.form.widget.FieldWidget(field, QueryStringWidget(request)) -# TODO: widget definition -@adapter(IField, ICastleLayer) -@implementer(IFieldWidget) -def CastleFieldWidget(field, request): - return z3c.form.widget.FieldWidget(field, QueryStringWidget(request)) - - @adapter(IField, ICastleLayer) @implementer(IFieldWidget) def RelatedItemsFieldWidget(field, request): From 1f02accac766d40cb3a9d49d50f2c1d2bc63cc15 Mon Sep 17 00:00:00 2001 From: "david.henne" Date: Wed, 29 Mar 2023 15:11:03 -0500 Subject: [PATCH 4/6] use strictly Castle defined vocabularies for easyform choice field. --- castle/cms/easyform/field.py | 25 ++++++++++++------------- castle/cms/vocabularies.py | 11 +++++++++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/castle/cms/easyform/field.py b/castle/cms/easyform/field.py index 42ef8df7f..f4bef2168 100644 --- a/castle/cms/easyform/field.py +++ b/castle/cms/easyform/field.py @@ -2,6 +2,7 @@ from plone.uuid.interfaces import IUUID from castle.cms.utils import parse_query_from_data +from castle.cms.vocabularies import castle_vocabularies from castle.cms.widgets import QueryFieldWidget from plone.autoform import directives as form from plone.schemaeditor.fields import FieldFactory @@ -167,8 +168,6 @@ class TextLineQueryChoiceField(TextLineChoiceField): pass -# TODO: -#! --------------- CASTLE CHOICE SCHEMA --------------- @implementer(IContextSourceBinder) class CastleChoiceSource(object): __name__ = 'CastleChoiceSource' @@ -181,20 +180,22 @@ def get_cache_key(self, context): IUUID(context, 'default'), self.field.__name__) def __call__(self, context): + default_none_val = SimpleVocabulary.createTerm(None, None, None) if self.field.possible_values == []: if self.field.vocabulary_name == None: return SimpleVocabulary([]) else: - # TODO: use vocab selection if there are no fields input. - # get name of vocabulary from vocabulary_name value and lookup all vocab terms associated with it - thing = 'vocabulary: %s' % self.field.vocabulary_name - return SimpleVocabulary([SimpleVocabulary.createTerm(thing, thing, thing)]) + try: + vocab = castle_vocabularies[self.field.vocabulary_name](context) + except TypeError: + vocab = castle_vocabularies[self.field.vocabulary_name] + vocab._terms.insert(0, default_none_val) + return vocab else: - default_none_val = SimpleVocabulary.createTerm(None, None, None) terms = [default_none_val] - for item in self.field.possible_values: + for term in self.field.possible_values: terms.append( - SimpleVocabulary.createTerm(item, item, item)) + SimpleVocabulary.createTerm(term, term, term)) return SimpleVocabulary(terms) @@ -214,8 +215,7 @@ class ICastleChoice(IChoice): vocabulary_name = schema.Choice( title=u'Vocabulary name', description=u'Vocabulary name to lookup in the vocabulary registry', - default=u'', - vocabulary='plone.app.vocabularies.Groups', + values=castle_vocabularies.keys(), required=False ) @@ -252,8 +252,7 @@ class ICastleChoiceFieldSchema(IField): vocabulary_name = schema.Choice( title=u'Vocabulary name', description=u'Vocabulary name to lookup in the vocabulary registry', - default=u'', - vocabulary='plone.app.vocabularies.Groups', + values=castle_vocabularies.keys(), required=False ) diff --git a/castle/cms/vocabularies.py b/castle/cms/vocabularies.py index 480d7ed55..05adb89bd 100644 --- a/castle/cms/vocabularies.py +++ b/castle/cms/vocabularies.py @@ -380,3 +380,14 @@ def make_terms(brains1, brains2): included_brains.append(brain['UID']) return [SimpleTerm(value=result[0], token=result[0], title=result[1]) for result in results] + + +castle_vocabularies = { + 'Countries': CountriesVocabularyFactory, + 'Friendly Types': ReallyUserFriendlyTypesVocabularyFactory, + 'Business Types': BusinessTypesVocabulary, + 'Survey': SurveyVocabulary, + 'Email Category': EmailCategoryVocabulary, + 'Mime Types': MimeTypeVocabulary, + 'Locations': LocationsVocabulary +} From 5679e7809449b9924b2f321d502bd5aabf2c08e2 Mon Sep 17 00:00:00 2001 From: "david.henne" Date: Thu, 30 Mar 2023 12:48:55 -0500 Subject: [PATCH 5/6] rename choice field --- castle/cms/easyform/field.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/castle/cms/easyform/field.py b/castle/cms/easyform/field.py index f4bef2168..23aea05b7 100644 --- a/castle/cms/easyform/field.py +++ b/castle/cms/easyform/field.py @@ -237,7 +237,7 @@ def __init__(self, possible_values=[], vocabulary_name=None, **kw): CastleChoiceFactory = FieldFactory( - CastleChoice, _(u'label_castle_choice_field', default=u'Castle Choice'), + CastleChoice, _(u'label_castle_choice_field', default=u'Choice (no default value)'), source=CastleChoiceSource) From f76b4025b315244f2cd319c6c0a0d9b25c01e851 Mon Sep 17 00:00:00 2001 From: "david.henne" Date: Thu, 30 Mar 2023 12:52:56 -0500 Subject: [PATCH 6/6] remove 'todo:' --- castle/cms/easyform/supermodel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/castle/cms/easyform/supermodel.py b/castle/cms/easyform/supermodel.py index 3cd31d4d1..32295207e 100644 --- a/castle/cms/easyform/supermodel.py +++ b/castle/cms/easyform/supermodel.py @@ -65,7 +65,6 @@ def write(self, field, name, type, elementName='field'): QueryChoiceImportExportHandler = QueryChoiceHandler(QueryChoice) -# TODO: class CastleChoiceHandler(plone.supermodel.exportimport.ChoiceHandler): """ Extend/override ChoiceHandler to work for CastleChoice field