ui: group the eSIM chip info into boxes and wrap values nicely

The chip view was one long flat list spread over the full height.

- esimRenderChip split into esimChipSectionRows (object or RAT rule list
  -> rows) and esimChipBox (titled box, skipped when empty); the boxes
  are laid out on a grid: EID, EUICCInfo1, Addresses and the rules
  authorisation table in the left column, the larger EUICCInfo2 in the
  wider right-hand box (single column on narrow screens).  Rows use a
  narrower label column (w-36).
- Values wrap with break-words + min-w-0 instead of break-all: text
  breaks at spaces first and long hex/AID tokens only when they cannot
  fit (same for the profile metadata rows).
- style.css rebuilt (grid-cols-1, lg:grid-cols-3, lg:col-span-1/2/3,
  break-words).
- tests: the new helpers, the grid/box layout and the wrapping check;
  help EN/RU note the grouping; sw.js simple-v232.
This commit is contained in:
2026-09-22 00:27:31 +03:00
parent d3f5aaa443
commit a7ec67b19c
6 changed files with 128 additions and 32 deletions
+35 -1
View File
@@ -24,7 +24,7 @@ function extractFunc(src, name) {
let code = '';
for (const fn of ['esimLabel', 'esimGroupEid', 'esimFieldRows', 'esimResultText',
'esimStateLabel', 'esimOperationsText', 'esimProfileRows', 'esimIconDataUrl',
'esimSwitchStatus']) {
'esimChipSectionRows', 'esimChipBox', 'esimSwitchStatus']) {
code += extractFunc(html, fn) + '\n';
}
for (const c of ['ESIM_CHIP_LABELS', 'ESIM_RESULT_KEYS']) {
@@ -32,6 +32,7 @@ for (const c of ['ESIM_CHIP_LABELS', 'ESIM_RESULT_KEYS']) {
.replace('const ', 'var ') + '\n';
}
code += 'function t(s){return s;}\n';
code += 'function esc(s){return String(s);}\n';
eval(code);
test('esimGroupEid groups the hex digits in fours', () => {
@@ -153,6 +154,39 @@ test('the profile card renders the icon image next to the rows', () => {
assert.match(fn, /<img src=/);
});
test('esimChipSectionRows builds rows for objects and RAT rule lists', () => {
assert.deepStrictEqual(esimChipSectionRows({ svn: '2.2.2' }), [['SVN', '2.2.2']]);
assert.deepStrictEqual(esimChipSectionRows(null), []);
assert.deepStrictEqual(esimChipSectionRows([{ ppr_ids: ['ppr1'] }]),
[['Rule 1 / PPR IDs', 'ppr1']]);
});
test('esimChipBox renders a titled box and skips empty sections', () => {
assert.strictEqual(esimChipBox('EUICCInfo1', []), '');
assert.strictEqual(esimChipBox('EUICCInfo1', null), '');
const box = esimChipBox('EUICCInfo1', [['SVN', '2.2.2'], ['', 'raw-value']]);
assert.match(box, /EUICCInfo1/);
assert.match(box, /SVN/);
assert.match(box, /2\.2\.2/);
assert.match(box, /raw-value/);
});
test('the chip boxes prefer wrapping at spaces over breaking words', () => {
const box = esimChipBox('EUICCInfo1', [['SVN', '2.2.2']]);
assert.match(box, /break-words/);
assert.doesNotMatch(box, /break-all/);
const render = extractFunc(html, 'esimRenderProfiles');
assert.doesNotMatch(render, /break-all/);
});
test('the chip view groups the sections into a grid', () => {
const fn = extractFunc(html, 'esimRenderChip');
assert.match(fn, /lg:grid-cols-3/);
assert.match(fn, /lg:col-span-2/);
assert.match(fn, /esimChipBox\('EUICCInfo2'/);
assert.match(fn, /esimChipSectionRows/);
});
test('the eSIM pill is wired into the Phone simulator tab', () => {
assert.ok(html.includes('data-phone-sub="esim"'));
assert.ok(html.includes('id="phone-sub-esim"'));