-
-
+
+
+
+
+
+
+
+ {{ t('CAPTAIN.ASSISTANTS.SETTINGS.DELETE.TITLE') }}
+
+
+ {{ t('CAPTAIN.ASSISTANTS.SETTINGS.DELETE.DESCRIPTION') }}
+
+
+
+
+
+
-
-
-
-
-
-
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/captain.routes.js b/app/javascript/dashboard/routes/dashboard/captain/captain.routes.js
index 12c5c53f3..4bc11ba1c 100644
--- a/app/javascript/dashboard/routes/dashboard/captain/captain.routes.js
+++ b/app/javascript/dashboard/routes/dashboard/captain/captain.routes.js
@@ -1,10 +1,14 @@
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
import { INSTALLATION_TYPES } from 'dashboard/constants/installationTypes';
import { frontendURL } from '../../../helper/URLHelper';
-import AssistantIndex from './assistants/Index.vue';
-import AssistantEdit from './assistants/Edit.vue';
-// import AssistantSettings from './assistants/settings/Settings.vue';
+
+import CaptainPageRouteView from './pages/CaptainPageRouteView.vue';
+import AssistantsIndexPage from './pages/AssistantsIndexPage.vue';
+import AssistantEmptyStateIndex from './assistants/Index.vue';
+
+import AssistantSettingsIndex from './assistants/settings/Settings.vue';
import AssistantInboxesIndex from './assistants/inboxes/Index.vue';
+import AssistantPlaygroundIndex from './assistants/playground/Index.vue';
import AssistantGuardrailsIndex from './assistants/guardrails/Index.vue';
import AssistantGuidelinesIndex from './assistants/guidelines/Index.vue';
import AssistantScenariosIndex from './assistants/scenarios/Index.vue';
@@ -13,87 +17,90 @@ import ResponsesIndex from './responses/Index.vue';
import ResponsesPendingIndex from './responses/Pending.vue';
import CustomToolsIndex from './tools/Index.vue';
-export const routes = [
+const meta = {
+ permissions: ['administrator', 'agent'],
+ featureFlag: FEATURE_FLAGS.CAPTAIN,
+ installationTypes: [INSTALLATION_TYPES.CLOUD, INSTALLATION_TYPES.ENTERPRISE],
+};
+
+const metaV2 = {
+ permissions: ['administrator', 'agent'],
+ featureFlag: FEATURE_FLAGS.CAPTAIN_V2,
+ installationTypes: [INSTALLATION_TYPES.CLOUD, INSTALLATION_TYPES.ENTERPRISE],
+};
+
+const assistantRoutes = [
{
- path: frontendURL('accounts/:accountId/captain/assistants'),
- component: AssistantIndex,
- name: 'captain_assistants_index',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
+ path: frontendURL('accounts/:accountId/captain/:assistantId/faqs'),
+ component: ResponsesIndex,
+ name: 'captain_assistants_responses_index',
+ meta,
},
{
- path: frontendURL('accounts/:accountId/captain/assistants/:assistantId'),
- component: AssistantEdit,
- name: 'captain_assistants_edit',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
+ path: frontendURL('accounts/:accountId/captain/:assistantId/documents'),
+ component: DocumentsIndex,
+ name: 'captain_assistants_documents_index',
+ meta,
},
{
- path: frontendURL(
- 'accounts/:accountId/captain/assistants/:assistantId/inboxes'
- ),
+ path: frontendURL('accounts/:accountId/captain/:assistantId/tools'),
+ component: CustomToolsIndex,
+ name: 'captain_tools_index',
+ meta: metaV2,
+ },
+ {
+ path: frontendURL('accounts/:accountId/captain/:assistantId/scenarios'),
+ component: AssistantScenariosIndex,
+ name: 'captain_assistants_scenarios_index',
+ meta: metaV2,
+ },
+ {
+ path: frontendURL('accounts/:accountId/captain/:assistantId/playground'),
+ component: AssistantPlaygroundIndex,
+ name: 'captain_assistants_playground_index',
+ meta,
+ },
+ {
+ path: frontendURL('accounts/:accountId/captain/:assistantId/inboxes'),
component: AssistantInboxesIndex,
name: 'captain_assistants_inboxes_index',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
+ meta,
},
+ {
+ path: frontendURL('accounts/:accountId/captain/:assistantId/faqs/pending'),
+ component: ResponsesPendingIndex,
+ name: 'captain_assistants_responses_pending',
+ meta,
+ },
+ {
+ path: frontendURL('accounts/:accountId/captain/:assistantId/settings'),
+ component: AssistantSettingsIndex,
+ name: 'captain_assistants_settings_index',
+ meta,
+ },
+ // Settings sub-pages (guardrails and guidelines)
{
path: frontendURL(
- 'accounts/:accountId/captain/assistants/:assistantId/guardrails'
+ 'accounts/:accountId/captain/:assistantId/settings/guardrails'
),
component: AssistantGuardrailsIndex,
name: 'captain_assistants_guardrails_index',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
+ meta: metaV2,
},
{
path: frontendURL(
- 'accounts/:accountId/captain/assistants/:assistantId/scenarios'
- ),
- component: AssistantScenariosIndex,
- name: 'captain_assistants_scenarios_index',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
- },
- {
- path: frontendURL(
- 'accounts/:accountId/captain/assistants/:assistantId/guidelines'
+ 'accounts/:accountId/captain/:assistantId/settings/guidelines'
),
component: AssistantGuidelinesIndex,
name: 'captain_assistants_guidelines_index',
+ meta: metaV2,
+ },
+ {
+ path: frontendURL('accounts/:accountId/captain/assistants'),
+ component: AssistantEmptyStateIndex,
+ name: 'captain_assistants_create_index',
meta: {
permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
installationTypes: [
INSTALLATION_TYPES.CLOUD,
INSTALLATION_TYPES.ENTERPRISE,
@@ -101,55 +108,26 @@ export const routes = [
},
},
{
- path: frontendURL('accounts/:accountId/captain/documents'),
- component: DocumentsIndex,
- name: 'captain_documents_index',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
- },
- {
- path: frontendURL('accounts/:accountId/captain/responses'),
- component: ResponsesIndex,
- name: 'captain_responses_index',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
- },
- {
- path: frontendURL('accounts/:accountId/captain/responses/pending'),
- component: ResponsesPendingIndex,
- name: 'captain_responses_pending',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
- },
- {
- path: frontendURL('accounts/:accountId/captain/tools'),
- component: CustomToolsIndex,
- name: 'captain_tools_index',
- meta: {
- permissions: ['administrator', 'agent'],
- featureFlag: FEATURE_FLAGS.CAPTAIN_V2,
- installationTypes: [
- INSTALLATION_TYPES.CLOUD,
- INSTALLATION_TYPES.ENTERPRISE,
- ],
- },
+ path: frontendURL('accounts/:accountId/captain/:navigationPath'),
+ component: AssistantsIndexPage,
+ name: 'captain_assistants_index',
+ meta,
+ },
+];
+
+export const routes = [
+ {
+ path: frontendURL('accounts/:accountId/captain'),
+ component: CaptainPageRouteView,
+ redirect: to => {
+ return {
+ name: 'captain_assistants_index',
+ params: {
+ navigationPath: 'captain_assistants_responses_index',
+ ...to.params,
+ },
+ };
+ },
+ children: [...assistantRoutes],
},
];
diff --git a/app/javascript/dashboard/routes/dashboard/captain/documents/Index.vue b/app/javascript/dashboard/routes/dashboard/captain/documents/Index.vue
index c90762abb..fe38d5ca1 100644
--- a/app/javascript/dashboard/routes/dashboard/captain/documents/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/captain/documents/Index.vue
@@ -1,6 +1,7 @@
@@ -114,6 +101,7 @@ onMounted(() => {
:show-pagination-footer="!isFetching && !!documents.length"
:is-fetching="isFetching"
:is-empty="!documents.length"
+ :show-know-more="false"
:feature-flag="FEATURE_FLAGS.CAPTAIN"
@update:current-page="onPageChange"
@click="handleCreateDocument"
@@ -138,15 +126,6 @@ onMounted(() => {
-
-
-
-
@@ -173,6 +152,7 @@ onMounted(() => {
+import { computed, nextTick, onMounted } from 'vue';
+import { useStore } from 'vuex';
+import { useRoute, useRouter } from 'vue-router';
+import { useUISettings } from 'dashboard/composables/useUISettings';
+
+import Spinner from 'dashboard/components-next/spinner/Spinner.vue';
+
+const store = useStore();
+const router = useRouter();
+const { uiSettings } = useUISettings();
+const route = useRoute();
+
+const assistants = computed(
+ () => store.getters['captainAssistants/getRecords']
+);
+
+const isAssistantPresent = assistantId => {
+ return !!assistants.value.find(a => a.id === Number(assistantId));
+};
+
+const routeToView = (name, params) => {
+ router.replace({ name, params, replace: true });
+};
+
+const generateRouterParams = () => {
+ const { last_active_assistant_id: lastActiveAssistantId } =
+ uiSettings.value || {};
+
+ if (isAssistantPresent(lastActiveAssistantId)) {
+ return {
+ assistantId: lastActiveAssistantId,
+ };
+ }
+
+ if (assistants.value.length > 0) {
+ const { id: assistantId } = assistants.value[0];
+ return { assistantId };
+ }
+
+ return null;
+};
+
+const routeToLastActiveAssistant = () => {
+ const params = generateRouterParams();
+
+ // No assistants found, redirect to create page
+ if (!params) {
+ return routeToView('captain_assistants_create_index', {
+ accountId: route.params.accountId,
+ });
+ }
+
+ const { navigationPath } = route.params;
+ const isAValidRoute = [
+ 'captain_assistants_responses_index', // Faq page
+ 'captain_assistants_documents_index', // Document page
+ 'captain_assistants_scenarios_index', // Scenario page
+ 'captain_assistants_playground_index', // Playground page
+ 'captain_assistants_inboxes_index', // Inboxes page
+ 'captain_tools_index', // Tools page
+ 'captain_assistants_settings_index', // Settings page
+ ].includes(navigationPath);
+
+ const navigateTo = isAValidRoute
+ ? navigationPath
+ : 'captain_assistants_responses_index';
+
+ return routeToView(navigateTo, {
+ accountId: route.params.accountId,
+ ...params,
+ });
+};
+
+const performRouting = async () => {
+ await store.dispatch('captainAssistants/get');
+ nextTick(() => routeToLastActiveAssistant());
+};
+
+onMounted(() => performRouting());
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/pages/CaptainPageRouteView.vue b/app/javascript/dashboard/routes/dashboard/captain/pages/CaptainPageRouteView.vue
new file mode 100644
index 000000000..f0edfb589
--- /dev/null
+++ b/app/javascript/dashboard/routes/dashboard/captain/pages/CaptainPageRouteView.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/responses/Index.vue b/app/javascript/dashboard/routes/dashboard/captain/responses/Index.vue
index 7a5d97f0b..7829e59a4 100644
--- a/app/javascript/dashboard/routes/dashboard/captain/responses/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/captain/responses/Index.vue
@@ -8,14 +8,12 @@ import { debounce } from '@chatwoot/utils';
import { useAccount } from 'dashboard/composables/useAccount';
import Banner from 'dashboard/components-next/banner/Banner.vue';
-import Button from 'dashboard/components-next/button/Button.vue';
-import Checkbox from 'dashboard/components-next/checkbox/Checkbox.vue';
import Input from 'dashboard/components-next/input/Input.vue';
+import BulkSelectBar from 'dashboard/components-next/captain/assistant/BulkSelectBar.vue';
import DeleteDialog from 'dashboard/components-next/captain/pageComponents/DeleteDialog.vue';
import BulkDeleteDialog from 'dashboard/components-next/captain/pageComponents/BulkDeleteDialog.vue';
import PageLayout from 'dashboard/components-next/captain/PageLayout.vue';
import CaptainPaywall from 'dashboard/components-next/captain/pageComponents/Paywall.vue';
-import AssistantSelector from 'dashboard/components-next/captain/pageComponents/AssistantSelector.vue';
import ResponseCard from 'dashboard/components-next/captain/assistant/ResponseCard.vue';
import CreateResponseDialog from 'dashboard/components-next/captain/pageComponents/response/CreateResponseDialog.vue';
import ResponsePageEmptyState from 'dashboard/components-next/captain/pageComponents/emptyStates/ResponsePageEmptyState.vue';
@@ -27,7 +25,6 @@ const route = useRoute();
const store = useStore();
const { isOnChatwootCloud } = useAccount();
const uiFlags = useMapGetter('captainResponses/getUIFlags');
-const assistants = useMapGetter('captainAssistants/getRecords');
const responseMeta = useMapGetter('captainResponses/getMeta');
const responses = useMapGetter('captainResponses/getRecords');
const isFetching = computed(() => uiFlags.value.fetchingList);
@@ -36,18 +33,13 @@ const selectedResponse = ref(null);
const deleteDialog = ref(null);
const bulkDeleteDialog = ref(null);
-const selectedAssistant = ref('all');
const dialogType = ref('');
const searchQuery = ref('');
const { t } = useI18n();
const createDialog = ref(null);
-const shouldShowDropdown = computed(() => {
- if (assistants.value.length === 0) return false;
-
- return !isFetching.value;
-});
+const selectedAssistantId = computed(() => Number(route.params.assistantId));
const pendingCount = useMapGetter('captainResponses/getPendingCount');
@@ -106,8 +98,8 @@ const updateURLWithFilters = (page, search) => {
const fetchResponses = (page = 1) => {
const filterParams = { page, status: 'approved' };
- if (selectedAssistant.value !== 'all') {
- filterParams.assistantId = selectedAssistant.value;
+ if (selectedAssistantId.value) {
+ filterParams.assistantId = selectedAssistantId.value;
}
if (searchQuery.value) {
filterParams.search = searchQuery.value;
@@ -123,33 +115,20 @@ const fetchResponses = (page = 1) => {
const bulkSelectedIds = ref(new Set());
const hoveredCard = ref(null);
-const bulkSelectionState = computed(() => {
- const selectedCount = bulkSelectedIds.value.size;
- const totalCount = responses.value?.length || 0;
-
- return {
- hasSelected: selectedCount > 0,
- isIndeterminate: selectedCount > 0 && selectedCount < totalCount,
- allSelected: totalCount > 0 && selectedCount === totalCount,
- };
-});
-
-const bulkCheckbox = computed({
- get: () => bulkSelectionState.value.allSelected,
- set: value => {
- bulkSelectedIds.value = value
- ? new Set(responses.value.map(r => r.id))
- : new Set();
- },
-});
-
const buildSelectedCountLabel = computed(() => {
const count = responses.value?.length || 0;
- return bulkSelectionState.value.allSelected
+ const isAllSelected = bulkSelectedIds.value.size === count && count > 0;
+ return isAllSelected
? t('CAPTAIN.RESPONSES.UNSELECT_ALL', { count })
: t('CAPTAIN.RESPONSES.SELECT_ALL', { count });
});
+const selectedCountLabel = computed(() => {
+ return t('CAPTAIN.RESPONSES.SELECTED', {
+ count: bulkSelectedIds.value.size,
+ });
+});
+
const handleCardHover = (isHovered, id) => {
hoveredCard.value = isHovered ? id : null;
};
@@ -179,14 +158,11 @@ const fetchResponseAfterBulkAction = () => {
};
const onPageChange = page => {
- // Store current selection state before fetching new page
- const wasAllPageSelected = bulkSelectionState.value.allSelected;
- const hadPartialSelection = bulkSelectedIds.value.size > 0;
+ const hadSelection = bulkSelectedIds.value.size > 0;
fetchResponses(page);
- // Reset selection if we had any selections on page change
- if (wasAllPageSelected || hadPartialSelection) {
+ if (hadSelection) {
bulkSelectedIds.value = new Set();
}
};
@@ -201,11 +177,6 @@ const onBulkDeleteSuccess = () => {
fetchResponseAfterBulkAction();
};
-const handleAssistantFilterChange = assistant => {
- selectedAssistant.value = assistant;
- fetchResponses(1);
-};
-
const debouncedSearch = debounce(async () => {
fetchResponses(1);
}, 500);
@@ -219,13 +190,12 @@ const initializeFromURL = () => {
};
const navigateToPendingFAQs = () => {
- router.push({ name: 'captain_responses_pending' });
+ router.push({ name: 'captain_assistants_responses_pending' });
};
onMounted(() => {
- store.dispatch('captainAssistants/get');
initializeFromURL();
- store.dispatch('captainResponses/fetchPendingCount');
+ store.dispatch('captainResponses/fetchPendingCount', selectedAssistantId);
});
@@ -255,82 +225,38 @@ onMounted(() => {
/>
-
+
-
-
-
-
-
-
-
-
- {{ buildSelectedCountLabel }}
-
-
-
- {{
- $t('CAPTAIN.RESPONSES.SELECTED', {
- count: bulkSelectedIds.size,
- })
- }}
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/responses/Pending.vue b/app/javascript/dashboard/routes/dashboard/captain/responses/Pending.vue
index 236bb7b23..f702387e6 100644
--- a/app/javascript/dashboard/routes/dashboard/captain/responses/Pending.vue
+++ b/app/javascript/dashboard/routes/dashboard/captain/responses/Pending.vue
@@ -7,16 +7,14 @@ import { useRouter, useRoute } from 'vue-router';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
import { debounce } from '@chatwoot/utils';
import { useAccount } from 'dashboard/composables/useAccount';
-import { frontendURL } from 'dashboard/helper/URLHelper';
import Button from 'dashboard/components-next/button/Button.vue';
-import Checkbox from 'dashboard/components-next/checkbox/Checkbox.vue';
import Input from 'dashboard/components-next/input/Input.vue';
+import BulkSelectBar from 'dashboard/components-next/captain/assistant/BulkSelectBar.vue';
import DeleteDialog from 'dashboard/components-next/captain/pageComponents/DeleteDialog.vue';
import BulkDeleteDialog from 'dashboard/components-next/captain/pageComponents/BulkDeleteDialog.vue';
import PageLayout from 'dashboard/components-next/captain/PageLayout.vue';
import CaptainPaywall from 'dashboard/components-next/captain/pageComponents/Paywall.vue';
-import AssistantSelector from 'dashboard/components-next/captain/pageComponents/AssistantSelector.vue';
import ResponseCard from 'dashboard/components-next/captain/assistant/ResponseCard.vue';
import CreateResponseDialog from 'dashboard/components-next/captain/pageComponents/response/CreateResponseDialog.vue';
import ResponsePageEmptyState from 'dashboard/components-next/captain/pageComponents/emptyStates/ResponsePageEmptyState.vue';
@@ -28,7 +26,6 @@ const route = useRoute();
const store = useStore();
const { isOnChatwootCloud } = useAccount();
const uiFlags = useMapGetter('captainResponses/getUIFlags');
-const assistants = useMapGetter('captainAssistants/getRecords');
const responseMeta = useMapGetter('captainResponses/getMeta');
const responses = useMapGetter('captainResponses/getRecords');
const isFetching = computed(() => uiFlags.value.fetchingList);
@@ -37,21 +34,20 @@ const selectedResponse = ref(null);
const deleteDialog = ref(null);
const bulkDeleteDialog = ref(null);
-const selectedAssistant = ref('all');
+const selectedAssistantId = Number(route.params.assistantId);
const dialogType = ref('');
const searchQuery = ref('');
const { t } = useI18n();
const createDialog = ref(null);
-const shouldShowDropdown = computed(() => {
- if (assistants.value.length === 0) return false;
- return !isFetching.value;
-});
-
-const backUrl = computed(() =>
- frontendURL(`accounts/${route.params.accountId}/captain/responses`)
-);
+const backUrl = computed(() => ({
+ name: 'captain_assistants_responses_index',
+ params: {
+ accountId: route.params.accountId,
+ assistantId: selectedAssistantId,
+ },
+}));
// Filter out approved responses in pending view
const filteredResponses = computed(() =>
@@ -78,11 +74,6 @@ const handleAccept = async () => {
}
};
-const handleCreate = () => {
- dialogType.value = 'create';
- nextTick(() => createDialog.value.dialogRef.open());
-};
-
const handleEdit = () => {
dialogType.value = 'edit';
nextTick(() => createDialog.value.dialogRef.open());
@@ -134,8 +125,8 @@ const updateURLWithFilters = (page, search) => {
const fetchResponses = (page = 1) => {
const filterParams = { page, status: 'pending' };
- if (selectedAssistant.value !== 'all') {
- filterParams.assistantId = selectedAssistant.value;
+ if (selectedAssistantId) {
+ filterParams.assistantId = selectedAssistantId;
}
if (searchQuery.value) {
filterParams.search = searchQuery.value;
@@ -151,33 +142,20 @@ const fetchResponses = (page = 1) => {
const bulkSelectedIds = ref(new Set());
const hoveredCard = ref(null);
-const bulkSelectionState = computed(() => {
- const selectedCount = bulkSelectedIds.value.size;
- const totalCount = filteredResponses.value?.length || 0;
-
- return {
- hasSelected: selectedCount > 0,
- isIndeterminate: selectedCount > 0 && selectedCount < totalCount,
- allSelected: totalCount > 0 && selectedCount === totalCount,
- };
-});
-
-const bulkCheckbox = computed({
- get: () => bulkSelectionState.value.allSelected,
- set: value => {
- bulkSelectedIds.value = value
- ? new Set(filteredResponses.value.map(r => r.id))
- : new Set();
- },
-});
-
const buildSelectedCountLabel = computed(() => {
const count = filteredResponses.value?.length || 0;
- return bulkSelectionState.value.allSelected
+ const isAllSelected = bulkSelectedIds.value.size === count && count > 0;
+ return isAllSelected
? t('CAPTAIN.RESPONSES.UNSELECT_ALL', { count })
: t('CAPTAIN.RESPONSES.SELECT_ALL', { count });
});
+const selectedCountLabel = computed(() => {
+ return t('CAPTAIN.RESPONSES.SELECTED', {
+ count: bulkSelectedIds.value.size,
+ });
+});
+
const handleCardHover = (isHovered, id) => {
hoveredCard.value = isHovered ? id : null;
};
@@ -219,12 +197,11 @@ const handleBulkApprove = async () => {
};
const onPageChange = page => {
- const wasAllPageSelected = bulkSelectionState.value.allSelected;
- const hadPartialSelection = bulkSelectedIds.value.size > 0;
+ const hadSelection = bulkSelectedIds.value.size > 0;
fetchResponses(page);
- if (wasAllPageSelected || hadPartialSelection) {
+ if (hadSelection) {
bulkSelectedIds.value = new Set();
}
};
@@ -239,22 +216,16 @@ const onBulkDeleteSuccess = () => {
fetchResponseAfterBulkAction();
};
-const handleAssistantFilterChange = assistant => {
- selectedAssistant.value = assistant;
- fetchResponses(1);
-};
-
const debouncedSearch = debounce(async () => {
fetchResponses(1);
}, 500);
const hasActiveFilters = computed(() => {
- return Boolean(searchQuery.value || selectedAssistant.value !== 'all');
+ return Boolean(searchQuery.value);
});
const clearFilters = () => {
searchQuery.value = '';
- selectedAssistant.value = 'all';
fetchResponses(1);
};
@@ -267,7 +238,6 @@ const initializeFromURL = () => {
};
onMounted(() => {
- store.dispatch('captainAssistants/get');
initializeFromURL();
});
@@ -276,16 +246,14 @@ onMounted(() => {
{
/>
-
+
-
-
-
-
-
-
-
-
- {{ buildSelectedCountLabel }}
-
-
-
- {{
- $t('CAPTAIN.RESPONSES.SELECTED', {
- count: bulkSelectedIds.size,
- })
- }}
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/captain/tools/Index.vue b/app/javascript/dashboard/routes/dashboard/captain/tools/Index.vue
index 880bdbbf3..c350e76f3 100644
--- a/app/javascript/dashboard/routes/dashboard/captain/tools/Index.vue
+++ b/app/javascript/dashboard/routes/dashboard/captain/tools/Index.vue
@@ -87,6 +87,7 @@ onMounted(() => {
:is-fetching="isFetching"
:is-empty="!customTools.length"
:feature-flag="FEATURE_FLAGS.CAPTAIN_V2"
+ :show-know-more="false"
@update:current-page="onPageChange"
@click="openCreateDialog"
>
diff --git a/app/javascript/dashboard/store/captain/storeFactory.spec.js b/app/javascript/dashboard/store/captain/storeFactory.spec.js
index 0aec26e40..44637d429 100644
--- a/app/javascript/dashboard/store/captain/storeFactory.spec.js
+++ b/app/javascript/dashboard/store/captain/storeFactory.spec.js
@@ -175,7 +175,7 @@ describe('storeFactory', () => {
expect(commit).toHaveBeenCalledWith(mutationTypes.SET_UI_FLAG, {
fetchingItem: true,
});
- expect(commit).toHaveBeenCalledWith(mutationTypes.ADD, data);
+ expect(commit).toHaveBeenCalledWith(mutationTypes.UPSERT, data);
expect(commit).toHaveBeenCalledWith(mutationTypes.SET_UI_FLAG, {
fetchingItem: false,
});
diff --git a/app/javascript/dashboard/store/captain/storeFactoryHelper.js b/app/javascript/dashboard/store/captain/storeFactoryHelper.js
index 7a04d2e81..ddb7367d7 100644
--- a/app/javascript/dashboard/store/captain/storeFactoryHelper.js
+++ b/app/javascript/dashboard/store/captain/storeFactoryHelper.js
@@ -22,7 +22,7 @@ export const showRecord =
commit(mutationTypes.SET_UI_FLAG, { fetchingItem: true });
try {
const response = await API.show(id);
- commit(mutationTypes.ADD, response.data);
+ commit(mutationTypes.UPSERT, response.data);
return response.data;
} catch (error) {
return throwErrorMessage(error);