Antraege durchsuchbar, Fortschritt sichtbar, Spieler an einem Stueck

Der Abgleich zeigt jetzt, was er tut. Gelesen wird zuerst von jedem Board die
erste Seite - danach steht der Umfang fest, und der Balken zeigt einen
ehrlichen Anteil statt einer Schaetzung. Ein Protokoll schreibt Seite fuer
Seite mit.

Beide Antragslisten lassen sich durchsuchen und wahlweise mit dem neuesten
oder dem aeltesten Antrag zuerst anzeigen. Die Liste ohne zugeordneten
Spieler blaettert seitenweise, statt bei fuenfhundert Eintraegen die ersten
fuenfzig zu zeigen und den Rest zu verschweigen.

Neu darueber: "Ersteller ohne Spieler" - dieselben Antraege, nach Ersteller
zusammengefasst. Wer dreiundzwanzig Antraege gestellt hat, faellt dort auf,
waehrend er zwischen fuenfhundert Einzelantraegen untergeht. Ein Klick legt
den Spieler mit bereits eingetragenem Forum-Namen an.

Ein Spieler laesst sich jetzt an einem Stueck abarbeiten, statt zwischen drei
Seiten zu wechseln:

- Seine Forums-Antraege stehen auf der Spielerseite, aeltester zuerst, jeder
  als Link ins Forum. Offene sind dort direkt entscheidbar, ueber denselben
  Weg wie auf der Antraege-Seite - danach stehen sie dort nicht mehr offen.
- Pakete, die noch in einer Import-Vorschau liegen, erscheinen unter "Offene
  Pakete aus dem Abgleich" und lassen sich einzeln oder am Stueck buchen.
  Gebuchtes wird ueberall abgehakt, wo dieselbe Bestellung noch offen liegt,
  auch in einem zweiten Import - doppelt buchen ist ausgeschlossen. Wer ein
  Paket gar nicht buchen will, legt es weg, ohne das Konto zu beruehren.

Die beiden Antrags-Dialoge liegen dafuer jetzt unter components/, weil beide
Seiten sie brauchen.
This commit is contained in:
2026-09-21 00:49:38 +02:00
parent e65fdfc0ad
commit 293d882cb4
16 changed files with 1655 additions and 431 deletions
+104
View File
@@ -311,3 +311,107 @@ describe('Konten beim Abgleich', () => {
assert.deepEqual(await scraper.steamIdsOf(spieler.id), []);
});
});
describe('Sortieren, Blättern und Suchen', () => {
before(async () => {
// Eigener Namensraum, damit die Faelle davor nicht hineinspielen.
for (const id of [8801, 8802, 8803, 8804, 8805]) {
await offenerThread(id, `Serienantrag ${id}`, 'Vielschreiber');
}
});
it('sortiert nach jüngstem und ältestem Antrag', async () => {
const neueste = await forum.listUnassignedThreads({ query: 'Vielschreiber', order: 'newest' });
assert.deepEqual(
neueste.items.map((t) => t.threadId),
[8805, 8804, 8803, 8802, 8801],
);
const aelteste = await forum.listUnassignedThreads({ query: 'Vielschreiber', order: 'oldest' });
assert.deepEqual(
aelteste.items.map((t) => t.threadId),
[8801, 8802, 8803, 8804, 8805],
);
});
it('blättert seitenweise durch und nennt die volle Zahl', async () => {
const erste = await forum.listUnassignedThreads({
query: 'Vielschreiber',
order: 'oldest',
take: 2,
});
assert.deepEqual(
erste.items.map((t) => t.threadId),
[8801, 8802],
);
assert.equal(erste.total, 5);
const zweite = await forum.listUnassignedThreads({
query: 'Vielschreiber',
order: 'oldest',
take: 2,
skip: 2,
});
assert.deepEqual(
zweite.items.map((t) => t.threadId),
[8803, 8804],
'keine Ueberschneidung mit der ersten Seite',
);
});
it('durchsucht auch die Arbeitsliste', async () => {
const spieler = await players.createPlayer(
{ displayName: 'Suchbar', steamId: '76561198000015555', forumName: 'Suchbar' },
ctx,
);
await offenerThread(8901, 'Ein ganz bestimmter Antrag', 'Suchbar');
await offenerThread(8902, 'Etwas voellig anderes', 'Suchbar');
await forum.claimThreadsForPlayer(spieler.id, ['Suchbar']);
const treffer = await forum.listThreads({ onlyOpen: true, query: 'bestimmter' });
assert.deepEqual(
treffer.map((t) => t.threadId),
[8901],
);
const nachAutor = await forum.listThreads({ onlyOpen: true, query: 'Suchbar' });
assert.equal(nachAutor.length, 2, 'die Suche greift auch auf den Ersteller');
});
});
describe('Ersteller ohne Spieler', () => {
it('fasst die Anträge je Ersteller zusammen', async () => {
const liste = await forum.listUntrackedAuthors();
const vielschreiber = liste.items.find((a) => a.authorName === 'Vielschreiber');
assert.ok(vielschreiber, 'wer fuenf Antraege gestellt hat, faellt auf');
assert.equal(vielschreiber?.threadCount, 5);
assert.equal(vielschreiber?.latestThreadId, 8805);
});
it('führt niemanden auf, der längst einem Spieler gehört', async () => {
const liste = await forum.listUntrackedAuthors();
assert.equal(
liste.items.some((a) => a.authorName === 'Suchbar'),
false,
);
});
it('verschwindet aus der Liste, sobald der Spieler angelegt ist', async () => {
assert.equal(
(await forum.listUntrackedAuthors()).items.some((a) => a.authorName === 'Vielschreiber'),
true,
);
await players.createPlayer(
{ displayName: 'Vielschreiber', steamId: '76561198000016666', forumName: 'Vielschreiber' },
ctx,
);
assert.equal(
(await forum.listUntrackedAuthors()).items.some((a) => a.authorName === 'Vielschreiber'),
false,
'seine Antraege stehen jetzt in der Arbeitsliste',
);
});
});