v3.28.1: the batch panel polish

- A throbber (#ram-batch-spin) next to the phase line shows while a card
  is actually being installed (active && current - the stopping-mid-
  install phase included) and hides again while waiting.
- The waiting prompt is explicit now: "Insert next card. Waiting for a
  card..." (RU "Вставьте следующую карту. Ожидание карты…"); the old
  "Waiting for a card..." key is gone.
- The notice reports only the last *finished* card: starting the next
  card's install clears it (state['notice'] = '' alongside
  current/installing in _ram_batch_handle_card), so the previous card's
  verdict never lingers over the next install.  It stays visible while
  waiting - the "report the status + ask for the next card" behavior.
- The batch operation's RU label is "Пакетная установка (.cap на
  множество карт)"; the help row's title aligned.

Tests: the render test (the new prompt, the throbber visible while
installing / stopping-mid-install and hidden while waiting, an empty
notice hiding the box) and the worker test (the notice is empty
mid-install and set again for the new outcome).  915 frontend + 925
Python; sw cache simple-v439.
This commit is contained in:
2026-10-14 18:04:22 +03:00
parent 262041795c
commit 91996a941b
7 changed files with 57 additions and 13 deletions
+19 -5
View File
@@ -165,10 +165,12 @@ test('ramBatchRender shows the phase, the counts and the stop button', () => {
setEl('ram-batch-counts', '');
setEl('ram-batch-attempts', '');
setEl('ram-batch-clear', '');
// waiting for a card
setEl('ram-batch-spin', '');
// waiting for a card: the explicit prompt, no throbber
app.setLast({ active: true, phase: 'waiting_card', attempts: [], counts: {}, attempts_total: 0, notice: '' });
app.ramBatchRender();
assert.strictEqual(els['ram-batch-state'].textContent, 'Waiting for a card...');
assert.strictEqual(els['ram-batch-state'].textContent, 'Insert next card. Waiting for a card...');
assert.ok(els['ram-batch-spin'].classes['hidden']);
assert.ok(els['ram-batch-stop'].classes['hidden'] === undefined);
assert.ok(els['ram-batch-start'].classes['hidden']);
assert.ok(els['ram-batch-clear'].disabled); // the server refuses a clear while active
@@ -177,12 +179,24 @@ test('ramBatchRender shows the phase, the counts and the stop button', () => {
attempts_total: 3, notice: 'Card 897… installed.', current: { iccid: '8970119000004600098', preset: 'Alfa' } });
app.ramBatchRender();
assert.match(els['ram-batch-state'].textContent, /Installing\.\.\. 8970119000004600098 — Alfa/);
assert.ok(els['ram-batch-spin'].classes['hidden'] === undefined); // the install throbber
assert.match(els['ram-batch-counts'].textContent, /Installed: 2 · Failed: 1 · Skipped: 0 · 3 attempts/);
assert.strictEqual(els['ram-batch-notice'].textContent, 'Card 897… installed.');
// stopping
app.setLast({ active: true, phase: 'stopping', attempts: [], counts: {}, attempts_total: 0 });
// a new install clears the previous notice: an empty one hides the box
app.setLast({ active: true, phase: 'installing', attempts: [], counts: {}, attempts_total: 3,
notice: '', current: { iccid: '8970119000004600106' } });
app.ramBatchRender();
assert.ok(els['ram-batch-notice'].classes['hidden']);
// stopping while a card is still being installed: the throbber stays
app.setLast({ active: true, phase: 'stopping', attempts: [], counts: {}, attempts_total: 0,
current: { iccid: '8970119000004600098' } });
app.ramBatchRender();
assert.ok(els['ram-batch-spin'].classes['hidden'] === undefined);
assert.match(els['ram-batch-state'].textContent, /Stopping after the current card\.\.\./);
// ...but not once the install finished (stopping while waiting)
app.setLast({ active: true, phase: 'stopping', attempts: [], counts: {}, attempts_total: 0, current: null });
app.ramBatchRender();
assert.ok(els['ram-batch-spin'].classes['hidden']);
assert.strictEqual(els['ram-batch-stop'].textContent, 'Stopping...');
assert.ok(els['ram-batch-stop'].disabled);
// stopped
@@ -248,7 +262,7 @@ test('the panel headline follows the live summary (phase and step)', () => {
// ...and back to waiting when the card is gone
app.ramBatchApplyStatus({ ram_batch: { active: true, phase: 'waiting_card', attempts_total: 0,
counts: { installed: 0, failed: 0, skipped: 0 } } });
assert.strictEqual(els['ram-batch-state'].textContent, 'Waiting for a card...');
assert.strictEqual(els['ram-batch-state'].textContent, 'Insert next card. Waiting for a card...');
});
test('the stop and clear calls hit their endpoints', async () => {