feat: inherit from wuttaweb for AppInfoView, appinfo/configure template

This commit is contained in:
Lance Edgar 2024-08-20 23:23:23 -05:00
parent 2ffc067097
commit f755460242
4 changed files with 48 additions and 412 deletions

View file

@ -703,7 +703,7 @@ class TailboneMenuHandler(WuttaMenuHandler):
},
{'type': 'sep'},
{
'title': "App Details",
'title': "App Info",
'route': 'appinfo',
'perm': 'appinfo.list',
},

View file

@ -1,247 +1,2 @@
## -*- coding: utf-8; -*-
<%inherit file="/configure.mako" />
<%def name="form_content()">
<h3 class="block is-size-3">Basics</h3>
<div class="block" style="padding-left: 2rem;">
<b-field grouped>
<b-field label="App Title">
<b-input name="rattail.app_title"
v-model="simpleSettings['rattail.app_title']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
<b-field label="Node Type">
## TODO: should be a dropdown, app handler defines choices
<b-input name="rattail.node_type"
v-model="simpleSettings['rattail.node_type']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
<b-field label="Node Title">
<b-input name="rattail.node_title"
v-model="simpleSettings['rattail.node_title']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
</b-field>
<b-field>
<b-checkbox name="rattail.production"
v-model="simpleSettings['rattail.production']"
native-value="true"
@input="settingsNeedSaved = true">
Production Mode
</b-checkbox>
</b-field>
<div class="level-left">
<div class="level-item">
<b-field>
<b-checkbox name="rattail.running_from_source"
v-model="simpleSettings['rattail.running_from_source']"
native-value="true"
@input="settingsNeedSaved = true">
Running from Source
</b-checkbox>
</b-field>
</div>
<div class="level-item">
<b-field label="Top-Level Package" horizontal
v-if="simpleSettings['rattail.running_from_source']">
<b-input name="rattail.running_from_source.rootpkg"
v-model="simpleSettings['rattail.running_from_source.rootpkg']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
</div>
</div>
</div>
<h3 class="block is-size-3">Display</h3>
<div class="block" style="padding-left: 2rem;">
<b-field grouped>
<b-field label="Background Color">
<b-input name="tailbone.background_color"
v-model="simpleSettings['tailbone.background_color']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
</b-field>
</div>
<h3 class="block is-size-3">Grids</h3>
<div class="block" style="padding-left: 2rem;">
<b-field grouped>
<b-field label="Default Page Size">
<b-input name="tailbone.grid.default_pagesize"
v-model="simpleSettings['tailbone.grid.default_pagesize']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
</b-field>
</div>
<h3 class="block is-size-3">Web Libraries</h3>
<div class="block" style="padding-left: 2rem;">
<${b}-table :data="weblibs">
<${b}-table-column field="title"
label="Name"
v-slot="props">
{{ props.row.title }}
</${b}-table-column>
<${b}-table-column field="configured_version"
label="Version"
v-slot="props">
{{ props.row.configured_version || props.row.default_version }}
</${b}-table-column>
<${b}-table-column field="configured_url"
label="URL Override"
v-slot="props">
{{ props.row.configured_url }}
</${b}-table-column>
<${b}-table-column field="live_url"
label="Effective (Live) URL"
v-slot="props">
<span v-if="props.row.modified"
class="has-text-warning">
save settings and refresh page to see new URL
</span>
<span v-if="!props.row.modified">
{{ props.row.live_url }}
</span>
</${b}-table-column>
<${b}-table-column field="actions"
label="Actions"
v-slot="props">
<a href="#"
@click.prevent="editWebLibraryInit(props.row)">
% if request.use_oruga:
<o-icon icon="edit" />
% else:
<i class="fas fa-edit"></i>
% endif
Edit
</a>
</${b}-table-column>
</${b}-table>
% for weblib in weblibs:
${h.hidden('wuttaweb.libver.{}'.format(weblib['key']), **{':value': "simpleSettings['wuttaweb.libver.{}']".format(weblib['key'])})}
${h.hidden('wuttaweb.liburl.{}'.format(weblib['key']), **{':value': "simpleSettings['wuttaweb.liburl.{}']".format(weblib['key'])})}
% endfor
<${b}-modal has-modal-card
% if request.use_oruga:
v-model:active="editWebLibraryShowDialog"
% else:
:active.sync="editWebLibraryShowDialog"
% endif
>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Web Library: {{ editWebLibraryRecord.title }}</p>
</header>
<section class="modal-card-body">
<b-field grouped>
<b-field label="Default Version">
<b-input v-model="editWebLibraryRecord.default_version"
disabled>
</b-input>
</b-field>
<b-field label="Override Version">
<b-input v-model="editWebLibraryVersion">
</b-input>
</b-field>
</b-field>
<b-field label="Override URL">
<b-input v-model="editWebLibraryURL"
expanded />
</b-field>
<b-field label="Effective URL (as of last page load)">
<b-input v-model="editWebLibraryRecord.live_url"
disabled
expanded />
</b-field>
</section>
<footer class="modal-card-foot">
<b-button type="is-primary"
@click="editWebLibrarySave()"
icon-pack="fas"
icon-left="save">
Save
</b-button>
<b-button @click="editWebLibraryShowDialog = false">
Cancel
</b-button>
</footer>
</div>
</${b}-modal>
</div>
</%def>
<%def name="modify_vue_vars()">
${parent.modify_vue_vars()}
<script>
ThisPageData.weblibs = ${json.dumps(weblibs)|n}
ThisPageData.editWebLibraryShowDialog = false
ThisPageData.editWebLibraryRecord = {}
ThisPageData.editWebLibraryVersion = null
ThisPageData.editWebLibraryURL = null
ThisPage.methods.editWebLibraryInit = function(row) {
this.editWebLibraryRecord = row
this.editWebLibraryVersion = row.configured_version
this.editWebLibraryURL = row.configured_url
this.editWebLibraryShowDialog = true
}
ThisPage.methods.editWebLibrarySave = function() {
this.editWebLibraryRecord.configured_version = this.editWebLibraryVersion
this.editWebLibraryRecord.configured_url = this.editWebLibraryURL
this.editWebLibraryRecord.modified = true
this.simpleSettings[`wuttaweb.libver.${'$'}{this.editWebLibraryRecord.key}`] = this.editWebLibraryVersion
this.simpleSettings[`wuttaweb.liburl.${'$'}{this.editWebLibraryRecord.key}`] = this.editWebLibraryURL
this.settingsNeedSaved = true
this.editWebLibraryShowDialog = false
}
</script>
</%def>
<%inherit file="wuttaweb:templates/appinfo/configure.mako" />

