diff --git a/tailbone/config.py b/tailbone/config.py index 5553924e..875bc25b 100644 --- a/tailbone/config.py +++ b/tailbone/config.py @@ -51,3 +51,8 @@ class ConfigExtension(BaseExtension): # provide default theme selection config.setdefault('tailbone', 'themes', 'default, falafel') config.setdefault('tailbone', 'themes.expose_picker', 'true') + + +def legacy_mobile_enabled(config): + return config.getbool('tailbone', 'legacy_mobile.enabled', + default=True) diff --git a/tailbone/views/auth.py b/tailbone/views/auth.py index 2dd37e2c..4765e8e8 100644 --- a/tailbone/views/auth.py +++ b/tailbone/views/auth.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2018 Lance Edgar +# Copyright © 2010-2020 Lance Edgar # # This file is part of Rattail. # @@ -206,6 +206,8 @@ class AuthenticationView(View): @classmethod def defaults(cls, config): + rattail_config = config.registry.settings.get('rattail_config') + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) # forbidden config.add_forbidden_view(cls, attr='forbidden') @@ -213,14 +215,16 @@ class AuthenticationView(View): # login config.add_route('login', '/login') config.add_view(cls, attr='login', route_name='login', renderer='/login.mako') - config.add_route('mobile.login', '/mobile/login') - config.add_view(cls, attr='mobile_login', route_name='mobile.login', renderer='/mobile/login.mako') + if legacy_mobile: + config.add_route('mobile.login', '/mobile/login') + config.add_view(cls, attr='mobile_login', route_name='mobile.login', renderer='/mobile/login.mako') # logout config.add_route('logout', '/logout') config.add_view(cls, attr='logout', route_name='logout') - config.add_route('mobile.logout', '/mobile/logout') - config.add_view(cls, attr='mobile_logout', route_name='mobile.logout') + if legacy_mobile: + config.add_route('mobile.logout', '/mobile/logout') + config.add_view(cls, attr='mobile_logout', route_name='mobile.logout') # no-op config.add_route('noop', '/noop') diff --git a/tailbone/views/batch/core.py b/tailbone/views/batch/core.py index e3e14ee8..fff98730 100644 --- a/tailbone/views/batch/core.py +++ b/tailbone/views/batch/core.py @@ -1489,12 +1489,14 @@ class BatchMasterView(MasterView): @classmethod def _batch_defaults(cls, config): + rattail_config = config.registry.settings.get('rattail_config') model_key = cls.get_model_key() route_prefix = cls.get_route_prefix() url_prefix = cls.get_url_prefix() permission_prefix = cls.get_permission_prefix() model_title = cls.get_model_title() model_title_plural = cls.get_model_title_plural() + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) # TODO: currently must do this here (in addition to `_defaults()` or # else the perm group label will not display correctly... @@ -1538,14 +1540,16 @@ class BatchMasterView(MasterView): permission='{}.edit'.format(permission_prefix)) # mobile mark complete - config.add_route('mobile.{}.mark_complete'.format(route_prefix), '/mobile{}/{{{}}}/mark-complete'.format(url_prefix, model_key)) - config.add_view(cls, attr='mobile_mark_complete', route_name='mobile.{}.mark_complete'.format(route_prefix), - permission='{}.edit'.format(permission_prefix)) + if legacy_mobile: + config.add_route('mobile.{}.mark_complete'.format(route_prefix), '/mobile{}/{{{}}}/mark-complete'.format(url_prefix, model_key)) + config.add_view(cls, attr='mobile_mark_complete', route_name='mobile.{}.mark_complete'.format(route_prefix), + permission='{}.edit'.format(permission_prefix)) # mobile mark pending - config.add_route('mobile.{}.mark_pending'.format(route_prefix), '/mobile{}/{{{}}}/mark-pending'.format(url_prefix, model_key)) - config.add_view(cls, attr='mobile_mark_pending', route_name='mobile.{}.mark_pending'.format(route_prefix), - permission='{}.edit'.format(permission_prefix)) + if legacy_mobile: + config.add_route('mobile.{}.mark_pending'.format(route_prefix), '/mobile{}/{{{}}}/mark-pending'.format(url_prefix, model_key)) + config.add_view(cls, attr='mobile_mark_pending', route_name='mobile.{}.mark_pending'.format(route_prefix), + permission='{}.edit'.format(permission_prefix)) # refresh multiple batches (results) if cls.results_refreshable: diff --git a/tailbone/views/batch/inventory.py b/tailbone/views/batch/inventory.py index 843b7061..fd4b9b07 100644 --- a/tailbone/views/batch/inventory.py +++ b/tailbone/views/batch/inventory.py @@ -634,6 +634,7 @@ class InventoryBatchView(BatchMasterView): route_prefix = cls.get_route_prefix() url_prefix = cls.get_url_prefix() permission_prefix = cls.get_permission_prefix() + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) # we need batch handler to determine available permissions factory = cls.get_handler_factory(rattail_config) @@ -655,9 +656,10 @@ class InventoryBatchView(BatchMasterView): renderer='json', permission='{}.create_row'.format(permission_prefix)) # mobile - make new row from UPC - config.add_route('mobile.{}.row_from_upc'.format(route_prefix), '/mobile{}/{{{}}}/row-from-upc'.format(url_prefix, model_key)) - config.add_view(cls, attr='mobile_row_from_upc', route_name='mobile.{}.row_from_upc'.format(route_prefix), - permission='{}.create_row'.format(permission_prefix)) + if legacy_mobile: + config.add_route('mobile.{}.row_from_upc'.format(route_prefix), '/mobile{}/{{{}}}/row-from-upc'.format(url_prefix, model_key)) + config.add_view(cls, attr='mobile_row_from_upc', route_name='mobile.{}.row_from_upc'.format(route_prefix), + permission='{}.create_row'.format(permission_prefix)) # TODO: this is a stopgap measure to fix an obvious bug, which exists when the diff --git a/tailbone/views/common.py b/tailbone/views/common.py index dd02e614..a118de7e 100644 --- a/tailbone/views/common.py +++ b/tailbone/views/common.py @@ -189,6 +189,7 @@ class CommonView(View): @classmethod def _defaults(cls, config): rattail_config = config.registry.settings.get('rattail_config') + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) # auto-correct URLs which require trailing slash config.add_notfound_view(cls, attr='notfound', append_slash=True) @@ -203,8 +204,9 @@ class CommonView(View): # home config.add_route('home', '/') config.add_view(cls, attr='home', route_name='home', renderer='/home.mako') - config.add_route('mobile.home', '/mobile/') - config.add_view(cls, attr='mobile_home', route_name='mobile.home', renderer='/mobile/home.mako') + if legacy_mobile: + config.add_route('mobile.home', '/mobile/') + config.add_view(cls, attr='mobile_home', route_name='mobile.home', renderer='/mobile/home.mako') # robots.txt config.add_route('robots.txt', '/robots.txt') @@ -213,8 +215,9 @@ class CommonView(View): # about config.add_route('about', '/about') config.add_view(cls, attr='about', route_name='about', renderer='/about.mako') - config.add_route('mobile.about', '/mobile/about') - config.add_view(cls, attr='about', route_name='mobile.about', renderer='/mobile/about.mako') + if legacy_mobile: + config.add_route('mobile.about', '/mobile/about') + config.add_view(cls, attr='about', route_name='mobile.about', renderer='/mobile/about.mako') # change db engine config.add_tailbone_permission('common', 'common.change_db_engine', @@ -234,9 +237,10 @@ class CommonView(View): config.add_route('feedback', '/feedback', request_method='POST') config.add_view(cls, attr='feedback', route_name='feedback', renderer='json', permission='common.feedback') - config.add_route('mobile.feedback', '/mobile/feedback', request_method='POST') - config.add_view(cls, attr='mobile_feedback', route_name='mobile.feedback', - renderer='json', permission='common.feedback') + if legacy_mobile: + config.add_route('mobile.feedback', '/mobile/feedback', request_method='POST') + config.add_view(cls, attr='mobile_feedback', route_name='mobile.feedback', + renderer='json', permission='common.feedback') # consume batch ID config.add_tailbone_permission('common', 'common.consume_batch_id', diff --git a/tailbone/views/core.py b/tailbone/views/core.py index 7e7a7cee..79a6c797 100644 --- a/tailbone/views/core.py +++ b/tailbone/views/core.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2019 Lance Edgar +# Copyright © 2010-2020 Lance Edgar # # This file is part of Rattail. # @@ -41,6 +41,7 @@ from tailbone.db import Session from tailbone.auth import logout_user from tailbone.progress import SessionProgress from tailbone.util import should_use_buefy +from tailbone.config import legacy_mobile_enabled class View(object): @@ -88,6 +89,14 @@ class View(object): """ return should_use_buefy(self.request) + @classmethod + def legacy_mobile_enabled(cls, rattail_config): + """ + Returns the boolean setting indicating whether the old / "legacy" + (jQuery) mobile app/site should be exposed. + """ + return legacy_mobile_enabled(rattail_config) + def late_login_user(self): """ Returns the :class:`rattail:rattail.db.model.User` instance diff --git a/tailbone/views/datasync.py b/tailbone/views/datasync.py index 688a479a..309b3bc2 100644 --- a/tailbone/views/datasync.py +++ b/tailbone/views/datasync.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2019 Lance Edgar +# Copyright © 2010-2020 Lance Edgar # # This file is part of Rattail. # @@ -94,6 +94,8 @@ class DataSyncChangesView(MasterView): @classmethod def defaults(cls, config): + rattail_config = config.registry.settings.get('rattail_config') + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) # fix permission group title config.add_tailbone_permission_group('datasync', label="DataSync") @@ -104,9 +106,10 @@ class DataSyncChangesView(MasterView): config.add_route('datasync.restart', '/datasync/restart') config.add_view(cls, attr='restart', route_name='datasync.restart', permission='datasync.restart') # mobile - config.add_route('datasync.mobile', '/mobile/datasync/') - config.add_view(cls, attr='mobile_index', route_name='datasync.mobile', - permission='datasync.restart', renderer='/mobile/datasync.mako') + if legacy_mobile: + config.add_route('datasync.mobile', '/mobile/datasync/') + config.add_view(cls, attr='mobile_index', route_name='datasync.mobile', + permission='datasync.restart', renderer='/mobile/datasync.mako') cls._defaults(config) diff --git a/tailbone/views/master.py b/tailbone/views/master.py index 4a16927c..d7bc8bdb 100644 --- a/tailbone/views/master.py +++ b/tailbone/views/master.py @@ -3593,6 +3593,7 @@ class MasterView(View): model_title_plural = cls.get_model_title_plural() if cls.has_rows: row_model_title = cls.get_row_model_title() + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) config.add_tailbone_permission_group(permission_prefix, model_title_plural, overwrite=False) @@ -3603,7 +3604,7 @@ class MasterView(View): config.add_route(route_prefix, '{}/'.format(url_prefix)) config.add_view(cls, attr='index', route_name=route_prefix, permission='{}.list'.format(permission_prefix)) - if cls.supports_mobile: + if legacy_mobile and cls.supports_mobile: config.add_route('mobile.{}'.format(route_prefix), '/mobile{}/'.format(url_prefix)) config.add_view(cls, attr='mobile_index', route_name='mobile.{}'.format(route_prefix), permission='{}.list'.format(permission_prefix)) @@ -3632,14 +3633,14 @@ class MasterView(View): permission='{}.quickie'.format(permission_prefix)) # create - if cls.creatable or cls.mobile_creatable: + if cls.creatable or (legacy_mobile and cls.mobile_creatable): config.add_tailbone_permission(permission_prefix, '{}.create'.format(permission_prefix), "Create new {}".format(model_title)) if cls.creatable: config.add_route('{}.create'.format(route_prefix), '{}/new'.format(url_prefix)) config.add_view(cls, attr='create', route_name='{}.create'.format(route_prefix), permission='{}.create'.format(permission_prefix)) - if cls.mobile_creatable: + if legacy_mobile and cls.mobile_creatable: config.add_route('mobile.{}.create'.format(route_prefix), '/mobile{}/new'.format(url_prefix)) config.add_view(cls, attr='mobile_create', route_name='mobile.{}.create'.format(route_prefix), permission='{}.create'.format(permission_prefix)) @@ -3709,7 +3710,7 @@ class MasterView(View): config.add_route('{}.view'.format(route_prefix), instance_url_prefix) config.add_view(cls, attr='view', route_name='{}.view'.format(route_prefix), permission='{}.view'.format(permission_prefix)) - if cls.supports_mobile: + if legacy_mobile and cls.supports_mobile: config.add_route('mobile.{}.view'.format(route_prefix), '/mobile{}'.format(instance_url_prefix)) config.add_view(cls, attr='mobile_view', route_name='mobile.{}.view'.format(route_prefix), permission='{}.view'.format(permission_prefix)) @@ -3762,27 +3763,27 @@ class MasterView(View): "Download associated data for {}".format(model_title)) # edit - if cls.editable or cls.mobile_editable: + if cls.editable or (legacy_mobile and cls.mobile_editable): config.add_tailbone_permission(permission_prefix, '{}.edit'.format(permission_prefix), "Edit {}".format(model_title)) if cls.editable: config.add_route('{}.edit'.format(route_prefix), '{}/edit'.format(instance_url_prefix)) config.add_view(cls, attr='edit', route_name='{}.edit'.format(route_prefix), permission='{}.edit'.format(permission_prefix)) - if cls.mobile_editable: + if legacy_mobile and cls.mobile_editable: config.add_route('mobile.{}.edit'.format(route_prefix), '/mobile{}/edit'.format(instance_url_prefix)) config.add_view(cls, attr='mobile_edit', route_name='mobile.{}.edit'.format(route_prefix), permission='{}.edit'.format(permission_prefix)) # execute - if cls.executable or cls.mobile_executable: + if cls.executable or (legacy_mobile and cls.mobile_executable): config.add_tailbone_permission(permission_prefix, '{}.execute'.format(permission_prefix), "Execute {}".format(model_title)) if cls.executable: config.add_route('{}.execute'.format(route_prefix), '{}/execute'.format(instance_url_prefix)) config.add_view(cls, attr='execute', route_name='{}.execute'.format(route_prefix), permission='{}.execute'.format(permission_prefix)) - if cls.mobile_executable: + if legacy_mobile and cls.mobile_executable: config.add_route('mobile.{}.execute'.format(route_prefix), '/mobile{}/execute'.format(instance_url_prefix)) config.add_view(cls, attr='mobile_execute', route_name='mobile.{}.execute'.format(route_prefix), permission='{}.execute'.format(permission_prefix)) @@ -3820,14 +3821,14 @@ class MasterView(View): # create row if cls.has_rows: - if cls.rows_creatable or cls.mobile_rows_creatable: + if cls.rows_creatable or (legacy_mobile and cls.mobile_rows_creatable): config.add_tailbone_permission(permission_prefix, '{}.create_row'.format(permission_prefix), "Create new {} rows".format(model_title)) if cls.rows_creatable: config.add_route('{}.create_row'.format(route_prefix), '{}/new-row'.format(instance_url_prefix)) config.add_view(cls, attr='create_row', route_name='{}.create_row'.format(route_prefix), permission='{}.create_row'.format(permission_prefix)) - if cls.mobile_rows_creatable: + if legacy_mobile and cls.mobile_rows_creatable: config.add_route('mobile.{}.create_row'.format(route_prefix), '/mobile{}/new-row'.format(instance_url_prefix)) config.add_view(cls, attr='mobile_create_row', route_name='mobile.{}.create_row'.format(route_prefix), permission='{}.create_row'.format(permission_prefix)) @@ -3842,35 +3843,35 @@ class MasterView(View): config.add_route('{}.view_row'.format(route_prefix), '{}/{{uuid}}/rows/{{row_uuid}}'.format(url_prefix)) config.add_view(cls, attr='view_row', route_name='{}.view_row'.format(route_prefix), permission='{}.view'.format(permission_prefix)) - if cls.mobile_rows_viewable: + if legacy_mobile and cls.mobile_rows_viewable: config.add_route('mobile.{}.view_row'.format(route_prefix), '/mobile{}/{{uuid}}/rows/{{row_uuid}}'.format(url_prefix)) config.add_view(cls, attr='mobile_view_row', route_name='mobile.{}.view_row'.format(route_prefix), permission='{}.view'.format(permission_prefix)) # edit row if cls.has_rows: - if cls.rows_editable or cls.mobile_rows_editable: + if cls.rows_editable or (legacy_mobile and cls.mobile_rows_editable): config.add_tailbone_permission(permission_prefix, '{}.edit_row'.format(permission_prefix), "Edit individual {} rows".format(model_title)) if cls.rows_editable: config.add_route('{}.edit_row'.format(route_prefix), '{}/{{uuid}}/rows/{{row_uuid}}/edit'.format(url_prefix)) config.add_view(cls, attr='edit_row', route_name='{}.edit_row'.format(route_prefix), permission='{}.edit_row'.format(permission_prefix)) - if cls.mobile_rows_editable: + if legacy_mobile and cls.mobile_rows_editable: config.add_route('mobile.{}.edit_row'.format(route_prefix), '/mobile{}/{{uuid}}/rows/{{row_uuid}}/edit'.format(url_prefix)) config.add_view(cls, attr='mobile_edit_row', route_name='mobile.{}.edit_row'.format(route_prefix), permission='{}.edit_row'.format(permission_prefix)) # delete row if cls.has_rows: - if cls.rows_deletable or cls.mobile_rows_deletable: + if cls.rows_deletable or (legacy_mobile and cls.mobile_rows_deletable): config.add_tailbone_permission(permission_prefix, '{}.delete_row'.format(permission_prefix), "Delete individual {} rows".format(model_title)) if cls.rows_deletable: config.add_route('{}.delete_row'.format(route_prefix), '{}/{{uuid}}/rows/{{row_uuid}}/delete'.format(url_prefix)) config.add_view(cls, attr='delete_row', route_name='{}.delete_row'.format(route_prefix), permission='{}.delete_row'.format(permission_prefix)) - if cls.mobile_rows_deletable: + if legacy_mobile and cls.mobile_rows_deletable: config.add_route('mobile.{}.delete_row'.format(route_prefix), '/mobile{}/{{uuid}}/rows/{{row_uuid}}/delete'.format(url_prefix)) config.add_view(cls, attr='mobile_delete_row', route_name='mobile.{}.delete_row'.format(route_prefix), permission='{}.delete_row'.format(permission_prefix)) diff --git a/tailbone/views/products.py b/tailbone/views/products.py index bfe01fc1..8a2c3d0c 100644 --- a/tailbone/views/products.py +++ b/tailbone/views/products.py @@ -1651,11 +1651,13 @@ class ProductsView(MasterView): @classmethod def _product_defaults(cls, config): + rattail_config = config.registry.settings.get('rattail_config') route_prefix = cls.get_route_prefix() url_prefix = cls.get_url_prefix() template_prefix = cls.get_template_prefix() permission_prefix = cls.get_permission_prefix() model_title = cls.get_model_title() + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) # print labels config.add_tailbone_permission('products', 'products.print_labels', @@ -1683,8 +1685,9 @@ class ProductsView(MasterView): config.add_view(cls, attr='image', route_name='products.image') # mobile quick lookup - config.add_route('mobile.products.quick_lookup', '/mobile/products/quick-lookup') - config.add_view(cls, attr='mobile_quick_lookup', route_name='mobile.products.quick_lookup') + if legacy_mobile: + config.add_route('mobile.products.quick_lookup', '/mobile/products/quick-lookup') + config.add_view(cls, attr='mobile_quick_lookup', route_name='mobile.products.quick_lookup') class ProductsAutocomplete(AutocompleteView): diff --git a/tailbone/views/purchasing/batch.py b/tailbone/views/purchasing/batch.py index 96f0d18c..97a002d3 100644 --- a/tailbone/views/purchasing/batch.py +++ b/tailbone/views/purchasing/batch.py @@ -975,11 +975,13 @@ class PurchasingBatchView(BatchMasterView): @classmethod def _purchasing_defaults(cls, config): + rattail_config = config.registry.settings.get('rattail_config') route_prefix = cls.get_route_prefix() url_prefix = cls.get_url_prefix() permission_prefix = cls.get_permission_prefix() model_key = cls.get_model_key() model_title = cls.get_model_title() + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) # eligible purchases (AJAX) config.add_route('{}.eligible_purchases'.format(route_prefix), '{}/eligible-purchases'.format(url_prefix)) @@ -987,7 +989,7 @@ class PurchasingBatchView(BatchMasterView): renderer='json', permission='{}.view'.format(permission_prefix)) # add new product - if cls.supports_new_product: + if legacy_mobile and cls.supports_new_product: config.add_tailbone_permission(permission_prefix, '{}.new_product'.format(permission_prefix), "Create new Product when adding row to {}".format(model_title)) config.add_route('mobile.{}.new_product'.format(route_prefix), '{}/{{{}}}/new-product'.format(url_prefix, model_key)) diff --git a/tailbone/views/purchasing/receiving.py b/tailbone/views/purchasing/receiving.py index 8a8ca0dd..17d2eddf 100644 --- a/tailbone/views/purchasing/receiving.py +++ b/tailbone/views/purchasing/receiving.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2019 Lance Edgar +# Copyright © 2010-2020 Lance Edgar # # This file is part of Rattail. # @@ -1804,14 +1804,16 @@ class ReceivingBatchView(PurchasingBatchView): instance_url_prefix = cls.get_instance_url_prefix() model_key = cls.get_model_key() permission_prefix = cls.get_permission_prefix() + legacy_mobile = cls.legacy_mobile_enabled(rattail_config) # row-level receiving config.add_route('{}.receive_row'.format(route_prefix), '{}/{{uuid}}/rows/{{row_uuid}}/receive'.format(url_prefix)) config.add_view(cls, attr='receive_row', route_name='{}.receive_row'.format(route_prefix), permission='{}.edit_row'.format(permission_prefix)) - config.add_route('mobile.{}.receive_row'.format(route_prefix), '/mobile{}/{{uuid}}/rows/{{row_uuid}}/receive'.format(url_prefix)) - config.add_view(cls, attr='mobile_receive_row', route_name='mobile.{}.receive_row'.format(route_prefix), - permission='{}.edit_row'.format(permission_prefix)) + if legacy_mobile: + config.add_route('mobile.{}.receive_row'.format(route_prefix), '/mobile{}/{{uuid}}/rows/{{row_uuid}}/receive'.format(url_prefix)) + config.add_view(cls, attr='mobile_receive_row', route_name='mobile.{}.receive_row'.format(route_prefix), + permission='{}.edit_row'.format(permission_prefix)) # declare credit for row config.add_route('{}.declare_credit'.format(route_prefix), '{}/{{uuid}}/rows/{{row_uuid}}/declare-credit'.format(url_prefix))