diff --git a/tailbone/forms/widgets.py b/tailbone/forms/widgets.py index ad9d9c31..3dac0a6a 100644 --- a/tailbone/forms/widgets.py +++ b/tailbone/forms/widgets.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2021 Lance Edgar +# Copyright © 2010-2022 Lance Edgar # # This file is part of Rattail. # @@ -247,6 +247,7 @@ class JQueryAutocompleteWidget(dfwidget.AutocompleteInputWidget): template = 'autocomplete_jquery' requirements = None field_display = "" + assigned_label = None service_url = None cleared_callback = None selected_callback = None @@ -275,6 +276,7 @@ class JQueryAutocompleteWidget(dfwidget.AutocompleteInputWidget): kw['options'] = json.dumps(options) kw['field_display'] = self.field_display kw['cleared_callback'] = self.cleared_callback + kw['assigned_label'] = self.assigned_label kw.setdefault('selected_callback', self.selected_callback) tmpl_values = self.get_template_values(field, cstruct, kw) template = readonly and self.readonly_template or self.template diff --git a/tailbone/static/js/tailbone.buefy.autocomplete.js b/tailbone/static/js/tailbone.buefy.autocomplete.js index 53c41b40..ce0aece9 100644 --- a/tailbone/static/js/tailbone.buefy.autocomplete.js +++ b/tailbone/static/js/tailbone.buefy.autocomplete.js @@ -95,6 +95,22 @@ const TailboneAutocomplete = { } }, + watch: { + // TODO: yikes this feels hacky. what happens is, when the + // caller explicitly assigns a new UUID value to the tailbone + // autocomplate component, the underlying buefy autocomplete + // component was not getting the new value. so here we are + // explicitly making sure it is in sync. this issue was + // discovered on the "new vendor catalog batch" page + value(val) { + this.$nextTick(() => { + if (this.buefyValue != val) { + this.buefyValue = val + } + }) + }, + }, + methods: { // fetch new search results from the server. this is invoked diff --git a/tailbone/templates/autocomplete.mako b/tailbone/templates/autocomplete.mako index 7961d07c..8c84aedd 100644 --- a/tailbone/templates/autocomplete.mako +++ b/tailbone/templates/autocomplete.mako @@ -64,7 +64,7 @@ - {{ getDisplayText() }} (click to change) diff --git a/tailbone/templates/batch/vendorcatalog/create.mako b/tailbone/templates/batch/vendorcatalog/create.mako index 87d65c54..78b5b17d 100644 --- a/tailbone/templates/batch/vendorcatalog/create.mako +++ b/tailbone/templates/batch/vendorcatalog/create.mako @@ -3,6 +3,7 @@ <%def name="extra_javascript()"> ${parent.extra_javascript()} + % if not use_buefy: + % endif +<%def name="modify_this_page_vars()"> + ${parent.modify_this_page_vars()} + + + + ${parent.body()} diff --git a/tailbone/templates/deform/autocomplete_jquery.pt b/tailbone/templates/deform/autocomplete_jquery.pt index 1533cc2b..6e1a1e61 100644 --- a/tailbone/templates/deform/autocomplete_jquery.pt +++ b/tailbone/templates/deform/autocomplete_jquery.pt @@ -110,7 +110,8 @@ + initial-label="${field_display}" + tal:attributes=":assigned-label assigned_label or 'null';"> diff --git a/tailbone/templates/forms/deform_buefy.mako b/tailbone/templates/forms/deform_buefy.mako index 17ccf7d1..a26c946a 100644 --- a/tailbone/templates/forms/deform_buefy.mako +++ b/tailbone/templates/forms/deform_buefy.mako @@ -76,6 +76,8 @@ template: '#${form.component}-template', components: {}, props: {}, + watch: {}, + computed: {}, methods: { ## TODO: deprecate / remove the latter option here diff --git a/tailbone/templates/vendors/configure.mako b/tailbone/templates/vendors/configure.mako index 0bcb4a9e..121617b2 100644 --- a/tailbone/templates/vendors/configure.mako +++ b/tailbone/templates/vendors/configure.mako @@ -6,11 +6,11 @@

Display

