feat(18-01): money list column, danger record actions, preview Edit rule and table kit (task 2)
- columns.yaml type: money with currency or currencyFrom (exactly one), never searchable, not sortable by default; every list row carries the currencyFrom column's value under its own key; the schema serves currency and currencyFrom on the column - pact.AdminRecordAction.Danger, served as danger on cabana.RecordAction (absent when false); RecordActions.vue passes it to the confirm dialog - CellValue money kind through formatMoney with the row's code, the em dash when empty and the amount alone without a code; DataTable aligns money headers and cells to the right - PreviewView renders Edit only when a registered value field allows update (F6) - main.css .summer-table* and .summer-stat__note kit classes (F7) over --c-* variables; cabana README kit rows - fixture record actions void (danger) and resend; TestMoneyListCompile, TestMoneyListSmoke and TestRecordActionDangerSmoke; regenerated OpenAPI and TS types; rebuilt dist; lists-and-filters and admin-controllers docs
This commit is contained in:
@@ -14,6 +14,7 @@ const actions = [
|
||||
{ name: 'reinstate', label: 'Reinstate', confirm: 'Lift the ban on this person?' },
|
||||
{ name: 'activate', label: 'Activate' },
|
||||
{ name: 'markup', label: '<b>Bold</b>' },
|
||||
{ name: 'ban', label: 'Ban', confirm: 'Ban this person? This cannot be undone.', danger: true },
|
||||
]
|
||||
const strings = {
|
||||
'backend::lang.form.action_confirm': { other: 'Run “:action” on this record?' },
|
||||
@@ -60,7 +61,7 @@ describe('record actions component (UI-SPEC S2, D-10)', () => {
|
||||
it('renders the offered actions in the given order, labels as text', () => {
|
||||
const { wrapper } = mountActions({})
|
||||
const buttons = wrapper.findAll('[data-record-action]')
|
||||
expect(buttons.map((item) => item.attributes('data-record-action'))).toEqual(['reinstate', 'activate', 'markup'])
|
||||
expect(buttons.map((item) => item.attributes('data-record-action'))).toEqual(['reinstate', 'activate', 'markup', 'ban'])
|
||||
expect(buttons[2]!.text()).toBe('<b>Bold</b>')
|
||||
expect(buttons[2]!.find('b').exists()).toBe(false)
|
||||
expect(buttons.every((item) => item.classes().includes('border-border-strong'))).toBe(true)
|
||||
@@ -184,3 +185,25 @@ describe('record actions component (UI-SPEC S2, D-10)', () => {
|
||||
expect(calls).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('danger record actions (UI-SPEC F5)', () => {
|
||||
it('gives the dialog confirm button the danger variant for a danger action, the default otherwise', async () => {
|
||||
const { wrapper } = mountActions({})
|
||||
await button(wrapper, 'ban').trigger('click')
|
||||
await flushPromises()
|
||||
const confirmButton = dialog()!.querySelector<HTMLButtonElement>('[data-action="confirm"]')!
|
||||
expect(confirmButton.className).toContain('bg-danger')
|
||||
expect(confirmButton.className).not.toContain('bg-primary')
|
||||
expect(confirmButton.textContent?.trim()).toBe('Ban')
|
||||
// The footer button itself stays outline.
|
||||
expect(button(wrapper, 'ban').classes()).toContain('border-border-strong')
|
||||
dialog()!.querySelector<HTMLButtonElement>('[data-action="cancel"]')!.click()
|
||||
await flushPromises()
|
||||
|
||||
await button(wrapper, 'activate').trigger('click')
|
||||
await flushPromises()
|
||||
const plain = dialog()!.querySelector<HTMLButtonElement>('[data-action="confirm"]')!
|
||||
expect(plain.className).toContain('bg-primary')
|
||||
expect(plain.className).not.toContain('bg-danger')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user