From fa07a4cab6b05b9eadb7a9a40d399f1ecf00e21c Mon Sep 17 00:00:00 2001 From: Dominik Klein Date: Thu, 25 Apr 2024 15:53:47 +0200 Subject: [PATCH] Feature: Desktop-View - Added new components CommonSimpleTable and CommonActionMenu. Co-authored-by: Dusan Vuckovic Co-authored-by: Martin Gruner Co-authored-by: Dominik Klein Co-authored-by: Benjamin Scharf --- .../CommonActionMenu/CommonActionMenu.vue | 100 ++++++++++++ .../__tests__/CommonActionMenu.spec.ts | 104 +++++++++++++ .../CommonPopover/CommonPopover.vue | 21 ++- .../CommonPopover/CommonPopoverMenu.vue | 70 ++++----- .../CommonPopover/CommonPopoverMenuItem.vue | 26 +++- .../__tests__/CommonPopoverMenu.spec.ts | 27 ++++ .../desktop/components/CommonPopover/types.ts | 8 +- .../CommonPopover/usePopoverMenu.ts | 68 ++++++++ .../CommonSimpleTable/CommonSimpleTable.vue | 54 +++++++ .../__tests__/CommonSimpleTable.spec.ts | 87 +++++++++++ .../CommonSimpleTable.spec.ts.snapshot.txt | 83 ++++++++++ .../components/CommonSimpleTable/types.ts | 12 ++ .../desktop/initializer/3RD-PARTY-ICONS.md | 1 + .../assets/three-dots-vertical.svg | 3 + .../pages/dashboard/views/Playground.vue | 145 +++++++++++++++++- i18n/zammad.pot | 5 + 16 files changed, 766 insertions(+), 48 deletions(-) create mode 100644 app/frontend/apps/desktop/components/CommonActionMenu/CommonActionMenu.vue create mode 100644 app/frontend/apps/desktop/components/CommonActionMenu/__tests__/CommonActionMenu.spec.ts create mode 100644 app/frontend/apps/desktop/components/CommonPopover/usePopoverMenu.ts create mode 100644 app/frontend/apps/desktop/components/CommonSimpleTable/CommonSimpleTable.vue create mode 100644 app/frontend/apps/desktop/components/CommonSimpleTable/__tests__/CommonSimpleTable.spec.ts create mode 100644 app/frontend/apps/desktop/components/CommonSimpleTable/__tests__/CommonSimpleTable.spec.ts.snapshot.txt create mode 100644 app/frontend/apps/desktop/components/CommonSimpleTable/types.ts create mode 100644 app/frontend/apps/desktop/initializer/assets/three-dots-vertical.svg diff --git a/app/frontend/apps/desktop/components/CommonActionMenu/CommonActionMenu.vue b/app/frontend/apps/desktop/components/CommonActionMenu/CommonActionMenu.vue new file mode 100644 index 000000000000..901fef403573 --- /dev/null +++ b/app/frontend/apps/desktop/components/CommonActionMenu/CommonActionMenu.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/app/frontend/apps/desktop/components/CommonActionMenu/__tests__/CommonActionMenu.spec.ts b/app/frontend/apps/desktop/components/CommonActionMenu/__tests__/CommonActionMenu.spec.ts new file mode 100644 index 000000000000..16e43933c01b --- /dev/null +++ b/app/frontend/apps/desktop/components/CommonActionMenu/__tests__/CommonActionMenu.spec.ts @@ -0,0 +1,104 @@ +// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ + +import CommonActionMenu from '#desktop/components/CommonActionMenu/CommonActionMenu.vue' +import renderComponent from '#tests/support/components/renderComponent.ts' + +const fn = vi.fn() +describe('CommonActionMenu', () => { + let view: ReturnType + + const actions = [ + { + key: 'delete-foo', + label: 'Delete Foo', + icon: 'trash3', + onClick: ({ id }: { id: string }) => { + fn(id) + }, + }, + { + key: 'change-foo', + label: 'Change Foo', + icon: 'person-gear', + onClick: ({ id }: { id: string }) => { + fn(id) + }, + }, + ] + + beforeEach(() => { + view = renderComponent(CommonActionMenu, { + props: { + entity: { + id: 'foo-test-action', + }, + actions, + }, + }) + }) + + it('shows action menu button by default', () => { + expect(view.getByIconName('three-dots-vertical')).toBeInTheDocument() + }) + + it('calls onClick handler when action is clicked', async () => { + await view.events.click(view.getByIconName('three-dots-vertical')) + + expect(view.getByIconName('trash3')).toBeInTheDocument() + expect(view.getByIconName('person-gear')).toBeInTheDocument() + + await view.events.click(view.getByText('Change Foo')) + + expect(fn).toHaveBeenCalledWith('foo-test-action') + }) + + it('finds corresponding a11y controls', async () => { + const id = view + .getByLabelText('Action menu button') + .getAttribute('aria-controls') + + await view.events.click(view.getByIconName('three-dots-vertical')) + + const popover = document.getElementById(id as string) + + expect(popover?.getAttribute('id')).toEqual(id) + }) + + describe('single action mode', () => { + beforeEach(async () => { + await view.rerender({ + actions: [actions[0]], + }) + }) + + it('adds aria label on single action button', () => { + expect(view.getByLabelText('Delete Foo')).toBeInTheDocument() + }) + + it('supports single action mode', () => { + expect( + view.queryByIconName('three-dots-vertical'), + ).not.toBeInTheDocument() + + expect(view.getByIconName('trash3')).toBeInTheDocument() + }) + + it('calls onClick handler when action is clicked', async () => { + await view.events.click(view.getByIconName('trash3')) + + expect(fn).toHaveBeenCalledWith('foo-test-action') + }) + + it('renders single action if prop is set', async () => { + await view.rerender({ + noSingleActionMode: true, + }) + + expect(view.queryByIconName('trash3')).not.toBeInTheDocument() + + await view.events.click(view.getByIconName('three-dots-vertical')) + + expect(view.getByIconName('trash3')).toBeInTheDocument() + }) + }) +}) diff --git a/app/frontend/apps/desktop/components/CommonPopover/CommonPopover.vue b/app/frontend/apps/desktop/components/CommonPopover/CommonPopover.vue index e9c3fa495ba9..ecb91043dfcd 100644 --- a/app/frontend/apps/desktop/components/CommonPopover/CommonPopover.vue +++ b/app/frontend/apps/desktop/components/CommonPopover/CommonPopover.vue @@ -1,7 +1,13 @@