From d15ac461841a7121fa00ff8ed0934237902246b9 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 20 Aug 2024 21:26:38 -0500 Subject: [PATCH] fix: show installed python packages on appinfo page --- src/wuttaweb/templates/appinfo/index.mako | 41 +++++++++++++++++++ .../templates/grids/vue_template.mako | 14 +++++++ src/wuttaweb/views/master.py | 6 ++- src/wuttaweb/views/settings.py | 41 ++++++++++++++++++- tests/views/test_master.py | 5 ++- tests/views/test_settings.py | 13 ++++++ 6 files changed, 116 insertions(+), 4 deletions(-) diff --git a/src/wuttaweb/templates/appinfo/index.mako b/src/wuttaweb/templates/appinfo/index.mako index 342617e..0997544 100644 --- a/src/wuttaweb/templates/appinfo/index.mako +++ b/src/wuttaweb/templates/appinfo/index.mako @@ -46,12 +46,53 @@ + <${b}-collapse class="panel" + :open="false" + @open="openInstalledPackages"> + + + +
+
+ ${grid.render_vue_tag(ref='packagesGrid')} +
+
+ + <%def name="modify_vue_vars()"> ${parent.modify_vue_vars()} diff --git a/src/wuttaweb/templates/grids/vue_template.mako b/src/wuttaweb/templates/grids/vue_template.mako index b161d9f..cb4f7a8 100644 --- a/src/wuttaweb/templates/grids/vue_template.mako +++ b/src/wuttaweb/templates/grids/vue_template.mako @@ -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()) diff --git a/src/wuttaweb/views/master.py b/src/wuttaweb/views/master.py index d43de9e..3422fe1 100644 --- a/src/wuttaweb/views/master.py +++ b/src/wuttaweb/views/master.py @@ -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): """ diff --git a/src/wuttaweb/views/settings.py b/src/wuttaweb/views/settings.py index 087a7df..0cea55b 100644 --- a/src/wuttaweb/views/settings.py +++ b/src/wuttaweb/views/settings.py @@ -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 [ diff --git a/tests/views/test_master.py b/tests/views/test_master.py index 5cf60db..21da2e5 100644 --- a/tests/views/test_master.py +++ b/tests/views/test_master.py @@ -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 diff --git a/tests/views/test_settings.py b/tests/views/test_settings.py index f0485c1..208d0f2 100644 --- a/tests/views/test_settings.py +++ b/tests/views/test_settings.py @@ -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()