2
0
Fork 0

fix: show installed python packages on appinfo page

This commit is contained in:
Lance Edgar 2024-08-20 21:26:38 -05:00
parent 3665d69e0c
commit d15ac46184
6 changed files with 116 additions and 4 deletions

View file

@ -46,12 +46,53 @@
</div>
</nav>
<${b}-collapse class="panel"
:open="false"
@open="openInstalledPackages">
<template #trigger="props">
<div class="panel-heading"
style="cursor: pointer;"
role="button">
## TODO: for some reason buefy will "reuse" the icon
## element in such a way that its display does not
## refresh. so to work around that, we use different
## structure for the two icons, so buefy is forced to
## re-draw
<b-icon v-if="props.open"
pack="fas"
icon="angle-down" />
<span v-if="!props.open">
<b-icon pack="fas"
icon="angle-right" />
</span>
<strong>Installed Packages</strong>
</div>
</template>
<div class="panel-block">
<div style="width: 100%;">
${grid.render_vue_tag(ref='packagesGrid')}
</div>
</div>
</${b}-collapse>
</%def>
<%def name="modify_vue_vars()">
${parent.modify_vue_vars()}
<script>
ThisPageData.configFiles = ${json.dumps([dict(path=p, priority=i) for i, p in enumerate(config.get_prioritized_files(), 1)])|n}
ThisPage.methods.openInstalledPackages = function() {
this.$refs.packagesGrid.fetchFirstData()
}
</script>
</%def>

View file

@ -134,6 +134,9 @@
data: ${grid.vue_component}CurrentData,
loading: false,
## nb. this tracks whether grid.fetchFirstData() happened
fetchedFirstData: false,
## sorting
% if grid.sortable:
sorters: ${json.dumps(grid.get_vue_active_sorters())|n},
@ -230,6 +233,17 @@
return params
},
## nb. this is meant to call for a grid which is hidden at
## first, when it is first being shown to the user. and if
## it was initialized with empty data set.
async fetchFirstData() {
if (this.fetchedFirstData) {
return
}
await this.fetchData()
this.fetchedFirstData = true
},
async fetchData() {
let params = new URLSearchParams(this.getBasicParams())

View file

@ -1208,8 +1208,10 @@ class MasterView(View):
self.set_labels(grid)
for key in self.get_model_key():
grid.set_link(key)
# TODO: i thought this was a good idea but if so it
# needs a try/catch in case of no model class
# for key in self.get_model_key():
# grid.set_link(key)
def grid_render_notes(self, record, key, value, maxlen=100):
"""

View file

@ -24,6 +24,11 @@
Views for app settings
"""
import json
import os
import sys
import subprocess
from collections import OrderedDict
from wuttjamaican.db.model import Setting
@ -47,13 +52,47 @@ class AppInfoView(MasterView):
model_name = 'AppInfo'
model_title_plural = "App Info"
route_prefix = 'appinfo'
has_grid = False
sort_on_backend = False
sort_defaults = 'name'
paginated = False
creatable = False
viewable = False
editable = False
deletable = False
configurable = True
grid_columns = [
'name',
'version',
'editable_project_location',
]
def get_grid_data(self, columns=None, session=None):
""" """
# 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'], text=True)
data = json.loads(output.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):
""" """
super().configure_grid(g)
g.sort_multiple = False
def configure_get_simple_settings(self):
""" """
return [

View file

@ -424,7 +424,10 @@ class TestMasterView(WebTestCase):
url_prefix='/appinfo',
creatable=False):
view = master.MasterView(self.request)
response = view.render_to_response('index', {})
response = view.render_to_response('index', {
# nb. grid is required for this template
'grid': MagicMock(),
})
self.assertIsInstance(response, Response)
# bad template name causes error

View file

@ -18,6 +18,19 @@ class TestAppInfoView(WebTestCase):
def make_view(self):
return mod.AppInfoView(self.request)
def test_get_grid_data(self):
view = self.make_view()
# empty data by default
data = view.get_grid_data()
self.assertEqual(data, [])
# 'partial' request returns data
self.request.GET = {'partial': '1'}
data = view.get_grid_data()
self.assertIsInstance(data, list)
self.assertTrue(data)
def test_index(self):
# sanity/coverage check
view = self.make_view()