View file

@ -666,6 +666,7 @@
<%def name="make_b_tooltip_component()">
<script type="text/x-template" id="b-tooltip-template">
<o-tooltip :label="label"
:position="orugaPosition"
:multiline="multilined">
<slot />
</o-tooltip>
@ -676,6 +677,14 @@
props: {
label: String,
multilined: Boolean,
position: String,
},
computed: {
orugaPosition() {
if (this.position) {
return this.position.replace(/^is-/, '')
}
},
},
}
</script>

View file

@ -25,11 +25,7 @@ Settings Views
"""
import json
import os
import re
import subprocess
import sys
from collections import OrderedDict
import colander
@ -37,201 +33,77 @@ from rattail.db.model import Setting
from rattail.settings import Setting as AppSetting
from rattail.util import import_module_path
from tailbone import forms
from tailbone import forms, grids
from tailbone.db import Session
from tailbone.views import MasterView, View
from wuttaweb.util import get_libver, get_liburl
from wuttaweb.views.settings import AppInfoView as WuttaAppInfoView
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 Details"
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):
app = self.get_rattail_app()
return "{} for {}".format(self.get_model_title_plural(),
app.get_title())
def get_data(self, session=None):
class AppInfoView(WuttaAppInfoView):
""" """
Session = Session
weblib_config_prefix = 'tailbone'
# nb. init with empty data, only load it upon user request
if not self.request.GET.get('partial'):
return []
# TODO: pretty sure this is not cross-platform. probably some
# sort of pip methods belong on the app handler? or it should
# have a pip handler for all that?
pip = os.path.join(sys.prefix, 'bin', 'pip')
output = subprocess.check_output([pip, 'list', '--format=json'])
data = json.loads(output.decode('utf_8').strip())
# must avoid null values for sort to work right
for pkg in data:
pkg.setdefault('editable_project_location', '')
return data
# TODO: for now we override to get tailbone searchable grid
def make_grid(self, **kwargs):
""" """
return grids.Grid(self.request, **kwargs)
def configure_grid(self, g):
""" """
super().configure_grid(g)
# sort on frontend
g.sort_on_backend = False
g.sort_multiple = False
g.set_sort_defaults('name')
# name
g.set_searchable('name')
# editable_project_location
g.set_searchable('editable_project_location')
def template_kwargs_index(self, **kwargs):
kwargs = super().template_kwargs_index(**kwargs)
kwargs['configure_button_title'] = "Configure App"
return kwargs
def get_weblibs(self):
""" """
return OrderedDict([
('vue', "Vue"),
('vue_resource', "vue-resource"),
('buefy', "Buefy"),
('buefy.css', "Buefy CSS"),
('fontawesome', "FontAwesome"),
('bb_vue', "(BB) vue"),
('bb_oruga', "(BB) @oruga-ui/oruga-next"),
('bb_oruga_bulma', "(BB) @oruga-ui/theme-bulma (JS)"),
('bb_oruga_bulma_css', "(BB) @oruga-ui/theme-bulma (CSS)"),
('bb_fontawesome_svg_core', "(BB) @fortawesome/fontawesome-svg-core"),
('bb_free_solid_svg_icons', "(BB) @fortawesome/free-solid-svg-icons"),
('bb_vue_fontawesome', "(BB) @fortawesome/vue-fontawesome"),
])
def configure_get_context(self, **kwargs):
""" """
context = super().configure_get_context(**kwargs)
simple_settings = context['simple_settings']
weblibs = self.get_weblibs()
weblibs = context['weblibs']
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,
prefix='tailbone',
configured_only=True),
'configured_url': get_liburl(self.request, key,
prefix='tailbone',
configured_only=True),
# these are for informational purposes only
'default_version': get_libver(self.request, key,
prefix='tailbone',
default_only=True),
'live_url': get_liburl(self.request, key,
prefix='tailbone'),
}
for weblib in weblibs:
key = weblib['key']
# TODO: this is only needed to migrate legacy settings to
# use the newer wutaweb setting names
# use the newer wuttaweb setting names
url = simple_settings[f'wuttaweb.liburl.{key}']
if not url and weblibs[key]['configured_url']:
simple_settings[f'wuttaweb.liburl.{key}'] = weblibs[key]['configured_url']
if not url and weblib['configured_url']:
simple_settings[f'wuttaweb.liburl.{key}'] = weblib['configured_url']
context['weblibs'] = list(weblibs.values())
return context
def configure_get_simple_settings(self):
""" """
simple_settings = [
simple_settings = super().configure_get_simple_settings()
# basics
{'section': 'rattail',
'option': 'app_title'},
{'section': 'rattail',
'option': 'node_type'},
{'section': 'rattail',
'option': 'node_title'},
{'section': 'rattail',
'option': 'production',
'type': bool},
{'section': 'rattail',
'option': 'running_from_source',
'type': bool},
{'section': 'rattail',
'option': 'running_from_source.rootpkg'},
# 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
},
# TODO: the update home page redirect setting is off by
# default for wuttaweb, but on for tailbone
for setting in simple_settings:
if setting['name'] == 'wuttaweb.home_redirect_to_login':
value = self.config.get_bool('wuttaweb.home_redirect_to_login')
if value is None:
value = self.config.get_bool('tailbone.login_is_home', default=True)
setting['default'] = value
break
# 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'},
]
simple_settings.extend([
{'name': 'tailbone.buefy_version'},
{'name': 'tailbone.vue_version'},
])
def getval(key):
return self.config.get(f'tailbone.{key}')
weblibs = self.get_weblibs()
for key, title in weblibs.items():
simple_settings.append({
'section': 'wuttaweb',
'option': f"libver.{key}",
'default': getval(f"libver.{key}"),
})
simple_settings.append({
'section': 'wuttaweb',
'option': f"liburl.{key}",
'default': getval(f"liburl.{key}"),
})
# nb. these are no longer used (deprecated), but we keep
# them defined here so the tool auto-deletes them
simple_settings.append({
'section': 'tailbone',
'option': f"libver.{key}",
})
simple_settings.append({
'section': 'tailbone',
'option': f"liburl.{key}",
})
for key in self.get_weblibs():
simple_settings.extend([
{'name': f'tailbone.libver.{key}'},
{'name': f'tailbone.liburl.{key}'},
])
return simple_settings