-
Notifications
You must be signed in to change notification settings - Fork 729
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature: Desktop view - Implement overview preferences.
Co-authored-by: Benjamin Scharf <bs@zammad.com> Co-authored-by: Dusan Vuckovic <dv@zammad.com> Co-authored-by: Florian Liebe <fl@zammad.com> Co-authored-by: Mantas Masalskis <mm@zammad.com>
- Loading branch information
1 parent
b72e5ce
commit e4582cf
Showing
40 changed files
with
1,675 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
app/frontend/apps/desktop/initializer/assets/grip-vertical.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions
45
...end/apps/desktop/pages/personal-setting/__tests__/personal-setting-overviews-a11y.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ | ||
|
||
import { axe } from 'vitest-axe' | ||
|
||
import { visitView } from '#tests/support/components/visitView.ts' | ||
import { mockPermissions } from '#tests/support/mock-permissions.ts' | ||
import { mockUserCurrent } from '#tests/support/mock-userCurrent.ts' | ||
|
||
import { convertToGraphQLId } from '#shared/graphql/utils.ts' | ||
|
||
import { mockUserCurrentOverviewListQuery } from '../graphql/queries/userCurrentOverviewList.mocks.ts' | ||
|
||
const userCurrentOverviewList = [ | ||
{ | ||
id: convertToGraphQLId('Overview', 1), | ||
name: 'Open Tickets', | ||
}, | ||
{ | ||
id: convertToGraphQLId('Overview', 2), | ||
name: 'My Tickets', | ||
}, | ||
{ | ||
id: convertToGraphQLId('Overview', 3), | ||
name: 'All Tickets', | ||
}, | ||
] | ||
|
||
describe('personal settings for token access', () => { | ||
beforeEach(() => { | ||
mockUserCurrent({ | ||
firstname: 'John', | ||
lastname: 'Doe', | ||
}) | ||
mockPermissions(['user_preferences.overview_sorting']) | ||
}) | ||
|
||
it('has no accessibility violations', async () => { | ||
mockUserCurrentOverviewListQuery({ userCurrentOverviewList }) | ||
|
||
const view = await visitView('/personal-setting/ticket-overviews') | ||
|
||
const results = await axe(view.html()) | ||
expect(results).toHaveNoViolations() | ||
}) | ||
}) |
122 changes: 122 additions & 0 deletions
122
...frontend/apps/desktop/pages/personal-setting/__tests__/personal-setting-overviews.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ | ||
|
||
import { getAllByRole } from '@testing-library/vue' | ||
import { visitView } from '#tests/support/components/visitView.ts' | ||
import { mockPermissions } from '#tests/support/mock-permissions.ts' | ||
import { mockUserCurrent } from '#tests/support/mock-userCurrent.ts' | ||
import { waitForNextTick } from '#tests/support/utils.ts' | ||
import { convertToGraphQLId } from '#shared/graphql/utils.ts' | ||
import { mockUserCurrentOverviewListQuery } from '../graphql/queries/userCurrentOverviewList.mocks.ts' | ||
import { mockUserCurrentOverviewResetOrderMutation } from '../graphql/mutations/userCurrentOverviewResetOrder.mocks.ts' | ||
import { getUserCurrentOverviewOrderingUpdatesSubscriptionHandler } from '../graphql/subscriptions/userCurrentOverviewOrderingUpdates.mocks.ts' | ||
|
||
const userCurrentOverviewList = [ | ||
{ | ||
id: convertToGraphQLId('Overview', 1), | ||
name: 'Open Tickets', | ||
}, | ||
{ | ||
id: convertToGraphQLId('Overview', 2), | ||
name: 'My Tickets', | ||
}, | ||
{ | ||
id: convertToGraphQLId('Overview', 3), | ||
name: 'All Tickets', | ||
}, | ||
] | ||
|
||
const userCurrentOverviewListAferReset = userCurrentOverviewList.reverse() | ||
|
||
describe('personal settings for token access', () => { | ||
beforeEach(() => { | ||
mockUserCurrent({ | ||
firstname: 'John', | ||
lastname: 'Doe', | ||
}) | ||
mockPermissions(['user_preferences.overview_sorting']) | ||
}) | ||
|
||
it('shows the overviews order by priority', async () => { | ||
mockUserCurrentOverviewListQuery({ userCurrentOverviewList }) | ||
|
||
const view = await visitView('/personal-setting/ticket-overviews') | ||
|
||
const overviewContainer = view.getByLabelText('Order of ticket overviews') | ||
|
||
const overviews = getAllByRole(overviewContainer, 'listitem') | ||
|
||
userCurrentOverviewList.forEach((overview, index) => { | ||
expect(overviews[index]).toHaveTextContent(overview.name) | ||
}) | ||
}) | ||
|
||
// TODO: Cover the update of overview order when the items are moved around the list. | ||
// We may need to implement a testable mechanism for reordering the list, though, as drag events are not fully | ||
// supported in JSDOM due to missing client-rectangle coordinate mocking. | ||
// One approach could be to add keyboard shortcuts for changing the order, or perhaps even hidden buttons. | ||
|
||
it('allows to reset the order of overviews', async () => { | ||
mockUserCurrentOverviewListQuery({ userCurrentOverviewList }) | ||
|
||
const view = await visitView('/personal-setting/ticket-overviews') | ||
|
||
mockUserCurrentOverviewResetOrderMutation({ | ||
userCurrentOverviewResetOrder: { | ||
success: true, | ||
overviews: userCurrentOverviewListAferReset, | ||
errors: null, | ||
}, | ||
}) | ||
|
||
const resetButton = view.getByRole('button', { | ||
name: 'Reset Overview Order', | ||
}) | ||
|
||
expect(resetButton).toBeInTheDocument() | ||
|
||
await view.events.click(resetButton) | ||
|
||
await waitForNextTick() | ||
|
||
expect( | ||
await view.findByRole('dialog', { name: 'Confirmation' }), | ||
).toBeInTheDocument() | ||
|
||
await view.events.click(view.getByRole('button', { name: 'Yes' })) | ||
|
||
await waitForNextTick() | ||
|
||
userCurrentOverviewListAferReset.forEach((overview) => { | ||
expect(view.getByText(overview.name)).toBeInTheDocument() | ||
}) | ||
}) | ||
|
||
it('updates the overviews list when a new overview is added', async () => { | ||
mockUserCurrentOverviewListQuery({ userCurrentOverviewList }) | ||
|
||
const view = await visitView('/personal-setting/ticket-overviews') | ||
|
||
const overviewUpdateSubscription = | ||
getUserCurrentOverviewOrderingUpdatesSubscriptionHandler() | ||
|
||
userCurrentOverviewList.forEach((overview) => { | ||
expect(view.getByText(overview.name)).toBeInTheDocument() | ||
}) | ||
|
||
overviewUpdateSubscription.trigger({ | ||
userCurrentOverviewOrderingUpdates: { | ||
overviews: [ | ||
...userCurrentOverviewList, | ||
{ | ||
id: convertToGraphQLId('Overview', 4), | ||
name: 'New Overview', | ||
}, | ||
], | ||
}, | ||
}) | ||
|
||
await waitForNextTick() | ||
|
||
expect(view.getByText('New Overview')).toBeInTheDocument() | ||
}) | ||
}) |
51 changes: 51 additions & 0 deletions
51
app/frontend/apps/desktop/pages/personal-setting/components/PersonalSettingOverviewOrder.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ --> | ||
|
||
<script setup lang="ts"> | ||
import Draggable from 'vuedraggable' | ||
export interface OverviewItem { | ||
id: string | ||
name: string | ||
} | ||
const localValue = defineModel<OverviewItem[]>('modelValue') | ||
</script> | ||
|
||
<template> | ||
<div v-if="localValue" class="rounded-lg bg-blue-200 dark:bg-gray-700"> | ||
<!-- :TODO if we add proper a11y support --> | ||
<!-- <span class="hidden" aria-live="assertive" >{{assistiveText}}</span>--> | ||
<span id="drag-and-drop-ticket-overviews" class="sr-only"> | ||
{{ $t('Drag and drop to reorder ticket overview list items.') }} | ||
</span> | ||
|
||
<div class="flex flex-col p-1"> | ||
<Draggable | ||
v-model="localValue" | ||
:animation="100" | ||
draggable=".draggable" | ||
role="list" | ||
ghost-class="invisible" | ||
item-key="id" | ||
> | ||
<template #item="{ element }"> | ||
<div | ||
role="listitem" | ||
draggable="true" | ||
aria-describedby="drag-and-drop-ticket-overviews" | ||
class="draggable flex h-9 cursor-grab items-center gap-2.5 p-2.5 active:cursor-grabbing" | ||
> | ||
<CommonIcon | ||
class="fill-stone-200 dark:fill-neutral-500" | ||
name="grip-vertical" | ||
size="tiny" | ||
/> | ||
<CommonLabel class="w-full text-black dark:text-white"> | ||
{{ $t(element.name) }} | ||
</CommonLabel> | ||
</div> | ||
</template> | ||
</Draggable> | ||
</div> | ||
</div> | ||
</template> |
26 changes: 26 additions & 0 deletions
26
...pps/desktop/pages/personal-setting/graphql/mutations/userCurrentOverviewResetOrder.api.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import * as Types from '#shared/graphql/types.ts'; | ||
|
||
import gql from 'graphql-tag'; | ||
import { ErrorsFragmentDoc } from '../../../../../../shared/graphql/fragments/errors.api'; | ||
import * as VueApolloComposable from '@vue/apollo-composable'; | ||
import * as VueCompositionApi from 'vue'; | ||
export type ReactiveFunction<TParam> = () => TParam; | ||
|
||
export const UserCurrentOverviewResetOrderDocument = gql` | ||
mutation userCurrentOverviewResetOrder { | ||
userCurrentOverviewResetOrder { | ||
success | ||
overviews { | ||
id | ||
name | ||
} | ||
errors { | ||
...errors | ||
} | ||
} | ||
} | ||
${ErrorsFragmentDoc}`; | ||
export function useUserCurrentOverviewResetOrderMutation(options: VueApolloComposable.UseMutationOptions<Types.UserCurrentOverviewResetOrderMutation, Types.UserCurrentOverviewResetOrderMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<Types.UserCurrentOverviewResetOrderMutation, Types.UserCurrentOverviewResetOrderMutationVariables>> = {}) { | ||
return VueApolloComposable.useMutation<Types.UserCurrentOverviewResetOrderMutation, Types.UserCurrentOverviewResetOrderMutationVariables>(UserCurrentOverviewResetOrderDocument, options); | ||
} | ||
export type UserCurrentOverviewResetOrderMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<Types.UserCurrentOverviewResetOrderMutation, Types.UserCurrentOverviewResetOrderMutationVariables>; |
12 changes: 12 additions & 0 deletions
12
...ps/desktop/pages/personal-setting/graphql/mutations/userCurrentOverviewResetOrder.graphql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
mutation userCurrentOverviewResetOrder { | ||
userCurrentOverviewResetOrder { | ||
success | ||
overviews { | ||
id | ||
name | ||
} | ||
errors { | ||
...errors | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...s/desktop/pages/personal-setting/graphql/mutations/userCurrentOverviewResetOrder.mocks.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import * as Types from '#shared/graphql/types.ts'; | ||
|
||
import * as Mocks from '#tests/graphql/builders/mocks.ts' | ||
import * as Operations from './userCurrentOverviewResetOrder.api.ts' | ||
|
||
export function mockUserCurrentOverviewResetOrderMutation(defaults: Mocks.MockDefaultsValue<Types.UserCurrentOverviewResetOrderMutation, Types.UserCurrentOverviewResetOrderMutationVariables>) { | ||
return Mocks.mockGraphQLResult(Operations.UserCurrentOverviewResetOrderDocument, defaults) | ||
} | ||
|
||
export function waitForUserCurrentOverviewResetOrderMutationCalls() { | ||
return Mocks.waitForGraphQLMockCalls<Types.UserCurrentOverviewResetOrderMutation>(Operations.UserCurrentOverviewResetOrderDocument) | ||
} |
22 changes: 22 additions & 0 deletions
22
...ps/desktop/pages/personal-setting/graphql/mutations/userCurrentOverviewUpdateOrder.api.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import * as Types from '#shared/graphql/types.ts'; | ||
|
||
import gql from 'graphql-tag'; | ||
import { ErrorsFragmentDoc } from '../../../../../../shared/graphql/fragments/errors.api'; | ||
import * as VueApolloComposable from '@vue/apollo-composable'; | ||
import * as VueCompositionApi from 'vue'; | ||
export type ReactiveFunction<TParam> = () => TParam; | ||
|
||
export const UserCurrentOverviewUpdateOrderDocument = gql` | ||
mutation userCurrentOverviewUpdateOrder($overviewIds: [ID!]!) { | ||
userCurrentOverviewUpdateOrder(overviewIds: $overviewIds) { | ||
success | ||
errors { | ||
...errors | ||
} | ||
} | ||
} | ||
${ErrorsFragmentDoc}`; | ||
export function useUserCurrentOverviewUpdateOrderMutation(options: VueApolloComposable.UseMutationOptions<Types.UserCurrentOverviewUpdateOrderMutation, Types.UserCurrentOverviewUpdateOrderMutationVariables> | ReactiveFunction<VueApolloComposable.UseMutationOptions<Types.UserCurrentOverviewUpdateOrderMutation, Types.UserCurrentOverviewUpdateOrderMutationVariables>> = {}) { | ||
return VueApolloComposable.useMutation<Types.UserCurrentOverviewUpdateOrderMutation, Types.UserCurrentOverviewUpdateOrderMutationVariables>(UserCurrentOverviewUpdateOrderDocument, options); | ||
} | ||
export type UserCurrentOverviewUpdateOrderMutationCompositionFunctionResult = VueApolloComposable.UseMutationReturn<Types.UserCurrentOverviewUpdateOrderMutation, Types.UserCurrentOverviewUpdateOrderMutationVariables>; |
8 changes: 8 additions & 0 deletions
8
...s/desktop/pages/personal-setting/graphql/mutations/userCurrentOverviewUpdateOrder.graphql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
mutation userCurrentOverviewUpdateOrder($overviewIds: [ID!]!) { | ||
userCurrentOverviewUpdateOrder(overviewIds: $overviewIds) { | ||
success | ||
errors { | ||
...errors | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
.../desktop/pages/personal-setting/graphql/mutations/userCurrentOverviewUpdateOrder.mocks.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import * as Types from '#shared/graphql/types.ts'; | ||
|
||
import * as Mocks from '#tests/graphql/builders/mocks.ts' | ||
import * as Operations from './userCurrentOverviewUpdateOrder.api.ts' | ||
|
||
export function mockUserCurrentOverviewUpdateOrderMutation(defaults: Mocks.MockDefaultsValue<Types.UserCurrentOverviewUpdateOrderMutation, Types.UserCurrentOverviewUpdateOrderMutationVariables>) { | ||
return Mocks.mockGraphQLResult(Operations.UserCurrentOverviewUpdateOrderDocument, defaults) | ||
} | ||
|
||
export function waitForUserCurrentOverviewUpdateOrderMutationCalls() { | ||
return Mocks.waitForGraphQLMockCalls<Types.UserCurrentOverviewUpdateOrderMutation>(Operations.UserCurrentOverviewUpdateOrderDocument) | ||
} |
Oops, something went wrong.