Skip to content

Commit

Permalink
I6528 2 (#461)
Browse files Browse the repository at this point in the history
* pkp/pkp-lib#6528 Bulk delete - Adjust permissions and the UI for improved accessibility

* pkp/pkp-lib#6528 Hide disabled checkbox for non sr users

* pkp/pkp-lib#6528 Improve accessibility to not announce the button icon

* pkp/pkp-lib#6528 Disable the delete action instead of hiding it when no incomplete submission is listed

* pkp/pkp-lib#6528 rename locale keys
  • Loading branch information
jardakotesovec authored Dec 16, 2024
1 parent 67a3095 commit d43997a
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 61 deletions.
12 changes: 6 additions & 6 deletions public/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,12 @@ window.pkp = {
'acceptInvitation.verifyOrcid': 'Verify ORCID iD',
'admin.jobs.failed.action.redispatch': 'Try Again',
'admin.jobs.failed.action.redispatch.all': 'Requeue All Failed Jobs',
'admin.submissions.incomplete.bulkDelete.body':
'##admin.submissions.incomplete.bulkDelete.body##',
'admin.submissions.incomplete.bulkDelete.column.description':
'##admin.submissions.incomplete.bulkDelete.column.description##',
'admin.submissions.incomplete.bulkDelete.confirm':
'##admin.submissions.incomplete.bulkDelete.confirm##',
'dashboard.submissions.incomplete.bulkDelete.body':
'##dashboard.submissions.incomplete.bulkDelete.body##',
'dashboard.submissions.incomplete.bulkDelete.column.description':
'##dashboard.submissions.incomplete.bulkDelete.column.description##',
'dashboard.submissions.incomplete.bulkDelete.confirm':
'##dashboard.submissions.incomplete.bulkDelete.confirm##',
'admin.version': 'Version',
'article.article': 'Article',
'article.metadata': 'Metadata',
Expand Down
8 changes: 8 additions & 0 deletions src/components/Button/Button.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ export const Warnable = {
},
};

export const WarnableDisabled = {
args: {
slot: 'Delete',
isWarnable: true,
isDisabled: true,
},
};

export const IsCompact = {
args: {
slot: 'Delete',
Expand Down
4 changes: 2 additions & 2 deletions src/components/Button/Button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
@focus="emit('focus')"
@blur="emit('blur')"
>
<Icon v-if="icon" class="h-5 w-5" :icon="icon" />
<Icon v-if="icon" class="h-5 w-5" :icon="icon" aria-hidden="true" />
<slot />
</component>
</template>
Expand Down Expand Up @@ -82,7 +82,7 @@ const styles = computed(() => ({
'text-primary border-light hover:text-hover disabled:text-disabled ':
isSecondary.value,
// Warnable
'text-negative border-light': props.isWarnable,
'text-negative border-light disabled:text-disabled': props.isWarnable,
// Warnable & Secondary have white background when its not link
'bg-secondary': (isSecondary.value || props.isWarnable) && !props.isLink,
// Active
Expand Down
13 changes: 12 additions & 1 deletion src/components/DropdownActions/DropdownActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
v-for="(action, i) in actions"
:key="i"
v-slot="{active, close}"
:disabled="action.disabled || false"
>
<div class="min-w-[96px]">
<PkpButton
Expand All @@ -57,6 +58,7 @@
:is-warnable="action.isWarnable"
:class="i !== actions.length - 1 ? 'border-b' : ''"
size-variant="fullWidth"
:is-disabled="action.disabled || false"
class="border-light"
@click="
() => {
Expand All @@ -82,7 +84,16 @@ import ButtonIcon from '@/components/ButtonIcon/ButtonIcon.vue';
import Icon from '@/components/Icon/Icon.vue';
defineProps({
/** An array of action objects. Each object should contain `label` (string), `url` (string) to navigate to if the action involves a link, or `name` (string) to perform the action when clicked, an optional `icon` (string) and `isWarnable` (boolean) if the button needs the "warning" button styling from `<Button>` component. */
/**
* An array of action objects.
* Each object should contain
* `label` (string),
* `url` (string) to navigate to if the action involves a link, or
* `name` (string) to perform the action when clicked, an optional
* `icon` (string) and
* `isWarnable` (boolean) if the button needs the "warning" button styling from `<Button>` component.
* `disabled` (boolean) when the item is not available
* */
actions: {
type: Array,
required: true,
Expand Down
1 change: 1 addition & 0 deletions src/components/Table/TableCellSelect.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<TableCell>
<input
:class="{'sr-only': disabled}"
type="checkbox"
:checked="props.checked"
:aria-describedby="describedBy"
Expand Down
10 changes: 6 additions & 4 deletions src/pages/dashboard/DashboardPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
</h1>
<div class="mt-2">
<div class="flex justify-between">
<div class="flex flex-row space-x-2">
<div class="flex flex-row items-center space-x-3">
<PkpButton @click="store.openFiltersModal">
{{ t('common.filter') }}
</PkpButton>
<!-- Temporarly hide it on main branch until permissions details are decided -->
<!--<DashboardBulkDeleteButton />-->
<DashboardBulkActions />
<DashboardBulkDeleteButton />
</div>
<div>
<Search
Expand Down Expand Up @@ -50,7 +50,9 @@
import PkpButton from '@/components/Button/Button.vue';
import DashboardActiveFilters from './components/DashboardActiveFilters.vue';
import DashboardTable from './components/DashboardTable/DashboardTable.vue';
//import DashboardBulkDeleteButton from './components/DashboardBulkDeleteButton.vue';
import DashboardBulkActions from './components/DashboardBulkActions.vue';
import DashboardBulkDeleteButton from './components/DashboardBulkDeleteButton.vue';
import Search from '@/components/Search/Search.vue';
import {useDashboardPageStore} from './dashboardPageStore';
Expand Down
41 changes: 41 additions & 0 deletions src/pages/dashboard/components/DashboardBulkActions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<template>
<DropdownActions
v-if="actions.length"
:label="t('common.moreActions')"
:display-as-ellipsis="true"
:actions="actions"
direction="right"
@action="handleAction"
/>
</template>
<script setup>
import {computed} from 'vue';
import DropdownActions from '@/components/DropdownActions/DropdownActions.vue';
import {useLocalize} from '@/composables/useLocalize';
const {t} = useLocalize();
const actions = computed(() => {
const _actions = [];
if (dashboardStore.bulkDeleteIsAvailableForUser) {
_actions.push({
label: t('dashboard.submissions.incomplete.bulkDelete.button'),
name: 'bulkDeleteSelectionEnable',
isWarnable: true,
icon: 'Cancel',
disabled: dashboardStore.bulkDeleteSubmissionIdsCanBeDeleted.length === 0,
});
}
return _actions;
});
import {useDashboardPageStore} from '../dashboardPageStore';
const dashboardStore = useDashboardPageStore();
function handleAction(actionName, actionArgs = {}) {
dashboardStore[actionName](actionArgs);
}
</script>
18 changes: 5 additions & 13 deletions src/pages/dashboard/components/DashboardBulkDeleteButton.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
<template>
<PkpButton
v-if="store.bulkDeleteDisplayDeleteButton"
:is-disabled="store.bulkDeleteSubmissionIdsCanBeDeleted.length === 0"
:is-active="
store.bulkDeleteEnabled && store.bulkDeleteSelectedItems.length === 0
"
:is-warnable="!!store.bulkDeleteSelectedItems.length"
@click="
() =>
store.bulkDeleteSelectedItems.length
? store.bulkDeleteActionDelete()
: store.bulkDeleteToggleEnabled()
"
v-if="store.bulkDeleteSelectionEnabled"
:is-disabled="store.bulkDeleteSelectedItems.length === 0"
:is-warnable="true"
@click="() => store.bulkDeleteActionDelete()"
>
{{ t('admin.submissions.incomplete.bulkDelete.button') }}
{{ t('dashboard.submissions.incomplete.bulkDelete.button') }}
</PkpButton>
</template>

Expand Down
11 changes: 8 additions & 3 deletions src/pages/dashboard/components/DashboardTable/DashboardTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
@sort="(columnId) => $emit('sortColumn', columnId)"
>
<TableHeader>
<TableColumn v-if="dashboardStore.bulkDeleteEnabled">
<TableColumn v-if="dashboardStore.bulkDeleteSelectionEnabled">
<span class="sr-only">
{{ t('admin.submissions.incomplete.bulkDelete.column.description') }}
{{
t('dashboard.submissions.incomplete.bulkDelete.column.description')
}}
</span>
</TableColumn>
<TableColumn
Expand All @@ -20,7 +22,10 @@
</TableHeader>
<TableBody>
<TableRow v-for="item in items" :key="item.id">
<CellBulkDelete v-if="dashboardStore.bulkDeleteEnabled" :item="item" />
<CellBulkDelete
v-if="dashboardStore.bulkDeleteSelectionEnabled"
:item="item"
/>
<component
:is="cellComponents[column.componentName] || column.componentName"
v-for="column in columns"
Expand Down
69 changes: 43 additions & 26 deletions src/pages/dashboard/composables/useDashboardBulkDelete.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ export function useDashboardBulkDelete({
}) {
const {t} = useLocalize();

// Display only for admins on editorial dashboard and for author dashboard, where user can delete own submissions
const bulkDeleteDisplayDeleteButton = computed(() => {
if (
dashboardPage === DashboardPageTypes.EDITORIAL_DASHBOARD &&
hasCurrentUserAtLeastOneRole([pkp.const.ROLE_ID_SITE_ADMIN])
) {
return true;
} else if (dashboardPage === DashboardPageTypes.MY_SUBMISSIONS) {
return true;
}
/**
* Enabling the checkboxes to select submissions to be deleted
* */
const bulkDeleteSelectionEnabled = ref(false);
function bulkDeleteSelectionEnable() {
bulkDeleteSelectionEnabled.value = true;
}

return false;
});
function bulkDeleteSelectionDisable() {
bulkDeleteSelectionEnabled.value = false;
}

const bulkDeleteEnabled = ref(false);
/**
* Managing the list of selected items
* */
const bulkDeleteSelectedItems = ref([]);
function bulkDeleteSelectItem(submissionId) {
if (!bulkDeleteSelectedItems.value.includes(submissionId)) {
Expand All @@ -42,10 +42,9 @@ export function useDashboardBulkDelete({
);
}

function bulkDeleteToggleEnabled() {
bulkDeleteEnabled.value = !bulkDeleteEnabled.value;
}

/**
* Permissions
* */
const {
hasCurrentUserAtLeastOneAssignedRoleInAnyStage,
hasCurrentUserAtLeastOneRole,
Expand All @@ -55,7 +54,10 @@ export function useDashboardBulkDelete({
// incomplete submission can be deleted by author of the submission or admin
if (submission.submissionProgress)
if (
hasCurrentUserAtLeastOneRole([pkp.const.ROLE_ID_SITE_ADMIN]) ||
hasCurrentUserAtLeastOneRole([
pkp.const.ROLE_ID_SITE_ADMIN,
pkp.const.ROLE_ID_MANAGER,
]) ||
hasCurrentUserAtLeastOneAssignedRoleInAnyStage(submission, [
pkp.const.ROLE_ID_AUTHOR,
])
Expand All @@ -66,6 +68,21 @@ export function useDashboardBulkDelete({
return false;
}

const bulkDeleteIsAvailableForUser = computed(() => {
if (
dashboardPage === DashboardPageTypes.EDITORIAL_DASHBOARD &&
hasCurrentUserAtLeastOneRole([
pkp.const.ROLE_ID_SITE_ADMIN,
pkp.const.ROLE_ID_MANAGER,
])
) {
return true;
} else if (dashboardPage === DashboardPageTypes.MY_SUBMISSIONS) {
return true;
}
return false;
});

const bulkDeleteSubmissionIdsCanBeDeleted = computed(() => {
const submissionIds = [];
if (submissions.value && submissions.value?.length) {
Expand All @@ -75,7 +92,6 @@ export function useDashboardBulkDelete({
}
});
}

return submissionIds;
});

Expand All @@ -94,14 +110,14 @@ export function useDashboardBulkDelete({

function bulkDeleteResetSelection() {
bulkDeleteSelectedItems.value = [];
bulkDeleteEnabled.value = false;
bulkDeleteSelectionEnabled.value = false;
}

function bulkDeleteActionDelete() {
const {openDialog} = useModal();
openDialog({
title: t('admin.submissions.incomplete.bulkDelete.confirm'),
message: t('admin.submissions.incomplete.bulkDelete.body'),
title: t('dashboard.submissions.incomplete.bulkDelete.confirm'),
message: t('dashboard.submissions.incomplete.bulkDelete.body'),
actions: [
{
label: t('common.confirm'),
Expand All @@ -115,6 +131,7 @@ export function useDashboardBulkDelete({
label: t('common.cancel'),
isWarnable: true,
callback: (close) => {
bulkDeleteResetSelection();
close();
},
},
Expand All @@ -125,10 +142,10 @@ export function useDashboardBulkDelete({
}

return {
bulkDeleteDisplayDeleteButton,
bulkDeleteEnabled,
bulkDeleteToggleEnabled,

bulkDeleteIsAvailableForUser,
bulkDeleteSelectionEnabled,
bulkDeleteSelectionEnable,
bulkDeleteSelectionDisable,
bulkDeleteSelectedItems,
bulkDeleteSelectItem,
bulkDeleteDeselectItem,
Expand Down
14 changes: 8 additions & 6 deletions src/pages/dashboard/dashboardPageStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,11 @@ export const useDashboardPageStore = defineComponentStore(
* Bulk delete
*/
const {
bulkDeleteDisplayDeleteButton,
bulkDeleteIsAvailableForUser,

bulkDeleteEnabled,
bulkDeleteToggleEnabled,
bulkDeleteSelectionEnabled,
bulkDeleteSelectionEnable,
bulkDeleteSelectionDisable,

bulkDeleteSelectedItems,
bulkDeleteSelectItem,
Expand Down Expand Up @@ -436,10 +437,11 @@ export const useDashboardPageStore = defineComponentStore(
setCurrentPage,

// Bulk delete
bulkDeleteDisplayDeleteButton,
bulkDeleteIsAvailableForUser,

bulkDeleteEnabled,
bulkDeleteToggleEnabled,
bulkDeleteSelectionEnabled,
bulkDeleteSelectionEnable,
bulkDeleteSelectionDisable,

bulkDeleteSelectedItems,
bulkDeleteSelectItem,
Expand Down

0 comments on commit d43997a

Please sign in to comment.