feat: Add new sidebar for Chatwoot V4 (#10291)

This PR has the initial version of the new sidebar targeted for the next major redesign of the app. This PR includes the following changes

- Components in the `layouts-next` and `base-next` directories in `dashboard/components`
- Two generic components `Avatar` and `Icon`
- `SidebarGroup` component to manage expandable sidebar groups with nested navigation items. This includes handling active states, transitions, and permissions.
- `SidebarGroupHeader` component to display the header of each navigation group with optional icons and active state indication.
- `SidebarGroupLeaf` component for individual navigation items within a group, supporting icons and active state.
- `SidebarGroupSeparator` component to visually separate nested navigation items. (They look a lot like header)
- `SidebarGroupEmptyLeaf` component to render empty state of any navigation groups.

----

Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Pranav <pranavrajs@gmail.com>
This commit is contained in:
Shivam Mishra
2024-10-24 07:02:37 +05:30
committed by GitHub
parent 601a0f8a76
commit 6d3ecfe3c1
47 changed files with 2188 additions and 155 deletions

View File

@@ -1,14 +1,22 @@
<script>
import { mapGetters } from 'vuex';
import { defineAsyncComponent } from 'vue';
import NextSidebar from 'next/sidebar/Sidebar.vue';
import Sidebar from '../../components/layout/Sidebar.vue';
import { BUS_EVENTS } from 'shared/constants/busEvents';
import WootKeyShortcutModal from 'dashboard/components/widgets/modal/WootKeyShortcutModal.vue';
import AddAccountModal from 'dashboard/components/layout/sidebarComponents/AddAccountModal.vue';
import AccountSelector from 'dashboard/components/layout/sidebarComponents/AccountSelector.vue';
import AddLabelModal from 'dashboard/routes/dashboard/settings/labels/AddLabel.vue';
import NotificationPanel from 'dashboard/routes/dashboard/notifications/components/NotificationPanel.vue';
import { useUISettings } from 'dashboard/composables/useUISettings';
import { useAccount } from 'dashboard/composables/useAccount';
import wootConstants from 'dashboard/constants/globals';
import { BUS_EVENTS } from 'shared/constants/busEvents';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
const CommandBar = defineAsyncComponent(
() => import('./commands/commandbar.vue')
);
@@ -16,6 +24,7 @@ import { emitter } from 'shared/helpers/mitt';
export default {
components: {
NextSidebar,
Sidebar,
CommandBar,
WootKeyShortcutModal,
@@ -26,10 +35,12 @@ export default {
},
setup() {
const { uiSettings, updateUISettings } = useUISettings();
const { accountId } = useAccount();
return {
uiSettings,
updateUISettings,
accountId,
};
},
data() {
@@ -44,6 +55,9 @@ export default {
};
},
computed: {
...mapGetters({
isFeatureEnabledonAccount: 'accounts/isFeatureEnabledonAccount',
}),
currentRoute() {
return ' ';
},
@@ -62,6 +76,12 @@ export default {
this.uiSettings;
return showSecondarySidebar;
},
showNextSidebar() {
return this.isFeatureEnabledonAccount(
this.accountId,
FEATURE_FLAGS.CHATWOOT_V4
);
},
},
watch: {
displayLayoutType() {
@@ -155,7 +175,16 @@ export default {
<template>
<div class="flex flex-wrap app-wrapper dark:text-slate-300">
<NextSidebar
v-if="showNextSidebar"
@toggle-account-modal="toggleAccountModal"
@open-notification-panel="openNotificationPanel"
@open-key-shortcut-modal="toggleKeyShortcutModal"
@close-key-shortcut-modal="closeKeyShortcutModal"
@show-create-account-modal="openCreateAccountModal"
/>
<Sidebar
v-else
:route="currentRoute"
:has-banner="hasBanner"
:show-secondary-sidebar="isSidebarOpen"

View File

@@ -71,7 +71,7 @@ export default {
records: 'contacts/getContacts',
uiFlags: 'contacts/getUIFlags',
meta: 'contacts/getMeta',
segments: 'customViews/getCustomViews',
segments: 'customViews/getContactCustomViews',
getAppliedContactFilters: 'contacts/getAppliedContactFilters',
}),
showEmptySearchResult() {

View File

@@ -7,6 +7,8 @@ import { routes as inboxRoutes } from './inbox/routes';
import { frontendURL } from '../../helper/URLHelper';
import helpcenterRoutes from './helpcenter/helpcenter.routes';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
const AppContainer = () => import('./Dashboard.vue');
const Captain = () => import('./Captain.vue');
const Suspended = () => import('./suspended/Index.vue');
@@ -24,6 +26,7 @@ export default {
component: Captain,
meta: {
permissions: ['administrator', 'agent'],
featureFlag: FEATURE_FLAGS.CAPTAIN,
},
},
...inboxRoutes,

View File

@@ -2,6 +2,7 @@
import { defineAsyncComponent } from 'vue';
import { mapGetters } from 'vuex';
import UpgradePage from './UpgradePage.vue';
import NextSidebar from 'next/sidebar/Sidebar.vue';
import { frontendURL } from '../../../../helper/URLHelper';
import Sidebar from 'dashboard/components/layout/Sidebar.vue';
import { BUS_EVENTS } from 'shared/constants/busEvents';
@@ -22,6 +23,7 @@ const CommandBar = defineAsyncComponent(
export default {
components: {
NextSidebar,
AccountSelector,
AddCategory,
CommandBar,
@@ -68,6 +70,12 @@ export default {
FEATURE_FLAGS.HELP_CENTER
);
},
showNextSidebar() {
return this.isFeatureEnabledonAccount(
this.accountId,
FEATURE_FLAGS.CHATWOOT_V4
);
},
isSidebarOpen() {
const { show_help_center_secondary_sidebar: showSecondarySidebar } =
this.uiSettings;
@@ -289,7 +297,15 @@ export default {
<template>
<div class="flex flex-grow-0 w-full h-full min-h-0 app-wrapper">
<NextSidebar
v-if="showNextSidebar"
@toggle-account-modal="toggleAccountModal"
@open-notification-panel="openNotificationPanel"
@open-key-shortcut-modal="toggleKeyShortcutModal"
@close-key-shortcut-modal="closeKeyShortcutModal"
/>
<Sidebar
v-else
:route="currentRoute"
@toggle-account-modal="toggleAccountModal"
@open-notification-panel="openNotificationPanel"

View File

@@ -7,6 +7,8 @@ import {
CONVERSATION_PERMISSIONS,
} from 'dashboard/constants/permissions.js';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
export const routes = [
{
path: frontendURL('accounts/:accountId/inbox-view'),
@@ -18,6 +20,7 @@ export const routes = [
component: InboxEmptyStateView,
meta: {
permissions: [...ROLES, ...CONVERSATION_PERMISSIONS],
featureFlag: FEATURE_FLAGS.INBOX_VIEW,
},
},
{
@@ -26,6 +29,7 @@ export const routes = [
component: InboxDetailView,
meta: {
permissions: [...ROLES, ...CONVERSATION_PERMISSIONS],
featureFlag: FEATURE_FLAGS.INBOX_VIEW,
},
},
],

View File

@@ -1,4 +1,5 @@
import { frontendURL } from '../../../../helper/URLHelper';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
const SettingsContent = () => import('../Wrapper.vue');
const Index = () => import('./Index.vue');
@@ -90,6 +91,7 @@ export default {
name: 'bot_reports',
meta: {
permissions: ['administrator', 'report_manage'],
featureFlag: FEATURE_FLAGS.RESPONSE_BOT,
},
component: BotReports,
},
@@ -184,6 +186,7 @@ export default {
name: 'sla_reports',
meta: {
permissions: ['administrator', 'report_manage'],
featureFlag: FEATURE_FLAGS.SLA,
},
component: SLAReports,
},