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

@@ -11,10 +11,13 @@ describe('#actions', () => {
describe('#get', () => {
it('sends correct actions if API is success', async () => {
axios.get.mockResolvedValue({ data: customViewList });
await actions.get({ commit });
await actions.get({ commit }, 'conversation');
expect(commit.mock.calls).toEqual([
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isFetching: true }],
[types.default.SET_CUSTOM_VIEW, customViewList],
[
types.default.SET_CUSTOM_VIEW,
{ data: customViewList, filterType: 'conversation' },
],
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isFetching: false }],
]);
});
@@ -30,11 +33,15 @@ describe('#actions', () => {
describe('#create', () => {
it('sends correct actions if API is success', async () => {
axios.post.mockResolvedValue({ data: customViewList[0] });
await actions.create({ commit }, customViewList[0]);
const firstItem = customViewList[0];
axios.post.mockResolvedValue({ data: firstItem });
await actions.create({ commit }, firstItem);
expect(commit.mock.calls).toEqual([
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true }],
[types.default.ADD_CUSTOM_VIEW, customViewList[0]],
[
types.default.ADD_CUSTOM_VIEW,
{ data: firstItem, filterType: 'conversation' },
],
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false }],
]);
});
@@ -54,7 +61,7 @@ describe('#actions', () => {
await actions.delete({ commit }, { id: 1, filterType: 'contact' });
expect(commit.mock.calls).toEqual([
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: true }],
[types.default.DELETE_CUSTOM_VIEW, 1],
[types.default.DELETE_CUSTOM_VIEW, { data: 1, filterType: 'contact' }],
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: false }],
]);
});
@@ -70,15 +77,15 @@ describe('#actions', () => {
describe('#update', () => {
it('sends correct actions if API is success', async () => {
axios.patch.mockResolvedValue({ data: updateCustomViewList[0] });
await actions.update(
{ commit },
updateCustomViewList[0].id,
updateCustomViewList[0]
);
const item = updateCustomViewList[0];
axios.patch.mockResolvedValue({ data: item });
await actions.update({ commit }, item);
expect(commit.mock.calls).toEqual([
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true }],
[types.default.UPDATE_CUSTOM_VIEW, updateCustomViewList[0]],
[
types.default.UPDATE_CUSTOM_VIEW,
{ data: item, filterType: 'conversation' },
],
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false }],
]);
});