Manage entries at scale

- the admin uses the full window width, table cells stop wrapping
- columns sort by number, title, project, status, date and author
- filters sit in one row with search first and a page size next to them
- entries carry a real date: publish_at on create and change, publishing
  keeps that date, a date in the past publishes backdated
This commit is contained in:
Matthias G
2026-08-01 15:43:05 +02:00
parent f8bc2d6108
commit cd3bf3f2b4
14 changed files with 221 additions and 44 deletions
+15 -4
View File
@@ -180,13 +180,24 @@ describe('Statusübergänge', () => {
expect(dropped.ok && dropped.entry.publishAt).toBeNull()
})
it('lehnt einen Termin in der Vergangenheit ab', async () => {
it('veröffentlicht rückwirkend, wenn der Termin in der Vergangenheit liegt', async () => {
const { entry } = await ready()
const earlier = new Date(Date.now() - 60 * 1000).toISOString()
const earlier = new Date(Date.now() - 60 * 60 * 1000)
const state = await performScheduleEntry(adminViewer(), { id: entry.id, publishAt: earlier })
const state = await performScheduleEntry(adminViewer(), { id: entry.id, publishAt: earlier.toISOString() })
expect(state).toMatchObject({ ok: false, error: 'schedulePast' })
expect(state).toMatchObject({ ok: true })
expect(state.ok && state.entry.status).toBe('published')
expect(state.ok && state.entry.publishAt).toBe(earlier.toISOString())
})
it('übernimmt beim Veröffentlichen ein mitgegebenes Datum', async () => {
const { entry } = await ready()
const backdated = new Date('2026-01-15T09:00:00.000Z')
const state = await performPublishEntry(adminViewer(), { id: entry.id, publishAt: backdated.toISOString() })
expect(state.ok && state.entry.publishAt).toBe(backdated.toISOString())
})
it('lehnt einen Übergang ab, den der Status nicht hergibt', async () => {