Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b9c07be9c | ||
|
|
975d22f1a2 | ||
|
|
dca8e3a995 | ||
|
|
f321becdbb | ||
|
|
3f3c06134c | ||
|
|
4897bfd2ef | ||
|
|
3a90653d12 |
@@ -7,7 +7,7 @@ defaults: &defaults
|
||||
working_directory: ~/build
|
||||
docker:
|
||||
# specify the version you desire here
|
||||
- image: cimg/ruby:3.3.3-browsers
|
||||
- image: cimg/ruby:3.2.2-browsers
|
||||
|
||||
# Specify service dependencies here if necessary
|
||||
# CircleCI maintains a library of pre-built images
|
||||
|
||||
@@ -12,7 +12,7 @@ services:
|
||||
args:
|
||||
VARIANT: "ubuntu-22.04"
|
||||
NODE_VERSION: "20.9.0"
|
||||
RUBY_VERSION: "3.3.3"
|
||||
RUBY_VERSION: "3.2.2"
|
||||
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
|
||||
USER_UID: "1000"
|
||||
USER_GID: "1000"
|
||||
@@ -25,7 +25,7 @@ services:
|
||||
args:
|
||||
VARIANT: "ubuntu-22.04"
|
||||
NODE_VERSION: "20.9.0"
|
||||
RUBY_VERSION: "3.3.3"
|
||||
RUBY_VERSION: "3.2.2"
|
||||
# On Linux, you may need to update USER_UID and USER_GID below if not your local UID is not 1000.
|
||||
USER_UID: "1000"
|
||||
USER_GID: "1000"
|
||||
|
||||
@@ -24,12 +24,10 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
platforms: 'arm64,amd64'
|
||||
uses: docker/setup-qemu-action@v1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Strip enterprise code
|
||||
run: |
|
||||
@@ -56,11 +54,10 @@ jobs:
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ env.DOCKER_TAG }}
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3.3.3
|
||||
3.2.2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
ruby '3.3.3'
|
||||
ruby '3.2.2'
|
||||
|
||||
##-- base gems for rails --##
|
||||
gem 'rack-cors', '2.0.0', require: 'rack/cors'
|
||||
@@ -116,7 +116,7 @@ gem 'sentry-ruby', require: false
|
||||
gem 'sentry-sidekiq', '>= 5.18.0', require: false
|
||||
|
||||
##-- background job processing --##
|
||||
gem 'sidekiq', '>= 7.3.0'
|
||||
gem 'sidekiq', '>= 7.2.4'
|
||||
# We want cron jobs
|
||||
gem 'sidekiq-cron', '>= 1.12.0'
|
||||
|
||||
|
||||
+16
-21
@@ -183,16 +183,13 @@ GEM
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
datadog-ci (0.8.3)
|
||||
msgpack
|
||||
date (3.3.4)
|
||||
ddtrace (1.23.2)
|
||||
datadog-ci (~> 0.8.1)
|
||||
debase-ruby_core_source (= 3.3.1)
|
||||
libdatadog (~> 7.0.0.1.0)
|
||||
libddwaf (~> 1.14.0.0.0)
|
||||
ddtrace (1.11.1)
|
||||
debase-ruby_core_source (>= 0.10.16, <= 3.2.0)
|
||||
libdatadog (~> 2.0.0.1.0)
|
||||
libddwaf (~> 1.8.2.0.0)
|
||||
msgpack
|
||||
debase-ruby_core_source (3.3.1)
|
||||
debase-ruby_core_source (3.2.0)
|
||||
debug (1.8.0)
|
||||
irb (>= 1.5.0)
|
||||
reline (>= 0.3.1)
|
||||
@@ -419,15 +416,15 @@ GEM
|
||||
addressable (~> 2.8)
|
||||
letter_opener (1.8.1)
|
||||
launchy (>= 2.2, < 3)
|
||||
libdatadog (7.0.0.1.0)
|
||||
libdatadog (7.0.0.1.0-x86_64-linux)
|
||||
libddwaf (1.14.0.0.0)
|
||||
libdatadog (2.0.0.1.0)
|
||||
libdatadog (2.0.0.1.0-x86_64-linux)
|
||||
libddwaf (1.8.2.0.0)
|
||||
ffi (~> 1.0)
|
||||
libddwaf (1.14.0.0.0-arm64-darwin)
|
||||
libddwaf (1.8.2.0.0-arm64-darwin)
|
||||
ffi (~> 1.0)
|
||||
libddwaf (1.14.0.0.0-x86_64-darwin)
|
||||
libddwaf (1.8.2.0.0-x86_64-darwin)
|
||||
ffi (~> 1.0)
|
||||
libddwaf (1.14.0.0.0-x86_64-linux)
|
||||
libddwaf (1.8.2.0.0-x86_64-linux)
|
||||
ffi (~> 1.0)
|
||||
line-bot-api (1.28.0)
|
||||
liquid (5.4.0)
|
||||
@@ -437,7 +434,6 @@ GEM
|
||||
llhttp-ffi (0.4.0)
|
||||
ffi-compiler (~> 1.0)
|
||||
rake (~> 13.0)
|
||||
logger (1.6.0)
|
||||
lograge (0.14.0)
|
||||
actionpack (>= 4)
|
||||
activesupport (>= 4)
|
||||
@@ -719,12 +715,11 @@ GEM
|
||||
sexp_processor (4.17.0)
|
||||
shoulda-matchers (5.3.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (7.3.0)
|
||||
sidekiq (7.2.4)
|
||||
concurrent-ruby (< 2)
|
||||
connection_pool (>= 2.3.0)
|
||||
logger
|
||||
rack (>= 2.2.4)
|
||||
redis-client (>= 0.22.2)
|
||||
redis-client (>= 0.19.0)
|
||||
sidekiq-cron (1.12.0)
|
||||
fugit (~> 1.8)
|
||||
globalid (>= 1.0.1)
|
||||
@@ -940,7 +935,7 @@ DEPENDENCIES
|
||||
sentry-ruby
|
||||
sentry-sidekiq (>= 5.18.0)
|
||||
shoulda-matchers
|
||||
sidekiq (>= 7.3.0)
|
||||
sidekiq (>= 7.2.4)
|
||||
sidekiq-cron (>= 1.12.0)
|
||||
simplecov (= 0.17.1)
|
||||
slack-ruby-client (~> 2.2.0)
|
||||
@@ -965,7 +960,7 @@ DEPENDENCIES
|
||||
working_hours
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.3.3p89
|
||||
ruby 3.2.2p185
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.14
|
||||
2.4.6
|
||||
|
||||
@@ -111,6 +111,15 @@
|
||||
@updateFolder="onUpdateSavedFilter"
|
||||
/>
|
||||
</woot-modal>
|
||||
<woot-modal
|
||||
:show.sync="showCustomSnoozeModal"
|
||||
:on-close="hideCustomSnoozeModal"
|
||||
>
|
||||
<custom-snooze-modal
|
||||
@close="hideCustomSnoozeModal"
|
||||
@choose-time="chooseSnoozeTime"
|
||||
/>
|
||||
</woot-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -143,6 +152,10 @@ import {
|
||||
isOnUnattendedView,
|
||||
} from '../store/modules/conversations/helpers/actionHelpers';
|
||||
import { CONVERSATION_EVENTS } from '../helper/AnalyticsHelper/events';
|
||||
import { CMD_SNOOZE_CONVERSATION } from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
|
||||
import { findSnoozeTime } from 'dashboard/helper/snoozeHelpers';
|
||||
import { getUnixTime } from 'date-fns';
|
||||
import CustomSnoozeModal from 'dashboard/components/CustomSnoozeModal.vue';
|
||||
import IntersectionObserver from './IntersectionObserver.vue';
|
||||
|
||||
export default {
|
||||
@@ -157,6 +170,7 @@ export default {
|
||||
ConversationBulkActions,
|
||||
IntersectionObserver,
|
||||
VirtualList,
|
||||
CustomSnoozeModal,
|
||||
},
|
||||
mixins: [
|
||||
timeMixin,
|
||||
@@ -233,6 +247,7 @@ export default {
|
||||
root: this.$refs.conversationList,
|
||||
rootMargin: '100px 0px 100px 0px',
|
||||
},
|
||||
showCustomSnoozeModal: false,
|
||||
|
||||
itemComponent: ConversationItem,
|
||||
// virtualListExtraProps is to pass the props to the conversationItem component.
|
||||
@@ -268,6 +283,7 @@ export default {
|
||||
campaigns: 'campaigns/getAllCampaigns',
|
||||
labels: 'labels/getLabels',
|
||||
selectedConversations: 'bulkActions/getSelectedConversationIds',
|
||||
contextMenuChatId: 'getContextMenuChatId',
|
||||
}),
|
||||
hasAppliedFilters() {
|
||||
return this.appliedFilters.length !== 0;
|
||||
@@ -298,14 +314,28 @@ export default {
|
||||
unassigned: 'unAssignedCount',
|
||||
all: 'allCount',
|
||||
};
|
||||
return Object.keys(ASSIGNEE_TYPE_TAB_KEYS).map(key => {
|
||||
const count = this.conversationStats[ASSIGNEE_TYPE_TAB_KEYS[key]] || 0;
|
||||
return {
|
||||
key,
|
||||
name: this.$t(`CHAT_LIST.ASSIGNEE_TYPE_TABS.${key}`),
|
||||
count,
|
||||
};
|
||||
});
|
||||
const userPermissions = this.currentUser.permissions;
|
||||
const allowedTabs = {
|
||||
me: ['conversation_manage', 'conversation_participating_manage'].some(
|
||||
permission => userPermissions.includes(permission)
|
||||
),
|
||||
unassigned: [
|
||||
'conversation_manage',
|
||||
'conversation_unassigned_manage',
|
||||
].some(permission => userPermissions.includes(permission)),
|
||||
all: true,
|
||||
};
|
||||
return Object.keys(allowedTabs)
|
||||
.filter(key => allowedTabs[key])
|
||||
.map(key => {
|
||||
const count =
|
||||
this.conversationStats[ASSIGNEE_TYPE_TAB_KEYS[key]] || 0;
|
||||
return {
|
||||
key,
|
||||
name: this.$t(`CHAT_LIST.ASSIGNEE_TYPE_TABS.${key}`),
|
||||
count,
|
||||
};
|
||||
});
|
||||
},
|
||||
showAssigneeInConversationCard() {
|
||||
return (
|
||||
@@ -501,6 +531,11 @@ export default {
|
||||
this.$emitter.on('fetch_conversation_stats', () => {
|
||||
this.$store.dispatch('conversationStats/get', this.conversationFilters);
|
||||
});
|
||||
|
||||
this.$emitter.on(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$emitter.off(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
|
||||
},
|
||||
methods: {
|
||||
updateVirtualListProps(key, value) {
|
||||
@@ -978,6 +1013,43 @@ export default {
|
||||
onContextMenuToggle(state) {
|
||||
this.isContextMenuOpen = state;
|
||||
},
|
||||
onCmdSnoozeConversation(snoozeType) {
|
||||
if (snoozeType === wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME) {
|
||||
this.showCustomSnoozeModal = true;
|
||||
} else {
|
||||
this.toggleStatus(
|
||||
wootConstants.STATUS_TYPE.SNOOZED,
|
||||
findSnoozeTime(snoozeType) || null
|
||||
);
|
||||
}
|
||||
},
|
||||
chooseSnoozeTime(customSnoozeTime) {
|
||||
this.showCustomSnoozeModal = false;
|
||||
if (customSnoozeTime) {
|
||||
this.toggleStatus(
|
||||
wootConstants.STATUS_TYPE.SNOOZED,
|
||||
getUnixTime(customSnoozeTime)
|
||||
);
|
||||
}
|
||||
},
|
||||
toggleStatus(status, snoozedUntil) {
|
||||
this.$store
|
||||
.dispatch('toggleStatus', {
|
||||
conversationId: this.currentChat?.id || this.contextMenuChatId,
|
||||
status,
|
||||
snoozedUntil,
|
||||
})
|
||||
.then(() => {
|
||||
this.$store.dispatch('setContextMenuChatId', null);
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_STATUS'));
|
||||
});
|
||||
},
|
||||
hideCustomSnoozeModal() {
|
||||
// if we select custom snooze and then the custom snooze modal is open
|
||||
// Then if the custom snooze modal is closed and set the context menu chat id to null
|
||||
this.$store.dispatch('setContextMenuChatId', null);
|
||||
this.showCustomSnoozeModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -37,8 +37,7 @@ import alertMixin from 'shared/mixins/alertMixin';
|
||||
import PrimarySidebar from './sidebarComponents/Primary.vue';
|
||||
import SecondarySidebar from './sidebarComponents/Secondary.vue';
|
||||
import keyboardEventListenerMixins from 'shared/mixins/keyboardEventListenerMixins';
|
||||
import router, { routesWithPermissions } from '../../routes';
|
||||
import { hasPermissions } from '../../helper/permissionsHelper';
|
||||
import router from '../../routes';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -99,12 +98,11 @@ export default {
|
||||
return getSidebarItems(this.accountId);
|
||||
},
|
||||
primaryMenuItems() {
|
||||
const userPermissions = this.currentUser.permissions;
|
||||
const permissions = this.currentUser.permissions;
|
||||
const menuItems = this.sideMenuConfig.primaryMenu;
|
||||
return menuItems.filter(menuItem => {
|
||||
const isAvailableForTheUser = hasPermissions(
|
||||
routesWithPermissions[menuItem.toStateName],
|
||||
userPermissions
|
||||
const isAvailableForTheUser = permissions.some(permission =>
|
||||
menuItem.meta.permissions.includes(permission)
|
||||
);
|
||||
|
||||
if (!isAvailableForTheUser) {
|
||||
|
||||
@@ -11,6 +11,9 @@ const campaigns = accountId => ({
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/campaigns/ongoing`),
|
||||
toStateName: 'ongoing_campaigns',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'oneOffCampaigns',
|
||||
@@ -19,6 +22,9 @@ const campaigns = accountId => ({
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/campaigns/one_off`),
|
||||
toStateName: 'one_off',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -14,6 +14,9 @@ const contacts = accountId => ({
|
||||
label: 'ALL_CONTACTS',
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/contacts`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'contacts_dashboard',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -28,6 +28,9 @@ const conversations = accountId => ({
|
||||
key: 'conversations',
|
||||
toState: frontendURL(`accounts/${accountId}/dashboard`),
|
||||
toolTip: 'Conversation from all subscribed inboxes',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'home',
|
||||
},
|
||||
{
|
||||
@@ -35,6 +38,9 @@ const conversations = accountId => ({
|
||||
label: 'MENTIONED_CONVERSATIONS',
|
||||
key: 'conversation_mentions',
|
||||
toState: frontendURL(`accounts/${accountId}/mentions/conversations`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'conversation_mentions',
|
||||
},
|
||||
{
|
||||
@@ -42,6 +48,9 @@ const conversations = accountId => ({
|
||||
label: 'UNATTENDED_CONVERSATIONS',
|
||||
key: 'conversation_unattended',
|
||||
toState: frontendURL(`accounts/${accountId}/unattended/conversations`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'conversation_unattended',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -9,6 +9,14 @@ const primaryMenuItems = accountId => [
|
||||
featureFlag: FEATURE_FLAGS.INBOX_VIEW,
|
||||
toState: frontendURL(`accounts/${accountId}/inbox-view`),
|
||||
toStateName: 'inbox_view',
|
||||
meta: {
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'chat',
|
||||
@@ -16,6 +24,14 @@ const primaryMenuItems = accountId => [
|
||||
label: 'CONVERSATIONS',
|
||||
toState: frontendURL(`accounts/${accountId}/dashboard`),
|
||||
toStateName: 'home',
|
||||
meta: {
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'book-contacts',
|
||||
@@ -24,6 +40,14 @@ const primaryMenuItems = accountId => [
|
||||
featureFlag: FEATURE_FLAGS.CRM,
|
||||
toState: frontendURL(`accounts/${accountId}/contacts`),
|
||||
toStateName: 'contacts_dashboard',
|
||||
meta: {
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'arrow-trending-lines',
|
||||
@@ -31,7 +55,10 @@ const primaryMenuItems = accountId => [
|
||||
label: 'REPORTS',
|
||||
featureFlag: FEATURE_FLAGS.REPORTS,
|
||||
toState: frontendURL(`accounts/${accountId}/reports`),
|
||||
toStateName: 'account_overview_reports',
|
||||
toStateName: 'settings_account_reports',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'megaphone',
|
||||
@@ -40,6 +67,9 @@ const primaryMenuItems = accountId => [
|
||||
featureFlag: FEATURE_FLAGS.CAMPAIGNS,
|
||||
toState: frontendURL(`accounts/${accountId}/campaigns`),
|
||||
toStateName: 'ongoing_campaigns',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'library',
|
||||
@@ -49,6 +79,9 @@ const primaryMenuItems = accountId => [
|
||||
alwaysVisibleOnChatwootInstances: true,
|
||||
toState: frontendURL(`accounts/${accountId}/portals`),
|
||||
toStateName: 'default_portal_articles',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'settings',
|
||||
@@ -56,6 +89,14 @@ const primaryMenuItems = accountId => [
|
||||
label: 'SETTINGS',
|
||||
toState: frontendURL(`accounts/${accountId}/settings`),
|
||||
toStateName: 'settings_home',
|
||||
meta: {
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ const reports = accountId => ({
|
||||
label: 'REPORTS_OVERVIEW',
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/overview`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'account_overview_reports',
|
||||
},
|
||||
{
|
||||
@@ -27,6 +30,9 @@ const reports = accountId => ({
|
||||
label: 'REPORTS_CONVERSATION',
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/conversation`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'conversation_reports',
|
||||
},
|
||||
{
|
||||
@@ -34,6 +40,9 @@ const reports = accountId => ({
|
||||
label: 'CSAT',
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/csat`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'csat_reports',
|
||||
},
|
||||
{
|
||||
@@ -42,6 +51,9 @@ const reports = accountId => ({
|
||||
hasSubMenu: false,
|
||||
featureFlag: FEATURE_FLAGS.RESPONSE_BOT,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/bot`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'bot_reports',
|
||||
},
|
||||
{
|
||||
@@ -49,6 +61,9 @@ const reports = accountId => ({
|
||||
label: 'REPORTS_AGENT',
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/agent`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'agent_reports',
|
||||
},
|
||||
{
|
||||
@@ -56,6 +71,9 @@ const reports = accountId => ({
|
||||
label: 'REPORTS_LABEL',
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/label`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'label_reports',
|
||||
},
|
||||
{
|
||||
@@ -63,6 +81,9 @@ const reports = accountId => ({
|
||||
label: 'REPORTS_INBOX',
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/inboxes`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'inbox_reports',
|
||||
},
|
||||
{
|
||||
@@ -70,6 +91,9 @@ const reports = accountId => ({
|
||||
label: 'REPORTS_TEAM',
|
||||
hasSubMenu: false,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/teams`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'team_reports',
|
||||
},
|
||||
{
|
||||
@@ -78,6 +102,9 @@ const reports = accountId => ({
|
||||
hasSubMenu: false,
|
||||
featureFlag: FEATURE_FLAGS.SLA,
|
||||
toState: frontendURL(`accounts/${accountId}/reports/sla`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'sla_reports',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -24,6 +24,7 @@ const settings = accountId => ({
|
||||
'settings_inbox_list',
|
||||
'settings_inbox_new',
|
||||
'settings_inbox_show',
|
||||
'settings_inbox',
|
||||
'settings_inboxes_add_agents',
|
||||
'settings_inboxes_page_channel',
|
||||
'settings_integrations_dashboard_apps',
|
||||
@@ -45,173 +46,173 @@ const settings = accountId => ({
|
||||
icon: 'briefcase',
|
||||
label: 'ACCOUNT_SETTINGS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/general`),
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
toStateName: 'general_settings_index',
|
||||
},
|
||||
{
|
||||
icon: 'people',
|
||||
label: 'AGENTS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/agents/list`),
|
||||
toStateName: 'agent_list',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.AGENT_MANAGEMENT,
|
||||
},
|
||||
{
|
||||
icon: 'people-team',
|
||||
label: 'TEAMS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/teams/list`),
|
||||
toStateName: 'settings_teams_list',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.TEAM_MANAGEMENT,
|
||||
},
|
||||
{
|
||||
icon: 'mail-inbox-all',
|
||||
label: 'INBOXES',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/inboxes/list`),
|
||||
toStateName: 'settings_inbox_list',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.INBOX_MANAGEMENT,
|
||||
},
|
||||
{
|
||||
icon: 'tag',
|
||||
label: 'LABELS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/labels/list`),
|
||||
toStateName: 'labels_list',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.LABELS,
|
||||
},
|
||||
{
|
||||
icon: 'code',
|
||||
label: 'CUSTOM_ATTRIBUTES',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(
|
||||
`accounts/${accountId}/settings/custom-attributes/list`
|
||||
),
|
||||
toStateName: 'attributes_list',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.CUSTOM_ATTRIBUTES,
|
||||
},
|
||||
{
|
||||
icon: 'automation',
|
||||
label: 'AUTOMATION',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/automation/list`),
|
||||
toStateName: 'automation_list',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.AUTOMATIONS,
|
||||
},
|
||||
{
|
||||
icon: 'bot',
|
||||
label: 'AGENT_BOTS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
globalConfigFlag: 'csmlEditorHost',
|
||||
toState: frontendURL(`accounts/${accountId}/settings/agent-bots`),
|
||||
toStateName: 'agent_bots',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.AGENT_BOTS,
|
||||
},
|
||||
{
|
||||
icon: 'flash-settings',
|
||||
label: 'MACROS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/macros`),
|
||||
toStateName: 'macros_wrapper',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.MACROS,
|
||||
},
|
||||
{
|
||||
icon: 'chat-multiple',
|
||||
label: 'CANNED_RESPONSES',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
toState: frontendURL(
|
||||
`accounts/${accountId}/settings/canned-response/list`
|
||||
),
|
||||
toStateName: 'canned_list',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.CANNED_RESPONSES,
|
||||
},
|
||||
{
|
||||
icon: 'flash-on',
|
||||
label: 'INTEGRATIONS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/integrations`),
|
||||
toStateName: 'settings_integrations',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.INTEGRATIONS,
|
||||
},
|
||||
{
|
||||
icon: 'star-emphasis',
|
||||
label: 'APPLICATIONS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/applications`),
|
||||
toStateName: 'settings_applications',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
featureFlag: FEATURE_FLAGS.INTEGRATIONS,
|
||||
},
|
||||
{
|
||||
icon: 'key',
|
||||
label: 'AUDIT_LOGS',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/audit-log/list`),
|
||||
toStateName: 'auditlogs_list',
|
||||
isEnterpriseOnly: true,
|
||||
featureFlag: FEATURE_FLAGS.AUDIT_LOGS,
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
beta: true,
|
||||
},
|
||||
{
|
||||
icon: 'document-list-clock',
|
||||
label: 'SLA',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/sla/list`),
|
||||
toStateName: 'sla_list',
|
||||
isEnterpriseOnly: true,
|
||||
featureFlag: FEATURE_FLAGS.SLA,
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
beta: true,
|
||||
},
|
||||
{
|
||||
icon: 'credit-card-person',
|
||||
label: 'BILLING',
|
||||
hasSubMenu: false,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
toState: frontendURL(`accounts/${accountId}/settings/billing`),
|
||||
toStateName: 'billing_settings_index',
|
||||
meta: {
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
showOnlyOnCloud: true,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -29,8 +29,6 @@ import SecondaryNavItem from './SecondaryNavItem.vue';
|
||||
import AccountContext from './AccountContext.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { FEATURE_FLAGS } from '../../../featureFlags';
|
||||
import { hasPermissions } from '../../../helper/permissionsHelper';
|
||||
import { routesWithPermissions } from '../../../routes';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -84,10 +82,10 @@ export default {
|
||||
accessibleMenuItems() {
|
||||
const menuItemsFilteredByPermissions = this.menuConfig.menuItems.filter(
|
||||
menuItem => {
|
||||
const { meta: { permissions: menuPermissions = [] } = {} } = menuItem;
|
||||
const { permissions: userPermissions = [] } = this.currentUser;
|
||||
return hasPermissions(
|
||||
routesWithPermissions[menuItem.toStateName],
|
||||
userPermissions
|
||||
return menuPermissions.some(permission =>
|
||||
userPermissions.includes(permission)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
:show-child-count="showChildCount(child.count)"
|
||||
:child-item-count="child.count"
|
||||
/>
|
||||
<Policy :permissions="['administrator']">
|
||||
<Policy :permissions="['account_manage']">
|
||||
<router-link
|
||||
v-if="menuItem.newLink"
|
||||
v-slot="{ href, navigate }"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
import { computed } from 'vue';
|
||||
import { hasPermissions } from '../helper/permissionsHelper';
|
||||
|
||||
const props = defineProps({
|
||||
permissions: {
|
||||
type: Array,
|
||||
@@ -11,8 +11,9 @@ const props = defineProps({
|
||||
|
||||
const getters = useStoreGetters();
|
||||
const user = getters.getCurrentUser.value;
|
||||
|
||||
const hasPermission = computed(() =>
|
||||
hasPermissions(props.permissions, user.permissions)
|
||||
props.permissions.some(permission => user.permissions.includes(permission))
|
||||
);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
export const ACCOUNT_PERMISSIONS = {
|
||||
ACCOUNT_MANAGE: 'account_manage',
|
||||
PORTAL_MANAGE: 'portal_manage',
|
||||
CONVERSATION_MANAGE: 'conversation_manage',
|
||||
CONVERSATION_UNASSIGNED_MANAGE: 'conversation_unassigned_manage',
|
||||
CONVERSATION_PARTICIPATING_MANAGE: 'conversation_participating_manage',
|
||||
MACROS_MANAGE: 'macros_manage',
|
||||
REPORTS_MANAGE: 'reports_manage',
|
||||
CONTACTS_MANAGE: 'contacts_manage',
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
export const hasPermissions = (
|
||||
requiredPermissions = [],
|
||||
availablePermissions = []
|
||||
) => {
|
||||
return requiredPermissions.some(permission =>
|
||||
availablePermissions.includes(permission)
|
||||
);
|
||||
};
|
||||
|
||||
const isPermissionsPresentInRoute = route =>
|
||||
route.meta && route.meta.permissions;
|
||||
|
||||
export const buildPermissionsFromRouter = (routes = []) =>
|
||||
routes.reduce((acc, route) => {
|
||||
if (route.name) {
|
||||
if (!isPermissionsPresentInRoute(route)) {
|
||||
// eslint-disable-next-line
|
||||
console.error(route);
|
||||
throw new Error(
|
||||
"The route doesn't have the required permissions defined"
|
||||
);
|
||||
}
|
||||
acc[route.name] = route.meta.permissions;
|
||||
}
|
||||
|
||||
if (route.children) {
|
||||
acc = {
|
||||
...acc,
|
||||
...buildPermissionsFromRouter(route.children),
|
||||
};
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
@@ -1,5 +1,3 @@
|
||||
import { hasPermissions } from './permissionsHelper';
|
||||
|
||||
// eslint-disable-next-line default-param-last
|
||||
export const getCurrentAccount = ({ accounts } = {}, accountId) => {
|
||||
return accounts.find(account => account.id === accountId);
|
||||
@@ -7,7 +5,9 @@ export const getCurrentAccount = ({ accounts } = {}, accountId) => {
|
||||
|
||||
export const routeIsAccessibleFor = (route, userPermissions = []) => {
|
||||
const { meta: { permissions: routePermissions = [] } = {} } = route;
|
||||
return hasPermissions(routePermissions, userPermissions);
|
||||
return routePermissions.some(permissions =>
|
||||
userPermissions.includes(permissions)
|
||||
);
|
||||
};
|
||||
|
||||
const validateActiveAccountRoutes = (to, user) => {
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
import {
|
||||
buildPermissionsFromRouter,
|
||||
hasPermissions,
|
||||
} from '../permissionsHelper';
|
||||
|
||||
describe('hasPermissions', () => {
|
||||
it('returns true if permission is present', () => {
|
||||
expect(
|
||||
hasPermissions(['contact_manage'], ['team_manage', 'contact_manage'])
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true if permission is not present', () => {
|
||||
expect(
|
||||
hasPermissions(['contact_manage'], ['team_manage', 'user_manage'])
|
||||
).toBe(false);
|
||||
expect(hasPermissions()).toBe(false);
|
||||
expect(hasPermissions([])).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildPermissionsFromRouter', () => {
|
||||
it('returns a valid object when routes have permissions defined', () => {
|
||||
expect(
|
||||
buildPermissionsFromRouter([
|
||||
{
|
||||
path: 'agent',
|
||||
name: 'agent_list',
|
||||
meta: { permissions: ['agent_admin'] },
|
||||
},
|
||||
{
|
||||
path: 'inbox',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'inbox_list',
|
||||
meta: { permissions: ['inbox_admin'] },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'conversations',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
children: [
|
||||
{
|
||||
path: 'attachments',
|
||||
name: 'attachments_list',
|
||||
meta: { permissions: ['conversation_admin'] },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
).toEqual({
|
||||
agent_list: ['agent_admin'],
|
||||
inbox_list: ['inbox_admin'],
|
||||
attachments_list: ['conversation_admin'],
|
||||
});
|
||||
});
|
||||
|
||||
it('throws an error if a named routed does not have permissions defined', () => {
|
||||
expect(() => {
|
||||
buildPermissionsFromRouter([
|
||||
{
|
||||
path: 'agent',
|
||||
name: 'agent_list',
|
||||
},
|
||||
]);
|
||||
}).toThrow("The route doesn't have the required permissions defined");
|
||||
|
||||
expect(() => {
|
||||
buildPermissionsFromRouter([
|
||||
{
|
||||
path: 'agent',
|
||||
name: 'agent_list',
|
||||
meta: {},
|
||||
},
|
||||
]);
|
||||
}).toThrow("The route doesn't have the required permissions defined");
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
getConversationDashboardRoute,
|
||||
getCurrentAccount,
|
||||
getUserRole,
|
||||
isAConversationRoute,
|
||||
routeIsAccessibleFor,
|
||||
validateLoggedInRoutes,
|
||||
@@ -14,11 +15,24 @@ describe('#getCurrentAccount', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getUserRole', () => {
|
||||
it('should return the current role', () => {
|
||||
expect(
|
||||
getUserRole({ accounts: [{ id: 1, role: 'administrator' }] }, 1)
|
||||
).toEqual('administrator');
|
||||
expect(getUserRole({ accounts: [] }, 1)).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#routeIsAccessibleFor', () => {
|
||||
it('should return the correct access', () => {
|
||||
let route = { meta: { permissions: ['administrator'] } };
|
||||
expect(routeIsAccessibleFor(route, ['agent'])).toEqual(false);
|
||||
expect(routeIsAccessibleFor(route, ['administrator'])).toEqual(true);
|
||||
const roleWiseRoutes = { agent: ['conversations'], admin: ['billing'] };
|
||||
expect(routeIsAccessibleFor('billing', 'agent', roleWiseRoutes)).toEqual(
|
||||
false
|
||||
);
|
||||
expect(routeIsAccessibleFor('billing', 'admin', roleWiseRoutes)).toEqual(
|
||||
true
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,7 +40,11 @@ describe('#validateLoggedInRoutes', () => {
|
||||
describe('when account access is missing', () => {
|
||||
it('should return the login route', () => {
|
||||
expect(
|
||||
validateLoggedInRoutes({ params: { accountId: 1 } }, { accounts: [] })
|
||||
validateLoggedInRoutes(
|
||||
{ params: { accountId: 1 } },
|
||||
{ accounts: [] },
|
||||
{}
|
||||
)
|
||||
).toEqual(`app/login`);
|
||||
});
|
||||
});
|
||||
@@ -35,12 +53,9 @@ describe('#validateLoggedInRoutes', () => {
|
||||
it('return suspended route', () => {
|
||||
expect(
|
||||
validateLoggedInRoutes(
|
||||
{
|
||||
name: 'conversations',
|
||||
params: { accountId: 1 },
|
||||
meta: { permissions: ['agent'] },
|
||||
},
|
||||
{ accounts: [{ id: 1, role: 'agent', status: 'suspended' }] }
|
||||
{ name: 'conversations', params: { accountId: 1 } },
|
||||
{ accounts: [{ id: 1, role: 'agent', status: 'suspended' }] },
|
||||
{ agent: ['conversations'] }
|
||||
)
|
||||
).toEqual(`accounts/1/suspended`);
|
||||
});
|
||||
@@ -50,22 +65,9 @@ describe('#validateLoggedInRoutes', () => {
|
||||
it('returns null (no action required)', () => {
|
||||
expect(
|
||||
validateLoggedInRoutes(
|
||||
{
|
||||
name: 'conversations',
|
||||
params: { accountId: 1 },
|
||||
meta: { permissions: ['agent'] },
|
||||
},
|
||||
{
|
||||
permissions: ['agent'],
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
role: 'agent',
|
||||
permissions: ['agent'],
|
||||
status: 'active',
|
||||
},
|
||||
],
|
||||
}
|
||||
{ name: 'conversations', params: { accountId: 1 } },
|
||||
{ accounts: [{ id: 1, role: 'agent', status: 'active' }] },
|
||||
{ agent: ['conversations'] }
|
||||
)
|
||||
).toEqual(null);
|
||||
});
|
||||
@@ -74,12 +76,9 @@ describe('#validateLoggedInRoutes', () => {
|
||||
it('returns dashboard url', () => {
|
||||
expect(
|
||||
validateLoggedInRoutes(
|
||||
{
|
||||
name: 'billing',
|
||||
params: { accountId: 1 },
|
||||
meta: { permissions: ['administrator'] },
|
||||
},
|
||||
{ accounts: [{ id: 1, role: 'agent', status: 'active' }] }
|
||||
{ name: 'conversations', params: { accountId: 1 } },
|
||||
{ accounts: [{ id: 1, role: 'agent', status: 'active' }] },
|
||||
{ admin: ['conversations'], agent: [] }
|
||||
)
|
||||
).toEqual(`accounts/1/dashboard`);
|
||||
});
|
||||
@@ -89,7 +88,8 @@ describe('#validateLoggedInRoutes', () => {
|
||||
expect(
|
||||
validateLoggedInRoutes(
|
||||
{ name: 'account_suspended', params: { accountId: 1 } },
|
||||
{ accounts: [{ id: 1, role: 'agent', status: 'active' }] }
|
||||
{ accounts: [{ id: 1, role: 'agent', status: 'active' }] },
|
||||
{ agent: ['account_suspended'] }
|
||||
)
|
||||
).toEqual(`accounts/1/dashboard`);
|
||||
});
|
||||
|
||||
@@ -8,7 +8,12 @@ export const routes = [
|
||||
path: frontendURL('accounts/:accountId/search'),
|
||||
name: 'search',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: SearchView,
|
||||
},
|
||||
|
||||
@@ -8,7 +8,12 @@ export const routes = [
|
||||
path: frontendURL('accounts/:accountId/contacts'),
|
||||
name: 'contacts_dashboard',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ContactsView,
|
||||
},
|
||||
@@ -16,7 +21,12 @@ export const routes = [
|
||||
path: frontendURL('accounts/:accountId/contacts/custom_view/:id'),
|
||||
name: 'contacts_segments_dashboard',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ContactsView,
|
||||
props: route => {
|
||||
@@ -27,7 +37,12 @@ export const routes = [
|
||||
path: frontendURL('accounts/:accountId/labels/:label/contacts'),
|
||||
name: 'contacts_labels_dashboard',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ContactsView,
|
||||
props: route => {
|
||||
@@ -38,7 +53,12 @@ export const routes = [
|
||||
path: frontendURL('accounts/:accountId/contacts/:contactId'),
|
||||
name: 'contact_profile_dashboard',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ContactManageView,
|
||||
props: route => {
|
||||
|
||||
@@ -22,40 +22,25 @@
|
||||
:is-on-expanded-layout="isOnExpandedLayout"
|
||||
@contact-panel-toggle="onToggleContactPanel"
|
||||
/>
|
||||
<woot-modal
|
||||
:show.sync="showCustomSnoozeModal"
|
||||
:on-close="hideCustomSnoozeModal"
|
||||
>
|
||||
<custom-snooze-modal
|
||||
@close="hideCustomSnoozeModal"
|
||||
@choose-time="chooseSnoozeTime"
|
||||
/>
|
||||
</woot-modal>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { getUnixTime } from 'date-fns';
|
||||
import ChatList from '../../../components/ChatList.vue';
|
||||
import ConversationBox from '../../../components/widgets/conversation/ConversationBox.vue';
|
||||
import PopOverSearch from './search/PopOverSearch.vue';
|
||||
import CustomSnoozeModal from 'dashboard/components/CustomSnoozeModal.vue';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
||||
import { CMD_SNOOZE_CONVERSATION } from 'dashboard/routes/dashboard/commands/commandBarBusEvents';
|
||||
import { findSnoozeTime } from 'dashboard/helper/snoozeHelpers';
|
||||
import wootConstants from 'dashboard/constants/globals';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ChatList,
|
||||
ConversationBox,
|
||||
PopOverSearch,
|
||||
CustomSnoozeModal,
|
||||
},
|
||||
mixins: [uiSettingsMixin, alertMixin],
|
||||
mixins: [uiSettingsMixin],
|
||||
props: {
|
||||
inboxId: {
|
||||
type: [String, Number],
|
||||
@@ -85,14 +70,12 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
showSearchModal: false,
|
||||
showCustomSnoozeModal: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
chatList: 'getAllConversations',
|
||||
currentChat: 'getSelectedChat',
|
||||
contextMenuChatId: 'getContextMenuChatId',
|
||||
}),
|
||||
showConversationList() {
|
||||
return this.isOnExpandedLayout ? !this.conversationId : true;
|
||||
@@ -129,10 +112,6 @@ export default {
|
||||
this.$watch('chatList.length', () => {
|
||||
this.setActiveChat();
|
||||
});
|
||||
this.$emitter.on(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$emitter.off(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation);
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -207,43 +186,6 @@ export default {
|
||||
closeSearch() {
|
||||
this.showSearchModal = false;
|
||||
},
|
||||
onCmdSnoozeConversation(snoozeType) {
|
||||
if (snoozeType === wootConstants.SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME) {
|
||||
this.showCustomSnoozeModal = true;
|
||||
} else {
|
||||
this.toggleStatus(
|
||||
wootConstants.STATUS_TYPE.SNOOZED,
|
||||
findSnoozeTime(snoozeType) || null
|
||||
);
|
||||
}
|
||||
},
|
||||
chooseSnoozeTime(customSnoozeTime) {
|
||||
this.showCustomSnoozeModal = false;
|
||||
if (customSnoozeTime) {
|
||||
this.toggleStatus(
|
||||
wootConstants.STATUS_TYPE.SNOOZED,
|
||||
getUnixTime(customSnoozeTime)
|
||||
);
|
||||
}
|
||||
},
|
||||
toggleStatus(status, snoozedUntil) {
|
||||
this.$store
|
||||
.dispatch('toggleStatus', {
|
||||
conversationId: this.currentChat?.id || this.contextMenuChatId,
|
||||
status,
|
||||
snoozedUntil,
|
||||
})
|
||||
.then(() => {
|
||||
this.$store.dispatch('setContextMenuChatId', null);
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_STATUS'));
|
||||
});
|
||||
},
|
||||
hideCustomSnoozeModal() {
|
||||
// if we select custom snooze and the custom snooze modal is open
|
||||
// Then if the custom snooze modal is closed then set the context menu chat id to null
|
||||
this.$store.dispatch('setContextMenuChatId', null);
|
||||
this.showCustomSnoozeModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
/* eslint arrow-body-style: 0 */
|
||||
import { ACCOUNT_PERMISSIONS } from '../../../constants/permissions';
|
||||
import { frontendURL } from '../../../helper/URLHelper';
|
||||
const ConversationView = () => import('./ConversationView');
|
||||
|
||||
const GENERIC_CONVERSATION_PERMISSIONS = [
|
||||
ACCOUNT_PERMISSIONS.ACCOUNT_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_PARTICIPATING_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_UNASSIGNED_MANAGE,
|
||||
];
|
||||
|
||||
export default {
|
||||
routes: [
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/dashboard'),
|
||||
name: 'home',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: () => {
|
||||
return { inboxId: 0 };
|
||||
@@ -18,9 +24,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/conversations/:conversation_id'),
|
||||
name: 'inbox_conversation',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => {
|
||||
return { inboxId: 0, conversationId: route.params.conversation_id };
|
||||
@@ -29,9 +33,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/inbox/:inbox_id'),
|
||||
name: 'inbox_dashboard',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => {
|
||||
return { inboxId: route.params.inbox_id };
|
||||
@@ -42,9 +44,7 @@ export default {
|
||||
'accounts/:accountId/inbox/:inbox_id/conversations/:conversation_id'
|
||||
),
|
||||
name: 'conversation_through_inbox',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => {
|
||||
return {
|
||||
@@ -56,9 +56,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/label/:label'),
|
||||
name: 'label_conversations',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({ label: route.params.label }),
|
||||
},
|
||||
@@ -67,9 +65,7 @@ export default {
|
||||
'accounts/:accountId/label/:label/conversations/:conversation_id'
|
||||
),
|
||||
name: 'conversations_through_label',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversation_id,
|
||||
@@ -79,9 +75,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/team/:teamId'),
|
||||
name: 'team_conversations',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({ teamId: route.params.teamId }),
|
||||
},
|
||||
@@ -90,9 +84,7 @@ export default {
|
||||
'accounts/:accountId/team/:teamId/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversations_through_team',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
@@ -102,9 +94,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/custom_view/:id'),
|
||||
name: 'folder_conversations',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({ foldersId: route.params.id }),
|
||||
},
|
||||
@@ -113,9 +103,7 @@ export default {
|
||||
'accounts/:accountId/custom_view/:id/conversations/:conversation_id'
|
||||
),
|
||||
name: 'conversations_through_folders',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversation_id,
|
||||
@@ -125,9 +113,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/mentions/conversations'),
|
||||
name: 'conversation_mentions',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: () => ({ conversationType: 'mention' }),
|
||||
},
|
||||
@@ -136,9 +122,7 @@ export default {
|
||||
'accounts/:accountId/mentions/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversation_through_mentions',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
@@ -148,9 +132,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/unattended/conversations'),
|
||||
name: 'conversation_unattended',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: () => ({ conversationType: 'unattended' }),
|
||||
},
|
||||
@@ -159,9 +141,7 @@ export default {
|
||||
'accounts/:accountId/unattended/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversation_through_unattended',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
@@ -171,10 +151,13 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/participating/conversations'),
|
||||
name: 'conversation_participating',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
component: ConversationView,
|
||||
meta: {
|
||||
permissions: [
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_PARTICIPATING_MANAGE,
|
||||
],
|
||||
},
|
||||
props: () => ({ conversationType: 'participating' }),
|
||||
},
|
||||
{
|
||||
@@ -182,10 +165,13 @@ export default {
|
||||
'accounts/:accountId/participating/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversation_through_participating',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
},
|
||||
component: ConversationView,
|
||||
meta: {
|
||||
permissions: [
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_PARTICIPATING_MANAGE,
|
||||
],
|
||||
},
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
conversationType: 'participating',
|
||||
|
||||
@@ -29,7 +29,7 @@ export default {
|
||||
path: frontendURL('accounts/:accountId/suspended'),
|
||||
name: 'account_suspended',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: ['profile_manage'],
|
||||
},
|
||||
component: Suspended,
|
||||
},
|
||||
|
||||
@@ -31,7 +31,12 @@ const portalRoutes = [
|
||||
path: getPortalRoute(''),
|
||||
name: 'default_portal_articles',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: DefaultPortalArticles,
|
||||
},
|
||||
@@ -39,7 +44,12 @@ const portalRoutes = [
|
||||
path: getPortalRoute('all'),
|
||||
name: 'list_all_portals',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListAllPortals,
|
||||
},
|
||||
@@ -52,7 +62,7 @@ const portalRoutes = [
|
||||
name: 'new_portal_information',
|
||||
component: PortalDetails,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -60,7 +70,7 @@ const portalRoutes = [
|
||||
name: 'portal_customization',
|
||||
component: PortalCustomization,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -68,7 +78,7 @@ const portalRoutes = [
|
||||
name: 'portal_finish',
|
||||
component: PortalSettingsFinish,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -77,14 +87,24 @@ const portalRoutes = [
|
||||
path: getPortalRoute(':portalSlug'),
|
||||
name: 'portalSlug',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ShowPortal,
|
||||
},
|
||||
{
|
||||
path: getPortalRoute(':portalSlug/edit'),
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: EditPortal,
|
||||
children: [
|
||||
@@ -93,7 +113,7 @@ const portalRoutes = [
|
||||
name: 'edit_portal_information',
|
||||
component: EditPortalBasic,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -101,7 +121,7 @@ const portalRoutes = [
|
||||
name: 'edit_portal_customization',
|
||||
component: EditPortalCustomization,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -109,14 +129,19 @@ const portalRoutes = [
|
||||
name: 'edit_portal_locales',
|
||||
component: EditPortalLocales,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'categories',
|
||||
name: 'list_all_locale_categories',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListAllCategories,
|
||||
},
|
||||
@@ -129,7 +154,12 @@ const articleRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/articles'),
|
||||
name: 'list_all_locale_articles',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListAllArticles,
|
||||
},
|
||||
@@ -137,7 +167,12 @@ const articleRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/articles/new'),
|
||||
name: 'new_article',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: NewArticle,
|
||||
},
|
||||
@@ -145,7 +180,12 @@ const articleRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/articles/mine'),
|
||||
name: 'list_mine_articles',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListAllArticles,
|
||||
},
|
||||
@@ -153,7 +193,12 @@ const articleRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/articles/archived'),
|
||||
name: 'list_archived_articles',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListAllArticles,
|
||||
},
|
||||
@@ -162,7 +207,12 @@ const articleRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/articles/draft'),
|
||||
name: 'list_draft_articles',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListAllArticles,
|
||||
},
|
||||
@@ -171,7 +221,12 @@ const articleRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/articles/:articleSlug'),
|
||||
name: 'edit_article',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: EditArticle,
|
||||
},
|
||||
@@ -182,7 +237,12 @@ const categoryRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/categories'),
|
||||
name: 'all_locale_categories',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListAllCategories,
|
||||
},
|
||||
@@ -190,7 +250,12 @@ const categoryRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/categories/new'),
|
||||
name: 'new_category_in_locale',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: NewCategory,
|
||||
},
|
||||
@@ -198,7 +263,12 @@ const categoryRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/categories/:categorySlug'),
|
||||
name: 'show_category',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListAllArticles,
|
||||
},
|
||||
@@ -208,7 +278,12 @@ const categoryRoutes = [
|
||||
),
|
||||
name: 'show_category_articles',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: ListCategoryArticles,
|
||||
},
|
||||
@@ -216,7 +291,12 @@ const categoryRoutes = [
|
||||
path: getPortalRoute(':portalSlug/:locale/categories/:categorySlug'),
|
||||
name: 'edit_category',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: EditCategory,
|
||||
},
|
||||
|
||||
@@ -13,7 +13,12 @@ export const routes = [
|
||||
name: 'inbox_view',
|
||||
component: InboxEmptyStateView,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -21,7 +26,12 @@ export const routes = [
|
||||
name: 'inbox_view_conversation',
|
||||
component: InboxDetailView,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -19,7 +19,12 @@ export const routes = [
|
||||
name: 'notifications_index',
|
||||
component: NotificationsView,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -7,7 +7,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/settings/general'),
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: SettingsContent,
|
||||
props: {
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
name: 'general_settings_index',
|
||||
component: Index,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -9,7 +9,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/settings/agent-bots'),
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: SettingsContent,
|
||||
props: {
|
||||
@@ -23,7 +23,7 @@ export default {
|
||||
name: 'agent_bots',
|
||||
component: Bot,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -31,7 +31,7 @@ export default {
|
||||
name: 'agent_bots_csml_new',
|
||||
component: CsmlNewBot,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
name: 'agent_bots_csml_edit',
|
||||
component: CsmlEditBot,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -15,6 +15,7 @@ export default {
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'agents_wrapper',
|
||||
redirect: 'list',
|
||||
},
|
||||
{
|
||||
@@ -22,7 +23,7 @@ export default {
|
||||
name: 'agent_list',
|
||||
component: AgentHome,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -15,6 +15,7 @@ export default {
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'attributes_wrapper',
|
||||
redirect: 'list',
|
||||
},
|
||||
{
|
||||
@@ -22,7 +23,7 @@ export default {
|
||||
name: 'attributes_list',
|
||||
component: AttributesHome,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -16,13 +16,14 @@ export default {
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'auditlogs_wrapper',
|
||||
redirect: 'list',
|
||||
},
|
||||
{
|
||||
path: 'list',
|
||||
name: 'auditlogs_list',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: AuditLogsHome,
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ export default {
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'automation_wrapper',
|
||||
redirect: 'list',
|
||||
},
|
||||
{
|
||||
@@ -22,7 +23,7 @@ export default {
|
||||
name: 'automation_list',
|
||||
component: Automation,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -7,7 +7,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/settings/billing'),
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: SettingsContent,
|
||||
props: {
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
name: 'billing_settings_index',
|
||||
component: Index,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -20,7 +20,7 @@ export default {
|
||||
path: 'ongoing',
|
||||
name: 'ongoing_campaigns',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: Index,
|
||||
},
|
||||
@@ -38,7 +38,7 @@ export default {
|
||||
path: 'one_off',
|
||||
name: 'one_off',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: Index,
|
||||
},
|
||||
|
||||
@@ -16,13 +16,19 @@ export default {
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'canned_wrapper',
|
||||
redirect: 'list',
|
||||
},
|
||||
{
|
||||
path: 'list',
|
||||
name: 'canned_list',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: CannedHome,
|
||||
},
|
||||
|
||||
@@ -28,6 +28,7 @@ export default {
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'settings_inbox',
|
||||
redirect: 'list',
|
||||
},
|
||||
{
|
||||
@@ -35,7 +36,7 @@ export default {
|
||||
name: 'settings_inbox_list',
|
||||
component: InboxHome,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -47,7 +48,7 @@ export default {
|
||||
name: 'settings_inbox_new',
|
||||
component: ChannelList,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -55,7 +56,7 @@ export default {
|
||||
name: 'settings_inbox_finish',
|
||||
component: FinishSetup,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -63,7 +64,7 @@ export default {
|
||||
name: 'settings_inboxes_page_channel',
|
||||
component: channelFactory.create(),
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
props: route => {
|
||||
return { channel_name: route.params.sub_page };
|
||||
@@ -73,7 +74,7 @@ export default {
|
||||
path: ':inbox_id/agents',
|
||||
name: 'settings_inboxes_add_agents',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: AddAgents,
|
||||
},
|
||||
@@ -84,7 +85,7 @@ export default {
|
||||
name: 'settings_inbox_show',
|
||||
component: Settings,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ export default {
|
||||
name: 'settings_applications',
|
||||
component: Index,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -35,7 +35,7 @@ export default {
|
||||
name: 'settings_applications_integration',
|
||||
component: IntegrationHooks,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
props: route => ({
|
||||
integrationId: route.params.integration_id,
|
||||
|
||||
+5
-5
@@ -31,7 +31,7 @@ export default {
|
||||
name: 'settings_integrations',
|
||||
component: Index,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -39,7 +39,7 @@ export default {
|
||||
component: Webhook,
|
||||
name: 'settings_integrations_webhook',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -47,7 +47,7 @@ export default {
|
||||
component: DashboardApps,
|
||||
name: 'settings_integrations_dashboard_apps',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -55,7 +55,7 @@ export default {
|
||||
name: 'settings_integrations_slack',
|
||||
component: Slack,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
props: route => ({ code: route.query.code }),
|
||||
},
|
||||
@@ -64,7 +64,7 @@ export default {
|
||||
name: 'settings_integrations_integration',
|
||||
component: ShowIntegration,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
props: route => {
|
||||
return {
|
||||
|
||||
@@ -18,7 +18,7 @@ export default {
|
||||
path: '',
|
||||
name: 'labels_wrapper',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
redirect: 'list',
|
||||
},
|
||||
@@ -26,7 +26,7 @@ export default {
|
||||
path: 'list',
|
||||
name: 'labels_list',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: Index,
|
||||
},
|
||||
|
||||
@@ -24,7 +24,12 @@ export default {
|
||||
name: 'macros_wrapper',
|
||||
component: Macros,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -32,7 +37,12 @@ export default {
|
||||
name: 'macros_new',
|
||||
component: MacroEditor,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -40,7 +50,12 @@ export default {
|
||||
name: 'macros_edit',
|
||||
component: MacroEditor,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -9,7 +9,12 @@ export default {
|
||||
path: frontendURL('accounts/:accountId/profile'),
|
||||
name: 'profile_settings',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
component: SettingsContent,
|
||||
children: [
|
||||
@@ -18,7 +23,12 @@ export default {
|
||||
name: 'profile_settings_index',
|
||||
component: Index,
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -30,7 +30,7 @@ export default {
|
||||
path: 'overview',
|
||||
name: 'account_overview_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: LiveReports,
|
||||
},
|
||||
@@ -49,7 +49,7 @@ export default {
|
||||
path: 'conversation',
|
||||
name: 'conversation_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: Index,
|
||||
},
|
||||
@@ -68,7 +68,7 @@ export default {
|
||||
path: 'csat',
|
||||
name: 'csat_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: CsatResponses,
|
||||
},
|
||||
@@ -87,7 +87,7 @@ export default {
|
||||
path: 'bot',
|
||||
name: 'bot_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: BotReports,
|
||||
},
|
||||
@@ -106,7 +106,7 @@ export default {
|
||||
path: 'agent',
|
||||
name: 'agent_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: AgentReports,
|
||||
},
|
||||
@@ -125,7 +125,7 @@ export default {
|
||||
path: 'label',
|
||||
name: 'label_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: LabelReports,
|
||||
},
|
||||
@@ -144,7 +144,7 @@ export default {
|
||||
path: 'inboxes',
|
||||
name: 'inbox_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: InboxReports,
|
||||
},
|
||||
@@ -162,7 +162,7 @@ export default {
|
||||
path: 'teams',
|
||||
name: 'team_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: TeamReports,
|
||||
},
|
||||
@@ -181,7 +181,7 @@ export default {
|
||||
path: 'sla',
|
||||
name: 'sla_reports',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: SLAReports,
|
||||
},
|
||||
|
||||
@@ -25,7 +25,12 @@ export default {
|
||||
path: frontendURL('accounts/:accountId/settings'),
|
||||
name: 'settings_home',
|
||||
meta: {
|
||||
permissions: ['administrator', 'agent'],
|
||||
permissions: [
|
||||
'account_manage',
|
||||
'conversation_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
],
|
||||
},
|
||||
redirect: () => {
|
||||
if (store.getters.getCurrentRole === 'administrator') {
|
||||
|
||||
@@ -14,7 +14,7 @@ export default {
|
||||
path: '',
|
||||
name: 'sla_wrapper',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
redirect: 'list',
|
||||
},
|
||||
@@ -22,7 +22,7 @@ export default {
|
||||
path: 'list',
|
||||
name: 'sla_list',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: Index,
|
||||
},
|
||||
|
||||
@@ -29,6 +29,7 @@ export default {
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'settings_teams',
|
||||
redirect: 'list',
|
||||
},
|
||||
{
|
||||
@@ -36,7 +37,7 @@ export default {
|
||||
name: 'settings_teams_list',
|
||||
component: TeamsHome,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -48,7 +49,7 @@ export default {
|
||||
name: 'settings_teams_new',
|
||||
component: CreateTeam,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -56,14 +57,14 @@ export default {
|
||||
name: 'settings_teams_finish',
|
||||
component: FinishSetup,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: ':teamId/agents',
|
||||
name: 'settings_teams_add_agents',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: AddAgents,
|
||||
},
|
||||
@@ -78,7 +79,7 @@ export default {
|
||||
name: 'settings_teams_edit',
|
||||
component: EditTeam,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -86,14 +87,14 @@ export default {
|
||||
name: 'settings_teams_edit_members',
|
||||
component: EditAgents,
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'finish',
|
||||
name: 'settings_teams_edit_finish',
|
||||
meta: {
|
||||
permissions: ['administrator'],
|
||||
permissions: ['account_manage'],
|
||||
},
|
||||
component: FinishSetup,
|
||||
},
|
||||
|
||||
@@ -5,12 +5,10 @@ import dashboard from './dashboard/dashboard.routes';
|
||||
import store from '../store';
|
||||
import { validateLoggedInRoutes } from '../helper/routeHelpers';
|
||||
import AnalyticsHelper from '../helper/AnalyticsHelper';
|
||||
import { buildPermissionsFromRouter } from '../helper/permissionsHelper';
|
||||
|
||||
const routes = [...dashboard.routes];
|
||||
|
||||
export const router = new VueRouter({ mode: 'history', routes });
|
||||
export const routesWithPermissions = buildPermissionsFromRouter(routes);
|
||||
|
||||
export const validateAuthenticateRoutePermission = (to, next, { getters }) => {
|
||||
const { isLoggedIn, getCurrentUser: user } = getters;
|
||||
|
||||
@@ -50,7 +50,11 @@ class AccountUser < ApplicationRecord
|
||||
end
|
||||
|
||||
def permissions
|
||||
administrator? ? ['administrator'] : ['agent']
|
||||
if administrator?
|
||||
GlobalConfigService.load('CHATWOOT_ADMIN_PERMISSIONS', 'account_manage').split(',')
|
||||
else
|
||||
GlobalConfigService.load('CHATWOOT_AGENT_PERMISSIONS', 'conversation_manage').split(',')
|
||||
end
|
||||
end
|
||||
|
||||
def push_event_data
|
||||
|
||||
@@ -168,6 +168,14 @@
|
||||
display_title: 'Dashboard Scripts'
|
||||
description: 'Scripts are loaded as the last item in the <body> tag'
|
||||
type: code
|
||||
- name: CHATWOOT_ADMIN_PERMISSIONS
|
||||
value:
|
||||
display_title: Chatwoot Admin Permissions
|
||||
description: 'Comma separated list of permissions for a Chatwoot admin'
|
||||
- name: CHATWOOT_AGENT_PERMISSIONS
|
||||
value:
|
||||
display_title: Chatwoot Agent Permissions
|
||||
description: 'Comma separated list of permissions for a Chatwoot agent'
|
||||
# ------- End of Chatwoot Internal Config for Cloud ----#
|
||||
|
||||
# ------- Chatwoot Internal Config for Self Hosted ----#
|
||||
|
||||
@@ -16,10 +16,10 @@ KillMode=mixed
|
||||
StandardInput=null
|
||||
SyslogIdentifier=%p
|
||||
|
||||
Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.3.3/bin:/home/chatwoot/.rvm/gems/ruby-3.3.3@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.3.3/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin"
|
||||
Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2/bin:/home/chatwoot/.rvm/gems/ruby-3.2.2@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.2.2/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin"
|
||||
Environment="PORT=3000"
|
||||
Environment="RAILS_ENV=production"
|
||||
Environment="NODE_ENV=production"
|
||||
Environment="RAILS_LOG_TO_STDOUT=true"
|
||||
Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.3.3"
|
||||
Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.3.3:/home/chatwoot/.rvm/gems/ruby-3.3.3@global"
|
||||
Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.2.2"
|
||||
Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2:/home/chatwoot/.rvm/gems/ruby-3.2.2@global"
|
||||
|
||||
@@ -16,10 +16,10 @@ KillMode=mixed
|
||||
StandardInput=null
|
||||
SyslogIdentifier=%p
|
||||
|
||||
Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.3.3/bin:/home/chatwoot/.rvm/gems/ruby-3.3.3@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.3.3/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin"
|
||||
Environment="PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2/bin:/home/chatwoot/.rvm/gems/ruby-3.2.2@global/bin:/home/chatwoot/.rvm/rubies/ruby-3.2.2/bin:/home/chatwoot/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/chatwoot/.rvm/bin:/home/chatwoot/.rvm/bin"
|
||||
Environment="PORT=3000"
|
||||
Environment="RAILS_ENV=production"
|
||||
Environment="NODE_ENV=production"
|
||||
Environment="RAILS_LOG_TO_STDOUT=true"
|
||||
Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.3.3"
|
||||
Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.3.3:/home/chatwoot/.rvm/gems/ruby-3.3.3@global"
|
||||
Environment="GEM_HOME=/home/chatwoot/.rvm/gems/ruby-3.2.2"
|
||||
Environment="GEM_PATH=/home/chatwoot/.rvm/gems/ruby-3.2.2:/home/chatwoot/.rvm/gems/ruby-3.2.2@global"
|
||||
|
||||
@@ -336,8 +336,8 @@ function setup_chatwoot() {
|
||||
sudo -i -u chatwoot << EOF
|
||||
rvm --version
|
||||
rvm autolibs disable
|
||||
rvm install "ruby-3.3.3"
|
||||
rvm use 3.3.3 --default
|
||||
rvm install "ruby-3.2.2"
|
||||
rvm use 3.2.2 --default
|
||||
|
||||
git clone https://github.com/chatwoot/chatwoot.git
|
||||
cd chatwoot
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
# pre-build stage
|
||||
FROM ruby:3.3.3-alpine3.19 AS pre-builder
|
||||
FROM ruby:3.2.2-alpine3.18 AS pre-builder
|
||||
|
||||
# ARG default to production settings
|
||||
# For development docker-compose file overrides ARGS
|
||||
@@ -25,7 +25,7 @@ RUN apk update && apk add --no-cache \
|
||||
tzdata \
|
||||
postgresql-dev \
|
||||
postgresql-client \
|
||||
nodejs=20.12.1-r0 \
|
||||
nodejs-current \
|
||||
yarn \
|
||||
git \
|
||||
&& mkdir -p /var/app \
|
||||
@@ -67,13 +67,13 @@ RUN if [ "$RAILS_ENV" = "production" ]; then \
|
||||
RUN git rev-parse HEAD > /app/.git_sha
|
||||
|
||||
# Remove unnecessary files
|
||||
RUN rm -rf /gems/ruby/3.3.0/cache/*.gem \
|
||||
&& find /gems/ruby/3.3.0/gems/ \( -name "*.c" -o -name "*.o" \) -delete \
|
||||
RUN rm -rf /gems/ruby/3.2.0/cache/*.gem \
|
||||
&& find /gems/ruby/3.2.0/gems/ \( -name "*.c" -o -name "*.o" \) -delete \
|
||||
&& rm -rf .git \
|
||||
&& rm .gitignore
|
||||
|
||||
# final build stage
|
||||
FROM ruby:3.3.3-alpine3.19
|
||||
FROM ruby:3.2.2-alpine3.18
|
||||
|
||||
|
||||
ARG BUNDLE_WITHOUT="development:test"
|
||||
|
||||
@@ -30,6 +30,7 @@ module Enterprise::SuperAdmin::AppConfigsController
|
||||
end
|
||||
|
||||
def internal_config_options
|
||||
%w[CHATWOOT_INBOX_TOKEN CHATWOOT_INBOX_HMAC_KEY ANALYTICS_TOKEN CLEARBIT_API_KEY DASHBOARD_SCRIPTS]
|
||||
%w[CHATWOOT_INBOX_TOKEN CHATWOOT_INBOX_HMAC_KEY ANALYTICS_TOKEN CLEARBIT_API_KEY DASHBOARD_SCRIPTS CHATWOOT_ADMIN_PERMISSIONS
|
||||
CHATWOOT_AGENT_PERMISSIONS]
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user