Add new views for App Info, and Configure App

and a way to specify version/url overrides for buefy, vue etc.

also, begin logic for "standard" admin menu
This commit is contained in:
Lance Edgar 2023-01-12 15:19:46 -06:00
parent 2163522e7c
commit d842a3d8e0
11 changed files with 752 additions and 26 deletions

View file

@ -2248,6 +2248,8 @@ class MasterView(View):
route = self.get_route_prefix()
return self.request.route_url(route, **kwargs)
# TODO: this should not be class method, if possible
# (pretty sure overriding as instance method works fine)
@classmethod
def get_index_title(cls):
"""
@ -4822,6 +4824,8 @@ class MasterView(View):
value = six.text_type(bool(value)).lower()
elif simple.get('type') is int:
value = six.text_type(int(value or '0'))
elif value is None:
value = ''
else:
value = six.text_type(value)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2022 Lance Edgar
# Copyright © 2010-2023 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,14 +26,17 @@ Settings Views
from __future__ import unicode_literals, absolute_import
import os
import re
import subprocess
import sys
import json
import six
from rattail.db import model
from rattail.settings import Setting
from rattail.util import import_module_path
from rattail.util import import_module_path, OrderedDict
import colander
from webhelpers2.html import tags
@ -41,6 +44,153 @@ from webhelpers2.html import tags
from tailbone import forms
from tailbone.db import Session
from tailbone.views import MasterView, View
from tailbone.util import get_libver, get_liburl
class AppInfoView(MasterView):
"""
Master view for the overall app, to show/edit config etc.
"""
route_prefix = 'appinfo'
model_key = 'UNUSED'
model_title = "UNUSED"
model_title_plural = "App Info"
creatable = False
viewable = False
editable = False
deletable = False
filterable = False
pageable = False
configurable = True
grid_columns = [
'name',
'version',
'editable_project_location',
]
def get_index_title(self):
return "App Info for {}".format(self.rattail_config.app_title())
def get_data(self, session=None):
pip = os.path.join(sys.prefix, 'bin', 'pip')
output = subprocess.check_output([pip, 'list', '--format=json'])
data = json.loads(output.decode('utf_8').strip())
for pkg in data:
pkg.setdefault('editable_project_location', '')
return data
def configure_grid(self, g):
super(AppInfoView, self).configure_grid(g)
g.sorters['name'] = g.make_simple_sorter('name', foldcase=True)
g.set_sort_defaults('name')
g.set_searchable('name')
g.sorters['version'] = g.make_simple_sorter('version', foldcase=True)
g.sorters['editable_project_location'] = g.make_simple_sorter(
'editable_project_location', foldcase=True)
g.set_searchable('editable_project_location')
def configure_get_context(self, **kwargs):
context = super(AppInfoView, self).configure_get_context(**kwargs)
weblibs = OrderedDict([
('vue', "Vue"),
('vue_resource', "vue-resource"),
('buefy', "Buefy"),
('buefy.css', "Buefy CSS"),
('fontawesome', "FontAwesome"),
('jquery', "jQuery"),
('jquery_ui', "jQuery UI"),
])
for key in weblibs:
title = weblibs[key]
weblibs[key] = {
'key': key,
'title': title,
# nb. these values are exactly as configured, and are
# used for editing the settings
'configured_version': get_libver(self.request, key, fallback=False),
'configured_url': get_liburl(self.request, key, fallback=False),
# these are for informational purposes only
'default_version': get_libver(self.request, key, default_only=True),
'live_url': get_liburl(self.request, key),
}
context['weblibs'] = list(weblibs.values())
return context
def configure_get_simple_settings(self):
return [
# basics
{'section': 'rattail',
'option': 'app_title'},
{'section': 'rattail',
'option': 'node_type'},
{'section': 'rattail',
'option': 'node_title'},
{'section': 'rattail',
'option': 'production',
'type': bool},
# display
{'section': 'tailbone',
'option': 'background_color'},
# grids
{'section': 'tailbone',
'option': 'grid.default_pagesize',
# TODO: seems like should enforce this, but validation is
# not setup yet
# 'type': int
},
# web libs
{'section': 'tailbone',
'option': 'libver.vue'},
{'section': 'tailbone',
'option': 'liburl.vue'},
{'section': 'tailbone',
'option': 'libver.vue_resource'},
{'section': 'tailbone',
'option': 'liburl.vue_resource'},
{'section': 'tailbone',
'option': 'libver.buefy'},
{'section': 'tailbone',
'option': 'liburl.buefy'},
{'section': 'tailbone',
'option': 'libver.buefy.css'},
{'section': 'tailbone',
'option': 'liburl.buefy.css'},
{'section': 'tailbone',
'option': 'libver.fontawesome'},
{'section': 'tailbone',
'option': 'liburl.fontawesome'},
{'section': 'tailbone',
'option': 'libver.jquery'},
{'section': 'tailbone',
'option': 'liburl.jquery'},
{'section': 'tailbone',
'option': 'libver.jquery_ui'},
{'section': 'tailbone',
'option': 'liburl.jquery_ui'},
# nb. these are no longer used (deprecated), but we keep
# them defined here so the tool auto-deletes them
{'section': 'tailbone',
'option': 'buefy_version'},
{'section': 'tailbone',
'option': 'vue_version'},
]
class SettingView(MasterView):
@ -322,6 +472,9 @@ class AppSettingsView(View):
def defaults(config, **kwargs):
base = globals()
AppInfoView = kwargs.get('AppInfoView', base['AppInfoView'])
AppInfoView.defaults(config)
AppSettingsView = kwargs.get('AppSettingsView', base['AppSettingsView'])
AppSettingsView.defaults(config)