- - + - Show vendor chooser as autocomplete field + Show vendor chooser as dropdown (select) element diff --git a/tailbone/views/batch/vendorcatalog.py b/tailbone/views/batch/vendorcatalog.py index 3668500a..dfd03ac9 100644 --- a/tailbone/views/batch/vendorcatalog.py +++ b/tailbone/views/batch/vendorcatalog.py @@ -30,15 +30,13 @@ import logging import six -from rattail.db import model, api -from rattail.vendors.catalogs import iter_catalog_parsers +from rattail.db import model import colander from deform import widget as dfwidget from webhelpers2.html import tags from tailbone import forms -from tailbone.db import Session from tailbone.views.batch import FileBatchMasterView from tailbone.diffs import Diff @@ -139,13 +137,9 @@ class VendorCatalogView(FileBatchMasterView): def get_parsers(self): if not hasattr(self, 'parsers'): - parsers = sorted(iter_catalog_parsers(), key=lambda p: p.display) - supported = self.rattail_config.getlist( - 'tailbone', 'batch.vendorcatalog.supported_parsers') - if supported: - parsers = [parser for parser in parsers - if parser.key in supported] - self.parsers = parsers + app = self.get_rattail_app() + vendor_handler = app.get_vendor_handler() + self.parsers = vendor_handler.get_supported_catalog_parsers() return self.parsers def configure_grid(self, g): @@ -160,24 +154,8 @@ class VendorCatalogView(FileBatchMasterView): def configure_form(self, f): super(VendorCatalogView, self).configure_form(f) - - # vendor - f.set_renderer('vendor', self.render_vendor) - if self.creating and 'vendor' in f: - f.replace('vendor', 'vendor_uuid') - f.set_node('vendor_uuid', colander.String()) - vendor_display = "" - if self.request.method == 'POST': - if self.request.POST.get('vendor_uuid'): - vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor_uuid']) - if vendor: - vendor_display = six.text_type(vendor) - vendors_url = self.request.route_url('vendors.autocomplete') - f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget( - field_display=vendor_display, service_url=vendors_url)) - f.set_label('vendor_uuid', "Vendor") - else: - f.set_readonly('vendor') + app = self.get_rattail_app() + vendor_handler = app.get_vendor_handler() # filename f.set_label('filename', "Catalog File") @@ -196,12 +174,75 @@ class VendorCatalogView(FileBatchMasterView): f.set_widget('parser_key', dfwidget.SelectWidget(values=values)) f.set_label('parser_key', "File Type") + # vendor + f.set_renderer('vendor', self.render_vendor) + if self.creating and 'vendor' in f: + f.replace('vendor', 'vendor_uuid') + f.set_label('vendor_uuid', "Vendor") + use_dropdown = vendor_handler.choice_uses_dropdown() + if use_dropdown: + vendors = self.Session.query(model.Vendor)\ + .order_by(model.Vendor.id) + vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, + vendor.name)) + for vendor in vendors] + f.set_widget('vendor_uuid', + dfwidget.SelectWidget(values=vendor_values)) + else: + vendor_display = "" + if self.request.method == 'POST': + if self.request.POST.get('vendor_uuid'): + vendor = self.Session.query(model.Vendor).get( + self.request.POST['vendor_uuid']) + if vendor: + vendor_display = six.text_type(vendor) + vendors_url = self.request.route_url('vendors.autocomplete') + f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget( + field_display=vendor_display, service_url=vendors_url, + assigned_label='vendorName')) + else: + f.set_readonly('vendor') + # effective if self.creating: f.remove('effective') else: f.set_readonly('effective') + def template_kwargs_create(self, **kwargs): + use_buefy = self.get_use_buefy() + app = self.get_rattail_app() + vendor_handler = app.get_vendor_handler() + parsers = self.get_parsers() + parsers_data = {} + for parser in parsers: + if use_buefy: + pdata = {'key': parser.key, + 'vendor_key': parser.vendor_key} + if parser.vendor_key: + vendor = vendor_handler.get_vendor(self.Session(), + parser.vendor_key) + if vendor: + pdata['vendor_uuid'] = vendor.uuid + pdata['vendor_name'] = vendor.name + parsers_data[parser.key] = pdata + else: + if parser.vendor_key: + vendor = vendor_handler.get_vendor(self.Session(), + parser.vendor_key) + if vendor: + parser.vendormap_value = "{{uuid: '{}', name: '{}'}}".format( + vendor.uuid, vendor.name.replace("'", "\\'")) + else: + log.warning("vendor '{}' not found for parser: {}".format( + parser.vendor_key, parser.key)) + parser.vendormap_value = 'null' + else: + parser.vendormap_value = 'null' + kwargs['parsers'] = parsers + kwargs['parsers_data'] = parsers_data + return kwargs + def get_batch_kwargs(self, batch): kwargs = super(VendorCatalogView, self).get_batch_kwargs(batch) kwargs['parser_key'] = batch.parser_key @@ -275,23 +316,6 @@ class VendorCatalogView(FileBatchMasterView): return kwargs - def template_kwargs_create(self, **kwargs): - parsers = self.get_parsers() - for parser in parsers: - if parser.vendor_key: - vendor = api.get_vendor(Session(), parser.vendor_key) - if vendor: - parser.vendormap_value = "{{uuid: '{}', name: '{}'}}".format( - vendor.uuid, vendor.name.replace("'", "\\'")) - else: - log.warning("vendor '{}' not found for parser: {}".format( - parser.vendor_key, parser.key)) - parser.vendormap_value = 'null' - else: - parser.vendormap_value = 'null' - kwargs['parsers'] = parsers - return kwargs - # TODO: deprecate / remove this VendorCatalogsView = VendorCatalogView diff --git a/tailbone/views/purchasing/batch.py b/tailbone/views/purchasing/batch.py index a4dab2aa..8a015838 100644 --- a/tailbone/views/purchasing/batch.py +++ b/tailbone/views/purchasing/batch.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2021 Lance Edgar +# Copyright © 2010-2022 Lance Edgar # # This file is part of Rattail. # @@ -29,7 +29,6 @@ from __future__ import unicode_literals, absolute_import import six from rattail.db import model, api -from rattail.time import localtime import colander from deform import widget as dfwidget @@ -230,7 +229,8 @@ class PurchasingBatchView(BatchMasterView): super(PurchasingBatchView, self).configure_form(f) model = self.model batch = f.model_instance - today = localtime(self.rattail_config).date() + app = self.get_rattail_app() + today = app.localtime().date() use_buefy = self.get_use_buefy() # mode @@ -265,9 +265,15 @@ class PurchasingBatchView(BatchMasterView): if self.creating: f.replace('vendor', 'vendor_uuid') f.set_label('vendor_uuid', "Vendor") - use_autocomplete = self.rattail_config.getbool( - 'rattail', 'vendor.use_autocomplete', default=True) - if use_autocomplete: + vendor_handler = app.get_vendor_handler() + use_dropdown = vendor_handler.choice_uses_dropdown() + if use_dropdown: + vendors = self.Session.query(model.Vendor)\ + .order_by(model.Vendor.id) + vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name)) + for vendor in vendors] + f.set_widget('vendor_uuid', dfwidget.SelectWidget(values=vendor_values)) + else: vendor_display = "" if self.request.method == 'POST': if self.request.POST.get('vendor_uuid'): @@ -277,12 +283,6 @@ class PurchasingBatchView(BatchMasterView): vendors_url = self.request.route_url('vendors.autocomplete') f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget( field_display=vendor_display, service_url=vendors_url)) - else: - vendors = self.Session.query(model.Vendor)\ - .order_by(model.Vendor.id) - vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name)) - for vendor in vendors] - f.set_widget('vendor_uuid', dfwidget.SelectWidget(values=vendor_values)) elif self.editing: f.set_readonly('vendor') diff --git a/tailbone/views/purchasing/costing.py b/tailbone/views/purchasing/costing.py index d790fbc1..2f467feb 100644 --- a/tailbone/views/purchasing/costing.py +++ b/tailbone/views/purchasing/costing.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2021 Lance Edgar +# Copyright © 2010-2022 Lance Edgar # # This file is part of Rattail. # @@ -200,9 +200,19 @@ class CostingBatchView(PurchasingBatchView): form.set_default('workflow', valid_workflows[0]) # configure vendor field - use_autocomplete = self.rattail_config.getbool( - 'rattail', 'vendor.use_autocomplete', default=True) - if use_autocomplete: + app = self.get_rattail_app() + vendor_handler = app.get_vendor_handler() + use_dropdown = vendor_handler.choice_uses_dropdown() + if use_dropdown: + vendors = self.Session.query(model.Vendor)\ + .order_by(model.Vendor.id) + vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name)) + for vendor in vendors] + if use_buefy: + form.set_widget('vendor', dfwidget.SelectWidget(values=vendor_values)) + else: + form.set_widget('vendor', forms.widgets.JQuerySelectWidget(values=vendor_values)) + else: vendor_display = "" if self.request.method == 'POST': if self.request.POST.get('vendor'): @@ -212,15 +222,6 @@ class CostingBatchView(PurchasingBatchView): vendors_url = self.request.route_url('vendors.autocomplete') form.set_widget('vendor', forms.widgets.JQueryAutocompleteWidget( field_display=vendor_display, service_url=vendors_url)) - else: - vendors = self.Session.query(model.Vendor)\ - .order_by(model.Vendor.id) - vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name)) - for vendor in vendors] - if use_buefy: - form.set_widget('vendor', dfwidget.SelectWidget(values=vendor_values)) - else: - form.set_widget('vendor', forms.widgets.JQuerySelectWidget(values=vendor_values)) # configure workflow field values = [(workflow['workflow_key'], workflow['display']) diff --git a/tailbone/views/purchasing/receiving.py b/tailbone/views/purchasing/receiving.py index 3664cdef..e481db82 100644 --- a/tailbone/views/purchasing/receiving.py +++ b/tailbone/views/purchasing/receiving.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2021 Lance Edgar +# Copyright © 2010-2022 Lance Edgar # # This file is part of Rattail. # @@ -294,9 +294,19 @@ class ReceivingBatchView(PurchasingBatchView): use_buefy=use_buefy) # configure vendor field - use_autocomplete = self.rattail_config.getbool( - 'rattail', 'vendor.use_autocomplete', default=True) - if use_autocomplete: + app = self.get_rattail_app() + vendor_handler = app.get_vendor_handler() + use_dropdown = vendor_handler.choice_uses_dropdown() + if use_dropdown: + vendors = self.Session.query(model.Vendor)\ + .order_by(model.Vendor.id) + vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name)) + for vendor in vendors] + if use_buefy: + form.set_widget('vendor', dfwidget.SelectWidget(values=vendor_values)) + else: + form.set_widget('vendor', forms.widgets.JQuerySelectWidget(values=vendor_values)) + else: vendor_display = "" if self.request.method == 'POST': if self.request.POST.get('vendor'): @@ -306,15 +316,6 @@ class ReceivingBatchView(PurchasingBatchView): vendors_url = self.request.route_url('vendors.autocomplete') form.set_widget('vendor', forms.widgets.JQueryAutocompleteWidget( field_display=vendor_display, service_url=vendors_url)) - else: - vendors = self.Session.query(model.Vendor)\ - .order_by(model.Vendor.id) - vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name)) - for vendor in vendors] - if use_buefy: - form.set_widget('vendor', dfwidget.SelectWidget(values=vendor_values)) - else: - form.set_widget('vendor', forms.widgets.JQuerySelectWidget(values=vendor_values)) # configure workflow field values = [(workflow['workflow_key'], workflow['display']) diff --git a/tailbone/views/vendors/core.py b/tailbone/views/vendors/core.py index bf73e1b1..36280738 100644 --- a/tailbone/views/vendors/core.py +++ b/tailbone/views/vendors/core.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2021 Lance Edgar +# Copyright © 2010-2022 Lance Edgar # # This file is part of Rattail. # @@ -175,7 +175,7 @@ class VendorView(MasterView): # display {'section': 'rattail', - 'option': 'vendor.use_autocomplete', + 'option': 'vendors.choice_uses_dropdown', 'type': bool}, ]