HH-555: remove advanced assignment commercial gate (#138)
* fix(HH-555): remove advanced assignment paywall * fix(HH-555): gate assignment entries with assignment v2 --------- Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
@@ -54,10 +54,10 @@ const isFeatureEnabledonAccount = useMapGetter(
|
|||||||
'accounts/isFeatureEnabledonAccount'
|
'accounts/isFeatureEnabledonAccount'
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasAdvancedAssignment = computed(() => {
|
const hasAssignmentV2 = computed(() => {
|
||||||
return isFeatureEnabledonAccount.value(
|
return isFeatureEnabledonAccount.value(
|
||||||
accountId.value,
|
accountId.value,
|
||||||
FEATURE_FLAGS.ADVANCED_ASSIGNMENT
|
FEATURE_FLAGS.ASSIGNMENT_V2
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -690,7 +690,7 @@ const menuItems = computed(() => {
|
|||||||
],
|
],
|
||||||
to: accountScopedRoute('settings_teams_list'),
|
to: accountScopedRoute('settings_teams_list'),
|
||||||
},
|
},
|
||||||
...(hasAdvancedAssignment.value
|
...(hasAssignmentV2.value
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
name: 'Settings Agent Assignment',
|
name: 'Settings Agent Assignment',
|
||||||
|
|||||||
@@ -869,8 +869,6 @@
|
|||||||
"ROUND_ROBIN": "Round robin",
|
"ROUND_ROBIN": "Round robin",
|
||||||
"BALANCED": "Balanced assignment"
|
"BALANCED": "Balanced assignment"
|
||||||
},
|
},
|
||||||
"UPGRADE_PROMPT": "Custom assignment policies are available on the Business plan",
|
|
||||||
"UPGRADE_TO_BUSINESS": "Upgrade to Business",
|
|
||||||
"DEFAULT_POLICY_LINKED": "Default policy linked",
|
"DEFAULT_POLICY_LINKED": "Default policy linked",
|
||||||
"DEFAULT_POLICY_DESCRIPTION": "Link a custom assignment policy to customize how conversations are assigned to agents in this inbox.",
|
"DEFAULT_POLICY_DESCRIPTION": "Link a custom assignment policy to customize how conversations are assigned to agents in this inbox.",
|
||||||
"LINK_EXISTING_POLICY": "Link existing policy",
|
"LINK_EXISTING_POLICY": "Link existing policy",
|
||||||
|
|||||||
@@ -764,9 +764,7 @@
|
|||||||
},
|
},
|
||||||
"BALANCED": {
|
"BALANCED": {
|
||||||
"LABEL": "Balanced",
|
"LABEL": "Balanced",
|
||||||
"DESCRIPTION": "Assign conversations based on available capacity.",
|
"DESCRIPTION": "Assign conversations based on available capacity."
|
||||||
"PREMIUM_MESSAGE": "Upgrade to access balanced assignment and agent capacity management.",
|
|
||||||
"PREMIUM_BADGE": "Premium"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ASSIGNMENT_PRIORITY": {
|
"ASSIGNMENT_PRIORITY": {
|
||||||
|
|||||||
@@ -869,8 +869,6 @@
|
|||||||
"ROUND_ROBIN": "轮询分配",
|
"ROUND_ROBIN": "轮询分配",
|
||||||
"BALANCED": "均衡分配"
|
"BALANCED": "均衡分配"
|
||||||
},
|
},
|
||||||
"UPGRADE_PROMPT": "自定义分配策略适用于商业版套餐",
|
|
||||||
"UPGRADE_TO_BUSINESS": "升级到商业版",
|
|
||||||
"DEFAULT_POLICY_LINKED": "已关联默认策略",
|
"DEFAULT_POLICY_LINKED": "已关联默认策略",
|
||||||
"DEFAULT_POLICY_DESCRIPTION": "关联自定义分配策略,以配置此收件箱如何将对话分配给客服。",
|
"DEFAULT_POLICY_DESCRIPTION": "关联自定义分配策略,以配置此收件箱如何将对话分配给客服。",
|
||||||
"LINK_EXISTING_POLICY": "关联现有策略",
|
"LINK_EXISTING_POLICY": "关联现有策略",
|
||||||
|
|||||||
@@ -764,9 +764,7 @@
|
|||||||
},
|
},
|
||||||
"BALANCED": {
|
"BALANCED": {
|
||||||
"LABEL": "均衡分配",
|
"LABEL": "均衡分配",
|
||||||
"DESCRIPTION": "根据可用容量分配会话。",
|
"DESCRIPTION": "根据可用容量分配会话。"
|
||||||
"PREMIUM_MESSAGE": "升级以使用均衡分配和客服容量管理。",
|
|
||||||
"PREMIUM_BADGE": "高级"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ASSIGNMENT_PRIORITY": {
|
"ASSIGNMENT_PRIORITY": {
|
||||||
|
|||||||
+1
-7
@@ -39,18 +39,12 @@ const agentAssignments = computed(() => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Only show Agent Capacity if BOTH assignment_v2 AND advanced_assignment are enabled
|
|
||||||
// advanced_assignment identifies premium users
|
|
||||||
const hasAssignmentV2 = isFeatureEnabledonAccount.value(
|
const hasAssignmentV2 = isFeatureEnabledonAccount.value(
|
||||||
accountId.value,
|
accountId.value,
|
||||||
'assignment_v2'
|
'assignment_v2'
|
||||||
);
|
);
|
||||||
const hasAdvancedAssignment = isFeatureEnabledonAccount.value(
|
|
||||||
accountId.value,
|
|
||||||
'advanced_assignment'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hasAssignmentV2 && hasAdvancedAssignment) {
|
if (hasAssignmentV2) {
|
||||||
assignments.push({
|
assignments.push({
|
||||||
key: 'agent_capacity_policy_index',
|
key: 'agent_capacity_policy_index',
|
||||||
title: t('ASSIGNMENT_POLICY.INDEX.AGENT_CAPACITY_POLICY.TITLE'),
|
title: t('ASSIGNMENT_POLICY.INDEX.AGENT_CAPACITY_POLICY.TITLE'),
|
||||||
|
|||||||
+206
-18
@@ -1,23 +1,211 @@
|
|||||||
import { readFileSync } from 'node:fs';
|
import { flushPromises, shallowMount } from '@vue/test-utils';
|
||||||
|
import { createMemoryHistory, createRouter } from 'vue-router';
|
||||||
|
import AgentAssignmentPolicyForm from './pages/components/AgentAssignmentPolicyForm.vue';
|
||||||
|
import AssignmentPolicyIndex from './Index.vue';
|
||||||
|
import assignmentPolicyRoutes from './assignmentPolicy.routes';
|
||||||
|
import CollaboratorsPage from '../inbox/settingsPage/CollaboratorsPage.vue';
|
||||||
|
import RadioCard from 'dashboard/components-next/radioCard/RadioCard.vue';
|
||||||
|
import AssignmentCard from 'dashboard/components-next/AssignmentPolicy/AssignmentCard/AssignmentCard.vue';
|
||||||
|
import Sidebar from 'dashboard/components-next/sidebar/Sidebar.vue';
|
||||||
|
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
||||||
|
|
||||||
describe('advanced assignment paywalls', () => {
|
const SidebarGroupStub = {
|
||||||
it.each([
|
name: 'SidebarGroup',
|
||||||
[
|
inheritAttrs: false,
|
||||||
'../inbox/settingsPage/CollaboratorsPage.vue',
|
props: ['name', 'children'],
|
||||||
'v-if="showAdvancedAssignmentPaywall"',
|
template: '<div />',
|
||||||
],
|
};
|
||||||
[
|
|
||||||
'./pages/components/AgentAssignmentPolicyForm.vue',
|
const mocked = vi.hoisted(() => ({
|
||||||
'disabled && showAdvancedAssignmentPaywall.value',
|
features: ['assignment_v2'],
|
||||||
],
|
dispatch: vi.fn(),
|
||||||
])('uses the deployment-aware paywall policy in %s', (path, condition) => {
|
getInboxPolicy: vi.fn(),
|
||||||
const source = readFileSync(
|
getPolicies: vi.fn(),
|
||||||
`app/javascript/dashboard/routes/dashboard/settings/assignmentPolicy/${path}`,
|
push: vi.fn(),
|
||||||
'utf8'
|
}));
|
||||||
|
|
||||||
|
const isFeatureEnabled = (_accountId, feature) =>
|
||||||
|
mocked.features.includes(feature);
|
||||||
|
const store = {
|
||||||
|
dispatch: (...args) => mocked.dispatch(...args),
|
||||||
|
getters: {
|
||||||
|
'agents/getAgents': [],
|
||||||
|
'accounts/isFeatureEnabledonAccount': isFeatureEnabled,
|
||||||
|
getUISettings: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
vi.mock('vue-router', async () => ({
|
||||||
|
...(await vi.importActual('vue-router')),
|
||||||
|
useRoute: () => ({ params: { accountId: '1' } }),
|
||||||
|
useRouter: () => ({ push: mocked.push }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('vuex', async () => ({
|
||||||
|
...(await vi.importActual('vuex')),
|
||||||
|
useStore: () => store,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('dashboard/composables/useUISettings', async () => {
|
||||||
|
const { ref } = await vi.importActual('vue');
|
||||||
|
return {
|
||||||
|
useUISettings: () => ({
|
||||||
|
uiSettings: ref({ sidebar_width: 200 }),
|
||||||
|
updateUISettings: vi.fn(),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('dashboard/composables/store', async () => {
|
||||||
|
const { computed } = await vi.importActual('vue');
|
||||||
|
const emptyListGetters = new Set([
|
||||||
|
'inboxes/getInboxes',
|
||||||
|
'labels/getLabelsOnSidebar',
|
||||||
|
'teams/getMyTeams',
|
||||||
|
'customViews/getContactCustomViews',
|
||||||
|
'customViews/getConversationCustomViews',
|
||||||
|
]);
|
||||||
|
const unreadCountGetters = new Set([
|
||||||
|
'conversationUnreadCounts/getInboxUnreadCount',
|
||||||
|
'conversationUnreadCounts/getLabelUnreadCount',
|
||||||
|
'conversationUnreadCounts/getTeamUnreadCount',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...(await vi.importActual('dashboard/composables/store')),
|
||||||
|
useMapGetter: key =>
|
||||||
|
computed(() => {
|
||||||
|
if (key === 'accounts/isFeatureEnabledonAccount') {
|
||||||
|
return isFeatureEnabled;
|
||||||
|
}
|
||||||
|
if (key === 'accounts/getAccount') return () => ({ id: 1 });
|
||||||
|
if (key === 'getCurrentAccountId') return 1;
|
||||||
|
if (emptyListGetters.has(key)) return [];
|
||||||
|
if (unreadCountGetters.has(key)) return () => 0;
|
||||||
|
return false;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('dashboard/api/assignmentPolicies', () => ({
|
||||||
|
default: {
|
||||||
|
getInboxPolicy: (...args) => mocked.getInboxPolicy(...args),
|
||||||
|
get: (...args) => mocked.getPolicies(...args),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('self-hosted advanced assignment', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mocked.features = ['assignment_v2'];
|
||||||
|
mocked.dispatch.mockResolvedValue({ data: { payload: [] } });
|
||||||
|
mocked.getInboxPolicy.mockResolvedValue({ data: null });
|
||||||
|
mocked.getPolicies.mockResolvedValue({ data: [] });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps balanced assignment available without a premium label', () => {
|
||||||
|
const wrapper = shallowMount(AgentAssignmentPolicyForm, {
|
||||||
|
props: { mode: 'CREATE' },
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
WithLabel: { template: '<div><slot /></div>' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const balancedOption = wrapper
|
||||||
|
.findAllComponents(RadioCard)
|
||||||
|
.find(option => option.props('id') === 'balanced');
|
||||||
|
|
||||||
|
expect(balancedOption.props()).toMatchObject({
|
||||||
|
disabled: false,
|
||||||
|
disabledLabel: '',
|
||||||
|
disabledMessage: '',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows agent capacity when assignment v2 is enabled', () => {
|
||||||
|
const wrapper = shallowMount(AssignmentPolicyIndex, {
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
SettingsLayout: {
|
||||||
|
template: '<main><slot name="header" /><slot name="body" /></main>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const cards = wrapper.findAllComponents(AssignmentCard);
|
||||||
|
|
||||||
|
expect(cards).toHaveLength(2);
|
||||||
|
expect(cards.map(card => card.props('title'))).toContain(
|
||||||
|
'Agent capacity policy'
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
expect(source).toContain('shouldShowPaywall');
|
it('shows the Agent Assignment sidebar entry without the legacy flag', () => {
|
||||||
expect(source).toContain('showAdvancedAssignmentPaywall');
|
const wrapper = shallowMount(Sidebar, {
|
||||||
expect(source).toContain(condition);
|
global: {
|
||||||
|
mocks: { $store: store },
|
||||||
|
stubs: { RouterLink: true, SidebarGroup: SidebarGroupStub },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const settings = wrapper
|
||||||
|
.findAllComponents(SidebarGroupStub)
|
||||||
|
.find(group => group.props('name') === 'Settings');
|
||||||
|
|
||||||
|
expect(settings.props('children')).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({ name: 'Settings Agent Assignment' }),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
'agent_capacity_policy_index',
|
||||||
|
'agent_capacity_policy_create',
|
||||||
|
'agent_capacity_policy_edit',
|
||||||
|
])('allows the %s route with assignment v2', async routeName => {
|
||||||
|
const router = createRouter({
|
||||||
|
history: createMemoryHistory(),
|
||||||
|
routes: assignmentPolicyRoutes.routes,
|
||||||
|
});
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
accountId: 1,
|
||||||
|
...(routeName === 'agent_capacity_policy_edit' ? { id: 1 } : {}),
|
||||||
|
};
|
||||||
|
await router.push({ name: routeName, params });
|
||||||
|
|
||||||
|
expect(router.currentRoute.value).toMatchObject({
|
||||||
|
name: routeName,
|
||||||
|
meta: { featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2 },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows policy controls instead of a Business plan upgrade', async () => {
|
||||||
|
const wrapper = shallowMount(CollaboratorsPage, {
|
||||||
|
props: {
|
||||||
|
inbox: {
|
||||||
|
id: 1,
|
||||||
|
enable_auto_assignment: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
SettingsAccordion: { template: '<section><slot /></section>' },
|
||||||
|
SettingsToggleSection: {
|
||||||
|
template: '<section><slot name="editor" /></section>',
|
||||||
|
},
|
||||||
|
NextButton: {
|
||||||
|
props: ['label'],
|
||||||
|
template: '<button>{{ label }}<slot /></button>',
|
||||||
|
},
|
||||||
|
WootInput: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(wrapper.text()).toContain('Create new policy');
|
||||||
|
expect(wrapper.text()).not.toContain('Upgrade to Business');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-3
@@ -62,7 +62,7 @@ export default {
|
|||||||
name: 'agent_capacity_policy_index',
|
name: 'agent_capacity_policy_index',
|
||||||
component: AgentCapacityIndex,
|
component: AgentCapacityIndex,
|
||||||
meta: {
|
meta: {
|
||||||
featureFlag: FEATURE_FLAGS.ADVANCED_ASSIGNMENT,
|
featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2,
|
||||||
permissions: ['administrator'],
|
permissions: ['administrator'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -71,7 +71,7 @@ export default {
|
|||||||
name: 'agent_capacity_policy_create',
|
name: 'agent_capacity_policy_create',
|
||||||
component: AgentCapacityCreate,
|
component: AgentCapacityCreate,
|
||||||
meta: {
|
meta: {
|
||||||
featureFlag: FEATURE_FLAGS.ADVANCED_ASSIGNMENT,
|
featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2,
|
||||||
permissions: ['administrator'],
|
permissions: ['administrator'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -80,7 +80,7 @@ export default {
|
|||||||
name: 'agent_capacity_policy_edit',
|
name: 'agent_capacity_policy_edit',
|
||||||
component: AgentCapacityEdit,
|
component: AgentCapacityEdit,
|
||||||
meta: {
|
meta: {
|
||||||
featureFlag: FEATURE_FLAGS.ADVANCED_ASSIGNMENT,
|
featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2,
|
||||||
permissions: ['administrator'],
|
permissions: ['administrator'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
+5
-42
@@ -1,10 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, reactive, ref, watch } from 'vue';
|
import { computed, reactive, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import { useMapGetter } from 'dashboard/composables/store';
|
|
||||||
import { usePolicy } from 'dashboard/composables/usePolicy';
|
|
||||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
|
||||||
import BaseInfo from 'dashboard/components-next/AssignmentPolicy/components/BaseInfo.vue';
|
import BaseInfo from 'dashboard/components-next/AssignmentPolicy/components/BaseInfo.vue';
|
||||||
import RadioCard from 'dashboard/components-next/radioCard/RadioCard.vue';
|
import RadioCard from 'dashboard/components-next/radioCard/RadioCard.vue';
|
||||||
import FairDistribution from 'dashboard/components-next/AssignmentPolicy/components/FairDistribution.vue';
|
import FairDistribution from 'dashboard/components-next/AssignmentPolicy/components/FairDistribution.vue';
|
||||||
@@ -68,18 +64,8 @@ const emit = defineEmits([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
|
||||||
const { shouldShowPaywall } = usePolicy();
|
|
||||||
|
|
||||||
const accountId = computed(() => Number(route.params.accountId));
|
|
||||||
const isFeatureEnabledonAccount = useMapGetter(
|
|
||||||
'accounts/isFeatureEnabledonAccount'
|
|
||||||
);
|
|
||||||
|
|
||||||
const BASE_KEY = 'ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY';
|
const BASE_KEY = 'ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY';
|
||||||
const showAdvancedAssignmentPaywall = computed(() =>
|
|
||||||
shouldShowPaywall(FEATURE_FLAGS.ADVANCED_ASSIGNMENT)
|
|
||||||
);
|
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
name: '',
|
name: '',
|
||||||
@@ -112,34 +98,11 @@ const createOption = (
|
|||||||
disabledLabel,
|
disabledLabel,
|
||||||
});
|
});
|
||||||
|
|
||||||
const assignmentOrderOptions = computed(() => {
|
const assignmentOrderOptions = computed(() =>
|
||||||
const hasAdvancedAssignment = isFeatureEnabledonAccount.value(
|
OPTIONS.ORDER.map(key =>
|
||||||
accountId.value,
|
createOption('ASSIGNMENT_ORDER', key, 'assignmentOrder')
|
||||||
'advanced_assignment'
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return OPTIONS.ORDER.map(key => {
|
|
||||||
const isBalanced = key === 'balanced';
|
|
||||||
const disabled = isBalanced && !hasAdvancedAssignment;
|
|
||||||
const disabledMessage =
|
|
||||||
disabled && showAdvancedAssignmentPaywall.value
|
|
||||||
? t(`${BASE_KEY}.FORM.ASSIGNMENT_ORDER.BALANCED.PREMIUM_MESSAGE`)
|
|
||||||
: '';
|
|
||||||
const disabledLabel =
|
|
||||||
disabled && showAdvancedAssignmentPaywall.value
|
|
||||||
? t(`${BASE_KEY}.FORM.ASSIGNMENT_ORDER.BALANCED.PREMIUM_BADGE`)
|
|
||||||
: '';
|
|
||||||
|
|
||||||
return createOption(
|
|
||||||
'ASSIGNMENT_ORDER',
|
|
||||||
key,
|
|
||||||
'assignmentOrder',
|
|
||||||
disabled,
|
|
||||||
disabledMessage,
|
|
||||||
disabledLabel
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const assignmentPriorityOptions = computed(() =>
|
const assignmentPriorityOptions = computed(() =>
|
||||||
OPTIONS.PRIORITY.map(key =>
|
OPTIONS.PRIORITY.map(key =>
|
||||||
|
|||||||
+3
-88
@@ -14,8 +14,6 @@ import DropdownMenu from 'dashboard/components-next/dropdown-menu/DropdownMenu.v
|
|||||||
import Icon from 'dashboard/components-next/icon/Icon.vue';
|
import Icon from 'dashboard/components-next/icon/Icon.vue';
|
||||||
import TagInput from 'dashboard/components-next/taginput/TagInput.vue';
|
import TagInput from 'dashboard/components-next/taginput/TagInput.vue';
|
||||||
import assignmentPoliciesAPI from 'dashboard/api/assignmentPolicies';
|
import assignmentPoliciesAPI from 'dashboard/api/assignmentPolicies';
|
||||||
import { usePolicy } from 'dashboard/composables/usePolicy';
|
|
||||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -29,7 +27,6 @@ const store = useStore();
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { shouldShowPaywall } = usePolicy();
|
|
||||||
|
|
||||||
const selectedAgentIds = ref([]);
|
const selectedAgentIds = ref([]);
|
||||||
const isAgentListUpdating = ref(false);
|
const isAgentListUpdating = ref(false);
|
||||||
@@ -81,22 +78,10 @@ const isFeatureEnabled = feature => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasAdvancedAssignment = computed(() => {
|
|
||||||
return isFeatureEnabled('advanced_assignment');
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasAssignmentV2 = computed(() => {
|
const hasAssignmentV2 = computed(() => {
|
||||||
return isFeatureEnabled('assignment_v2');
|
return isFeatureEnabled('assignment_v2');
|
||||||
});
|
});
|
||||||
|
|
||||||
const showAdvancedAssignmentUI = computed(() => {
|
|
||||||
return hasAdvancedAssignment.value && hasAssignmentV2.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
const showAdvancedAssignmentPaywall = computed(() =>
|
|
||||||
shouldShowPaywall(FEATURE_FLAGS.ADVANCED_ASSIGNMENT)
|
|
||||||
);
|
|
||||||
|
|
||||||
const assignmentOrderLabel = computed(() => {
|
const assignmentOrderLabel = computed(() => {
|
||||||
if (!assignmentPolicy.value) return '';
|
if (!assignmentPolicy.value) return '';
|
||||||
const priority = assignmentPolicy.value.conversation_priority;
|
const priority = assignmentPolicy.value.conversation_priority;
|
||||||
@@ -315,14 +300,6 @@ const navigateToAssignmentPolicyEdit = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateToBilling = () => {
|
|
||||||
const accountId = route.params.accountId;
|
|
||||||
router.push({
|
|
||||||
name: 'billing_settings_index',
|
|
||||||
params: { accountId },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const confirmDeletePolicy = () => {
|
const confirmDeletePolicy = () => {
|
||||||
showDeleteConfirmModal.value = true;
|
showDeleteConfirmModal.value = true;
|
||||||
};
|
};
|
||||||
@@ -351,7 +328,7 @@ const setDefaults = () => {
|
|||||||
maxAssignmentLimit.value =
|
maxAssignmentLimit.value =
|
||||||
props.inbox.auto_assignment_config?.max_assignment_limit || null;
|
props.inbox.auto_assignment_config?.max_assignment_limit || null;
|
||||||
fetchAttachedAgents();
|
fetchAttachedAgents();
|
||||||
if (showAdvancedAssignmentUI.value) {
|
if (hasAssignmentV2.value) {
|
||||||
fetchAssignmentPolicy();
|
fetchAssignmentPolicy();
|
||||||
fetchAvailablePolicies();
|
fetchAvailablePolicies();
|
||||||
}
|
}
|
||||||
@@ -416,7 +393,7 @@ onMounted(() => {
|
|||||||
<template v-if="hasAssignmentV2">
|
<template v-if="hasAssignmentV2">
|
||||||
<!-- Policy Card - When policy is attached -->
|
<!-- Policy Card - When policy is attached -->
|
||||||
<div
|
<div
|
||||||
v-if="showAdvancedAssignmentUI && assignmentPolicy"
|
v-if="assignmentPolicy"
|
||||||
class="ltr:pr-0 rtl:pl-0 ltr:pl-4 rtl:pr-4 py-4"
|
class="ltr:pr-0 rtl:pl-0 ltr:pl-4 rtl:pr-4 py-4"
|
||||||
>
|
>
|
||||||
<div class="flex items-start gap-4">
|
<div class="flex items-start gap-4">
|
||||||
@@ -480,13 +457,7 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Default Policy - When no custom policy attached but feature enabled -->
|
<!-- Default Policy - When no custom policy attached but feature enabled -->
|
||||||
<div
|
<div v-else-if="!assignmentPolicy && !isLoadingPolicy">
|
||||||
v-else-if="
|
|
||||||
showAdvancedAssignmentUI &&
|
|
||||||
!assignmentPolicy &&
|
|
||||||
!isLoadingPolicy
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<!-- Default Policy Header -->
|
<!-- Default Policy Header -->
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<div class="flex items-start gap-4">
|
<div class="flex items-start gap-4">
|
||||||
@@ -579,62 +550,6 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Default Rules Card - Feature not enabled (no advanced_assignment) -->
|
|
||||||
<div
|
|
||||||
v-else-if="!showAdvancedAssignmentUI"
|
|
||||||
class="ltr:pr-0 rtl:pl-0 ltr:pl-4 rtl:pr-4 py-4"
|
|
||||||
>
|
|
||||||
<div class="flex items-start gap-4">
|
|
||||||
<div
|
|
||||||
class="flex-shrink-0 size-10 rounded-xl bg-n-slate-3 dark:bg-n-slate-4 flex items-center justify-center"
|
|
||||||
>
|
|
||||||
<Icon icon="i-lucide-zap" class="text-xl text-n-slate-11" />
|
|
||||||
</div>
|
|
||||||
<div class="flex-grow">
|
|
||||||
<h4 class="text-heading-3 text-n-slate-12 mb-0.5">
|
|
||||||
{{ $t('INBOX_MGMT.ASSIGNMENT.DEFAULT_RULES_TITLE') }}
|
|
||||||
</h4>
|
|
||||||
<p class="text-body-main text-n-slate-11 mb-4">
|
|
||||||
{{ $t('INBOX_MGMT.ASSIGNMENT.DEFAULT_RULES_DESCRIPTION') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul class="space-y-2 mb-6">
|
|
||||||
<li class="flex items-center gap-2">
|
|
||||||
<span
|
|
||||||
class="w-1.5 h-1.5 rounded-full bg-n-slate-11 flex-shrink-0"
|
|
||||||
/>
|
|
||||||
<span class="text-body-main text-n-slate-12">
|
|
||||||
{{ $t('INBOX_MGMT.ASSIGNMENT.DEFAULT_RULE_1') }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li class="flex items-center gap-2">
|
|
||||||
<span
|
|
||||||
class="w-1.5 h-1.5 rounded-full bg-n-slate-11 flex-shrink-0"
|
|
||||||
/>
|
|
||||||
<span class="text-body-main text-n-slate-12">
|
|
||||||
{{ $t('INBOX_MGMT.ASSIGNMENT.DEFAULT_RULE_2') }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div class="w-full h-px bg-n-weak my-4" />
|
|
||||||
|
|
||||||
<div v-if="showAdvancedAssignmentPaywall">
|
|
||||||
<p class="text-body-main text-n-slate-11 mb-1">
|
|
||||||
{{ $t('INBOX_MGMT.ASSIGNMENT.UPGRADE_PROMPT') }}
|
|
||||||
</p>
|
|
||||||
<NextButton
|
|
||||||
:label="$t('INBOX_MGMT.ASSIGNMENT.UPGRADE_TO_BUSINESS')"
|
|
||||||
icon="i-lucide-arrow-right"
|
|
||||||
trailing-icon
|
|
||||||
link
|
|
||||||
@click="navigateToBilling"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Old UI for non-assignment_v2 -->
|
<!-- Old UI for non-assignment_v2 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user