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'
|
||||
);
|
||||
|
||||
const hasAdvancedAssignment = computed(() => {
|
||||
const hasAssignmentV2 = computed(() => {
|
||||
return isFeatureEnabledonAccount.value(
|
||||
accountId.value,
|
||||
FEATURE_FLAGS.ADVANCED_ASSIGNMENT
|
||||
FEATURE_FLAGS.ASSIGNMENT_V2
|
||||
);
|
||||
});
|
||||
|
||||
@@ -690,7 +690,7 @@ const menuItems = computed(() => {
|
||||
],
|
||||
to: accountScopedRoute('settings_teams_list'),
|
||||
},
|
||||
...(hasAdvancedAssignment.value
|
||||
...(hasAssignmentV2.value
|
||||
? [
|
||||
{
|
||||
name: 'Settings Agent Assignment',
|
||||
|
||||
@@ -869,8 +869,6 @@
|
||||
"ROUND_ROBIN": "Round robin",
|
||||
"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_DESCRIPTION": "Link a custom assignment policy to customize how conversations are assigned to agents in this inbox.",
|
||||
"LINK_EXISTING_POLICY": "Link existing policy",
|
||||
|
||||
@@ -764,9 +764,7 @@
|
||||
},
|
||||
"BALANCED": {
|
||||
"LABEL": "Balanced",
|
||||
"DESCRIPTION": "Assign conversations based on available capacity.",
|
||||
"PREMIUM_MESSAGE": "Upgrade to access balanced assignment and agent capacity management.",
|
||||
"PREMIUM_BADGE": "Premium"
|
||||
"DESCRIPTION": "Assign conversations based on available capacity."
|
||||
}
|
||||
},
|
||||
"ASSIGNMENT_PRIORITY": {
|
||||
|
||||
@@ -869,8 +869,6 @@
|
||||
"ROUND_ROBIN": "轮询分配",
|
||||
"BALANCED": "均衡分配"
|
||||
},
|
||||
"UPGRADE_PROMPT": "自定义分配策略适用于商业版套餐",
|
||||
"UPGRADE_TO_BUSINESS": "升级到商业版",
|
||||
"DEFAULT_POLICY_LINKED": "已关联默认策略",
|
||||
"DEFAULT_POLICY_DESCRIPTION": "关联自定义分配策略,以配置此收件箱如何将对话分配给客服。",
|
||||
"LINK_EXISTING_POLICY": "关联现有策略",
|
||||
|
||||
@@ -764,9 +764,7 @@
|
||||
},
|
||||
"BALANCED": {
|
||||
"LABEL": "均衡分配",
|
||||
"DESCRIPTION": "根据可用容量分配会话。",
|
||||
"PREMIUM_MESSAGE": "升级以使用均衡分配和客服容量管理。",
|
||||
"PREMIUM_BADGE": "高级"
|
||||
"DESCRIPTION": "根据可用容量分配会话。"
|
||||
}
|
||||
},
|
||||
"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(
|
||||
accountId.value,
|
||||
'assignment_v2'
|
||||
);
|
||||
const hasAdvancedAssignment = isFeatureEnabledonAccount.value(
|
||||
accountId.value,
|
||||
'advanced_assignment'
|
||||
);
|
||||
|
||||
if (hasAssignmentV2 && hasAdvancedAssignment) {
|
||||
if (hasAssignmentV2) {
|
||||
assignments.push({
|
||||
key: 'agent_capacity_policy_index',
|
||||
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', () => {
|
||||
it.each([
|
||||
[
|
||||
'../inbox/settingsPage/CollaboratorsPage.vue',
|
||||
'v-if="showAdvancedAssignmentPaywall"',
|
||||
],
|
||||
[
|
||||
'./pages/components/AgentAssignmentPolicyForm.vue',
|
||||
'disabled && showAdvancedAssignmentPaywall.value',
|
||||
],
|
||||
])('uses the deployment-aware paywall policy in %s', (path, condition) => {
|
||||
const source = readFileSync(
|
||||
`app/javascript/dashboard/routes/dashboard/settings/assignmentPolicy/${path}`,
|
||||
'utf8'
|
||||
const SidebarGroupStub = {
|
||||
name: 'SidebarGroup',
|
||||
inheritAttrs: false,
|
||||
props: ['name', 'children'],
|
||||
template: '<div />',
|
||||
};
|
||||
|
||||
const mocked = vi.hoisted(() => ({
|
||||
features: ['assignment_v2'],
|
||||
dispatch: vi.fn(),
|
||||
getInboxPolicy: vi.fn(),
|
||||
getPolicies: vi.fn(),
|
||||
push: vi.fn(),
|
||||
}));
|
||||
|
||||
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');
|
||||
expect(source).toContain('showAdvancedAssignmentPaywall');
|
||||
expect(source).toContain(condition);
|
||||
it('shows the Agent Assignment sidebar entry without the legacy flag', () => {
|
||||
const wrapper = shallowMount(Sidebar, {
|
||||
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',
|
||||
component: AgentCapacityIndex,
|
||||
meta: {
|
||||
featureFlag: FEATURE_FLAGS.ADVANCED_ASSIGNMENT,
|
||||
featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2,
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
},
|
||||
@@ -71,7 +71,7 @@ export default {
|
||||
name: 'agent_capacity_policy_create',
|
||||
component: AgentCapacityCreate,
|
||||
meta: {
|
||||
featureFlag: FEATURE_FLAGS.ADVANCED_ASSIGNMENT,
|
||||
featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2,
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
},
|
||||
@@ -80,7 +80,7 @@ export default {
|
||||
name: 'agent_capacity_policy_edit',
|
||||
component: AgentCapacityEdit,
|
||||
meta: {
|
||||
featureFlag: FEATURE_FLAGS.ADVANCED_ASSIGNMENT,
|
||||
featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2,
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
},
|
||||
|
||||
+5
-42
@@ -1,10 +1,6 @@
|
||||
<script setup>
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
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 RadioCard from 'dashboard/components-next/radioCard/RadioCard.vue';
|
||||
import FairDistribution from 'dashboard/components-next/AssignmentPolicy/components/FairDistribution.vue';
|
||||
@@ -68,18 +64,8 @@ const emit = defineEmits([
|
||||
]);
|
||||
|
||||
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 showAdvancedAssignmentPaywall = computed(() =>
|
||||
shouldShowPaywall(FEATURE_FLAGS.ADVANCED_ASSIGNMENT)
|
||||
);
|
||||
|
||||
const state = reactive({
|
||||
name: '',
|
||||
@@ -112,34 +98,11 @@ const createOption = (
|
||||
disabledLabel,
|
||||
});
|
||||
|
||||
const assignmentOrderOptions = computed(() => {
|
||||
const hasAdvancedAssignment = isFeatureEnabledonAccount.value(
|
||||
accountId.value,
|
||||
'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 assignmentOrderOptions = computed(() =>
|
||||
OPTIONS.ORDER.map(key =>
|
||||
createOption('ASSIGNMENT_ORDER', key, 'assignmentOrder')
|
||||
)
|
||||
);
|
||||
|
||||
const assignmentPriorityOptions = computed(() =>
|
||||
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 TagInput from 'dashboard/components-next/taginput/TagInput.vue';
|
||||
import assignmentPoliciesAPI from 'dashboard/api/assignmentPolicies';
|
||||
import { usePolicy } from 'dashboard/composables/usePolicy';
|
||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const props = defineProps({
|
||||
@@ -29,7 +27,6 @@ const store = useStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const { shouldShowPaywall } = usePolicy();
|
||||
|
||||
const selectedAgentIds = ref([]);
|
||||
const isAgentListUpdating = ref(false);
|
||||
@@ -81,22 +78,10 @@ const isFeatureEnabled = feature => {
|
||||
);
|
||||
};
|
||||
|
||||
const hasAdvancedAssignment = computed(() => {
|
||||
return isFeatureEnabled('advanced_assignment');
|
||||
});
|
||||
|
||||
const hasAssignmentV2 = computed(() => {
|
||||
return isFeatureEnabled('assignment_v2');
|
||||
});
|
||||
|
||||
const showAdvancedAssignmentUI = computed(() => {
|
||||
return hasAdvancedAssignment.value && hasAssignmentV2.value;
|
||||
});
|
||||
|
||||
const showAdvancedAssignmentPaywall = computed(() =>
|
||||
shouldShowPaywall(FEATURE_FLAGS.ADVANCED_ASSIGNMENT)
|
||||
);
|
||||
|
||||
const assignmentOrderLabel = computed(() => {
|
||||
if (!assignmentPolicy.value) return '';
|
||||
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 = () => {
|
||||
showDeleteConfirmModal.value = true;
|
||||
};
|
||||
@@ -351,7 +328,7 @@ const setDefaults = () => {
|
||||
maxAssignmentLimit.value =
|
||||
props.inbox.auto_assignment_config?.max_assignment_limit || null;
|
||||
fetchAttachedAgents();
|
||||
if (showAdvancedAssignmentUI.value) {
|
||||
if (hasAssignmentV2.value) {
|
||||
fetchAssignmentPolicy();
|
||||
fetchAvailablePolicies();
|
||||
}
|
||||
@@ -416,7 +393,7 @@ onMounted(() => {
|
||||
<template v-if="hasAssignmentV2">
|
||||
<!-- Policy Card - When policy is attached -->
|
||||
<div
|
||||
v-if="showAdvancedAssignmentUI && assignmentPolicy"
|
||||
v-if="assignmentPolicy"
|
||||
class="ltr:pr-0 rtl:pl-0 ltr:pl-4 rtl:pr-4 py-4"
|
||||
>
|
||||
<div class="flex items-start gap-4">
|
||||
@@ -480,13 +457,7 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<!-- Default Policy - When no custom policy attached but feature enabled -->
|
||||
<div
|
||||
v-else-if="
|
||||
showAdvancedAssignmentUI &&
|
||||
!assignmentPolicy &&
|
||||
!isLoadingPolicy
|
||||
"
|
||||
>
|
||||
<div v-else-if="!assignmentPolicy && !isLoadingPolicy">
|
||||
<!-- Default Policy Header -->
|
||||
<div class="p-4">
|
||||
<div class="flex items-start gap-4">
|
||||
@@ -579,62 +550,6 @@ onMounted(() => {
|
||||
</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>
|
||||
|
||||
<!-- Old UI for non-assignment_v2 -->
|
||||
|
||||
Reference in New Issue
Block a user