feat(tables): migrate /tables page from Jinja2 to Vue 3 + Vite

Rewrite 237-line vanilla JS + Jinja2 template into Vue 3 SFC components
(App.vue, TableCatalog.vue, DataViewer.vue, useTableData composable).
Establishes apiPost POST request pattern for pure Vite pages. Removes
templates/index.html, updates Vite entry to HTML, and Flask route to
send_from_directory. Includes sql_fragments WHERE_CLAUSE escaping fix,
updated integration tests, and OpenSpec artifact archive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
egg
2026-02-09 14:52:14 +08:00
parent 44b89599a4
commit dcbf6dcf1f
23 changed files with 1483 additions and 838 deletions

View File

@@ -507,6 +507,24 @@ class TestBuildFilterBuilder:
sql = mock_read.call_args[0][0]
assert RESOURCE_TABLE in sql
def test_resource_version_sql_replaces_where_clause_placeholder(self):
"""Version SQL should not leak placeholder token into Oracle."""
import mes_dashboard.services.resource_cache as rc
from mes_dashboard.services.sql_fragments import RESOURCE_TABLE
with patch.object(
rc,
"read_sql_df",
return_value=pd.DataFrame([{"VERSION": "2026-02-09T12:00:00"}]),
) as mock_read:
rc._get_version_from_oracle()
sql = mock_read.call_args[0][0]
assert RESOURCE_TABLE in sql
assert "{{ WHERE_CLAUSE }}" not in sql
assert "{ WHERE_CLAUSE }" not in sql
assert "WHERE " in sql
class TestResourceDerivedIndex:
"""Test derived resource index and telemetry behavior."""

View File

@@ -54,14 +54,14 @@ class TestTemplateIntegration(unittest.TestCase):
self.assertIn('mes-api.js', html)
self.assertIn('mes-toast-container', html)
def test_tables_page_includes_base_scripts(self):
def test_tables_page_serves_pure_vite_module(self):
response = self.client.get('/tables')
self.assertEqual(response.status_code, 200)
html = response.data.decode('utf-8')
self.assertIn('toast.js', html)
self.assertIn('mes-api.js', html)
self.assertIn('mes-toast-container', html)
self.assertIn('/static/dist/tables.js', html)
self.assertIn('type="module"', html)
self.assertNotIn('mes-toast-container', html)
def test_resource_page_includes_base_scripts(self):
response = self.client.get('/resource')