feat: Add bulk actions for help center articles (translate, status change, delete) (#14137)

Fixes
https://linear.app/chatwoot/issue/CW-6950/support-bulk-actions-for-publish-archive-move-to-draft-delete-in

How to test

1. Go to Help Center → Articles
2. Select articles using checkboxes → bulk bar appears
3. Click Publish/Draft/Archive → articles update, list refreshes
4. Click Delete → confirmation dialog → articles removed
5. Click Translate (requires Captain enabled) → select locale + category
→ translation starts
6. Try translating to a locale that already has translations → warning
with links to existing articles → "Overwrite and translate" proceeds
8. Single article: click three-dot menu → Translate → same dialog opens
for that article



https://github.com/user-attachments/assets/7c76495e-f89e-4456-92bd-a6639a9992f4

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pranav
2026-04-24 09:13:43 -07:00
committed by GitHub
co-authored by Claude Opus 4.7
parent 751c28d94d
commit 2ada713f29
10 changed files with 486 additions and 22 deletions
@@ -17,6 +17,7 @@ import CardLayout from 'dashboard/components-next/CardLayout.vue';
import DropdownMenu from 'dashboard/components-next/dropdown-menu/DropdownMenu.vue';
import Button from 'dashboard/components-next/button/Button.vue';
import Avatar from 'dashboard/components-next/avatar/Avatar.vue';
import Checkbox from 'dashboard/components-next/checkbox/Checkbox.vue';
const props = defineProps({
id: {
@@ -47,9 +48,26 @@ const props = defineProps({
type: Number,
required: true,
},
isSelected: {
type: Boolean,
default: false,
},
selectable: {
type: Boolean,
default: false,
},
showSelectionControl: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['openArticle', 'articleAction']);
const emit = defineEmits([
'openArticle',
'articleAction',
'toggleSelect',
'hover',
]);
const { t } = useI18n();
@@ -143,14 +161,27 @@ const handleClick = id => {
</script>
<template>
<CardLayout>
<CardLayout
:selectable="selectable"
class="relative"
@mouseenter="emit('hover', true)"
@mouseleave="emit('hover', false)"
>
<div
v-show="showSelectionControl"
class="absolute top-7 ltr:left-3 rtl:right-3"
>
<Checkbox :model-value="isSelected" @change="emit('toggleSelect', id)" />
</div>
<div class="flex justify-between w-full gap-1">
<span
class="text-base cursor-pointer hover:underline underline-offset-2 hover:text-n-blue-11 text-n-slate-12 line-clamp-1"
@click="handleClick(id)"
>
{{ title }}
</span>
<div class="flex items-center gap-2 min-w-0">
<span
class="text-base cursor-pointer hover:underline underline-offset-2 hover:text-n-blue-11 text-n-slate-12 line-clamp-1"
@click="handleClick(id)"
>
{{ title }}
</span>
</div>
<div class="flex items-center gap-2">
<span
class="text-xs font-medium inline-flex items-center h-6 px-2 py-0.5 rounded-md bg-n-alpha-2"