Add page/way to configure main menus

just the basics so far, index page routes and separators should be
supported but nothing else.  also "menus from config" is all or
nothing, no way to mix config + code at this point
This commit is contained in:
Lance Edgar 2022-02-26 17:08:23 -06:00
parent 587a4daf7a
commit 74fecf553e
7 changed files with 883 additions and 25 deletions

View file

@ -4209,7 +4209,9 @@ class MasterView(View):
if self.request.method == 'POST':
if self.request.POST.get('remove_settings'):
self.configure_remove_settings()
self.request.session.flash("Settings have been removed.")
self.request.session.flash("All settings for {} have been "
"removed.".format(self.get_config_title()),
'warning')
return self.redirect(self.request.current_route_url())
else:
data = self.request.POST
@ -4517,6 +4519,8 @@ class MasterView(View):
config.add_view(cls, attr='index', route_name=route_prefix,
permission='{}.list'.format(permission_prefix),
**kwargs)
config.add_tailbone_index_page(route_prefix, model_title_plural,
'{}.list'.format(permission_prefix))
# download results
# this is the "new" more flexible approach, but we only want to
@ -4572,7 +4576,8 @@ class MasterView(View):
route_name='{}.configure'.format(route_prefix),
permission='{}.configure'.format(permission_prefix))
config.add_tailbone_config_page('{}.configure'.format(route_prefix),
config_title)
config_title,
'{}.configure'.format(permission_prefix))
# quickie (search)
if cls.supports_quickie_search:

191
tailbone/views/menus.py Normal file
View file

@ -0,0 +1,191 @@
# -*- coding: utf-8; -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Base class for Config Views
"""
from __future__ import unicode_literals, absolute_import
import json
import sqlalchemy as sa
from tailbone.views import View
from tailbone.db import Session
from tailbone.menus import make_menu_key
class MenuConfigView(View):
"""
View for configuring the main menu.
"""
def configure(self):
"""
Main entry point to menu config views.
"""
if self.request.method == 'POST':
if self.request.POST.get('remove_settings'):
self.configure_remove_settings()
self.request.session.flash("All settings for Menus have been removed.",
'warning')
return self.redirect(self.request.current_route_url())
else:
data = self.request.POST
# gather/save settings
settings = self.configure_gather_settings(data)
self.configure_remove_settings()
self.configure_save_settings(settings)
self.request.session.flash("Settings have been saved.")
return self.redirect(self.request.current_route_url())
context = {
'config_title': "Menus",
'use_buefy': True,
'index_title': "App Settings",
'index_url': self.request.route_url('appsettings'),
}
possible_index_options = sorted(
self.request.registry.settings['tailbone_index_pages'],
key=lambda p: p['label'])
index_options = []
for option in possible_index_options:
perm = option['permission']
option['perm'] = perm
option['url'] = self.request.route_url(option['route'])
index_options.append(option)
context['index_route_options'] = index_options
return context
def configure_gather_settings(self, data):
settings = [{'name': 'tailbone.menu.from_settings',
'value': 'true'}]
main_keys = []
for topitem in json.loads(data['menus']):
key = make_menu_key(self.rattail_config, topitem['title'])
main_keys.append(key)
settings.extend([
{'name': 'tailbone.menu.menu.{}.label'.format(key),
'value': topitem['title']},
])
item_keys = []
for item in topitem['items']:
item_type = item.get('type', 'item')
if item_type == 'item':
if item.get('route'):
item_key = item['route']
else:
item_key = make_menu_key(self.rattail_config, item['title'])
item_keys.append(item_key)
settings.extend([
{'name': 'tailbone.menu.menu.{}.item.{}.label'.format(key, item_key),
'value': item['title']},
])
if item.get('route'):
settings.extend([
{'name': 'tailbone.menu.menu.{}.item.{}.route'.format(key, item_key),
'value': item['route']},
])
elif item.get('url'):
settings.extend([
{'name': 'tailbone.menu.menu.{}.item.{}.url'.format(key, item_key),
'value': item['url']},
])
if item.get('perm'):
settings.extend([
{'name': 'tailbone.menu.menu.{}.item.{}.perm'.format(key, item_key),
'value': item['perm']},
])
elif item_type == 'sep':
item_keys.append('SEP')
settings.extend([
{'name': 'tailbone.menu.menu.{}.items'.format(key),
'value': ' '.join(item_keys)},
])
settings.append({'name': 'tailbone.menu.menus',
'value': ' '.join(main_keys)})
return settings
def configure_remove_settings(self):
model = self.model
Session.query(model.Setting)\
.filter(sa.or_(
model.Setting.name == 'tailbone.menu.from_settings',
model.Setting.name == 'tailbone.menu.menus',
model.Setting.name.like('tailbone.menu.menu.%.label'),
model.Setting.name.like('tailbone.menu.menu.%.items'),
model.Setting.name.like('tailbone.menu.menu.%.item.%.label'),
model.Setting.name.like('tailbone.menu.menu.%.item.%.route'),
model.Setting.name.like('tailbone.menu.menu.%.item.%.perm'),
model.Setting.name.like('tailbone.menu.menu.%.item.%.url')))\
.delete(synchronize_session=False)
def configure_save_settings(self, settings):
model = self.model
session = Session()
for setting in settings:
session.add(model.Setting(name=setting['name'],
value=setting['value']))
@classmethod
def defaults(cls, config):
cls._defaults(config)
@classmethod
def _defaults(cls, config):
# configure menus
config.add_route('configure_menus',
'/configure-menus')
config.add_view(cls, attr='configure',
route_name='configure_menus',
# nb. must be root to configure menus! b/c
# otherwise some route options may be hidden
permission='admin',
renderer='/configure-menus.mako')
config.add_tailbone_config_page('configure_menus', "Menus", 'admin')
def defaults(config, **kwargs):
base = globals()
MenuConfigView = kwargs.get('MenuConfigView', base['MenuConfigView'])
MenuConfigView.defaults(config)
def includeme(config):
defaults(config)