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'}, {'type': 'sep'},
{ {
'title': "App Details", 'title': "App Info",
'route': 'appinfo', 'route': 'appinfo',
'perm': 'appinfo.list', 'perm': 'appinfo.list',
}, },

View file

@ -1,247 +1,2 @@
## -*- coding: utf-8; -*- ## -*- coding: utf-8; -*-
<%inherit file="/configure.mako" /> <%inherit file="wuttaweb:templates/appinfo/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>

View file

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

View file

@ -25,11 +25,7 @@ Settings Views
""" """
import json import json
import os
import re import re
import subprocess
import sys
from collections import OrderedDict
import colander import colander
@ -37,201 +33,77 @@ from rattail.db.model import Setting
from rattail.settings import Setting as AppSetting from rattail.settings import Setting as AppSetting
from rattail.util import import_module_path from rattail.util import import_module_path
from tailbone import forms from tailbone import forms, grids
from tailbone.db import Session from tailbone.db import Session
from tailbone.views import MasterView, View from tailbone.views import MasterView, View
from wuttaweb.util import get_libver, get_liburl from wuttaweb.util import get_libver, get_liburl
from wuttaweb.views.settings import AppInfoView as WuttaAppInfoView
class AppInfoView(MasterView): class AppInfoView(WuttaAppInfoView):
"""
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):
""" """ """ """
Session = Session
weblib_config_prefix = 'tailbone'
# nb. init with empty data, only load it upon user request # TODO: for now we override to get tailbone searchable grid
if not self.request.GET.get('partial'): def make_grid(self, **kwargs):
return [] """ """
return grids.Grid(self.request, **kwargs)
# 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
def configure_grid(self, g): def configure_grid(self, g):
""" """
super().configure_grid(g) super().configure_grid(g)
# sort on frontend
g.sort_on_backend = False
g.sort_multiple = False
g.set_sort_defaults('name')
# name # name
g.set_searchable('name') g.set_searchable('name')
# editable_project_location # editable_project_location
g.set_searchable('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): def configure_get_context(self, **kwargs):
""" """ """ """
context = super().configure_get_context(**kwargs) context = super().configure_get_context(**kwargs)
simple_settings = context['simple_settings'] simple_settings = context['simple_settings']
weblibs = self.get_weblibs() weblibs = context['weblibs']
for key in weblibs: for weblib in weblibs:
title = weblibs[key] key = weblib['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'),
}
# TODO: this is only needed to migrate legacy settings to # 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}'] url = simple_settings[f'wuttaweb.liburl.{key}']
if not url and weblibs[key]['configured_url']: if not url and weblib['configured_url']:
simple_settings[f'wuttaweb.liburl.{key}'] = weblibs[key]['configured_url'] simple_settings[f'wuttaweb.liburl.{key}'] = weblib['configured_url']
context['weblibs'] = list(weblibs.values())
return context return context
def configure_get_simple_settings(self): def configure_get_simple_settings(self):
""" """ """ """
simple_settings = [ simple_settings = super().configure_get_simple_settings()
# basics # TODO: the update home page redirect setting is off by
{'section': 'rattail', # default for wuttaweb, but on for tailbone
'option': 'app_title'}, for setting in simple_settings:
{'section': 'rattail', if setting['name'] == 'wuttaweb.home_redirect_to_login':
'option': 'node_type'}, value = self.config.get_bool('wuttaweb.home_redirect_to_login')
{'section': 'rattail', if value is None:
'option': 'node_title'}, value = self.config.get_bool('tailbone.login_is_home', default=True)
{'section': 'rattail', setting['default'] = value
'option': 'production', break
'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
},
# nb. these are no longer used (deprecated), but we keep # nb. these are no longer used (deprecated), but we keep
# them defined here so the tool auto-deletes them # 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): for key in self.get_weblibs():
return self.config.get(f'tailbone.{key}') simple_settings.extend([
{'name': f'tailbone.libver.{key}'},
weblibs = self.get_weblibs() {'name': f'tailbone.liburl.{key}'},
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}",
})
return simple_settings return simple_settings