mirror of
https://github.com/twentyhq/twenty.git
synced 2024-11-27 11:03:40 +03:00
fix #6127 updated the Support button toopen a menu that allows users to either access the [user guide](https://twenty.com/user-guide) or contact support through the chat. ![Screenshot (675)](https://github.com/user-attachments/assets/026e48ee-c397-44ae-bee7-e76698298a52) --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
parent
6728e40256
commit
9d51af3b41
@ -3,7 +3,7 @@ import { useRecoilValue, useSetRecoilState } from 'recoil';
|
|||||||
|
|
||||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
import { SettingsNavigationDrawerItems } from '@/settings/components/SettingsNavigationDrawerItems';
|
import { SettingsNavigationDrawerItems } from '@/settings/components/SettingsNavigationDrawerItems';
|
||||||
import { SupportChat } from '@/support/components/SupportChat';
|
import { SupportDropdown } from '@/support/components/SupportDropdown';
|
||||||
import { GithubVersionLink } from '@/ui/navigation/link/components/GithubVersionLink';
|
import { GithubVersionLink } from '@/ui/navigation/link/components/GithubVersionLink';
|
||||||
import {
|
import {
|
||||||
NavigationDrawer,
|
NavigationDrawer,
|
||||||
@ -53,7 +53,7 @@ export const AppNavigationDrawer = ({
|
|||||||
undefined,
|
undefined,
|
||||||
title: currentWorkspace?.displayName ?? undefined,
|
title: currentWorkspace?.displayName ?? undefined,
|
||||||
children: <MainNavigationDrawerItems />,
|
children: <MainNavigationDrawerItems />,
|
||||||
footer: <SupportChat />,
|
footer: <SupportDropdown />,
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { IconHelpCircle } from 'twenty-ui';
|
import { IconHelpCircle } from 'twenty-ui';
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ import { currentUserState } from '@/auth/states/currentUserState';
|
|||||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { supportChatState } from '@/client-config/states/supportChatState';
|
import { supportChatState } from '@/client-config/states/supportChatState';
|
||||||
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||||
import { SupportChatSkeletonLoader } from '@/support/components/SupportChatSkeletonLoader';
|
import { SupportButtonSkeletonLoader } from '@/support/components/SupportButtonSkeletonLoader';
|
||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||||
import { User } from '~/generated/graphql';
|
import { User } from '~/generated/graphql';
|
||||||
@ -34,7 +34,7 @@ const insertScript = ({
|
|||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SupportChat = () => {
|
export const SupportButton = () => {
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
const supportChat = useRecoilValue(supportChatState);
|
const supportChat = useRecoilValue(supportChatState);
|
||||||
@ -102,7 +102,7 @@ export const SupportChat = () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <SupportChatSkeletonLoader />;
|
return <SupportButtonSkeletonLoader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isFrontChatLoaded ? (
|
return isFrontChatLoaded ? (
|
@ -1,7 +1,7 @@
|
|||||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
|
|
||||||
export const SupportChatSkeletonLoader = () => {
|
export const SupportButtonSkeletonLoader = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
return (
|
return (
|
||||||
<SkeletonTheme
|
<SkeletonTheme
|
@ -0,0 +1,51 @@
|
|||||||
|
import { SupportButton } from '@/support/components/SupportButton';
|
||||||
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
|
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||||
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
|
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||||
|
import { IconHelpCircle, IconMessage } from 'twenty-ui';
|
||||||
|
|
||||||
|
export const SupportDropdown = () => {
|
||||||
|
const dropdownId = `support-field-active-action-dropdown`;
|
||||||
|
|
||||||
|
const { closeDropdown } = useDropdown(dropdownId);
|
||||||
|
|
||||||
|
const handleTalkToUs = () => {
|
||||||
|
window.FrontChat?.('show');
|
||||||
|
closeDropdown();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUserGuide = () => {
|
||||||
|
window.open('https://twenty.com/user-guide', '_blank');
|
||||||
|
closeDropdown();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown
|
||||||
|
dropdownId={dropdownId}
|
||||||
|
dropdownPlacement="top-start"
|
||||||
|
dropdownOffset={{ x: 0, y: -28 }}
|
||||||
|
clickableComponent={<SupportButton />}
|
||||||
|
dropdownComponents={
|
||||||
|
<DropdownMenu width="160px">
|
||||||
|
<DropdownMenuItemsContainer>
|
||||||
|
<MenuItem
|
||||||
|
text="Talk to us"
|
||||||
|
LeftIcon={IconMessage}
|
||||||
|
onClick={handleTalkToUs}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text="Documentation"
|
||||||
|
LeftIcon={IconHelpCircle}
|
||||||
|
onClick={handleUserGuide}
|
||||||
|
/>
|
||||||
|
</DropdownMenuItemsContainer>
|
||||||
|
</DropdownMenu>
|
||||||
|
}
|
||||||
|
dropdownHotkeyScope={{
|
||||||
|
scope: dropdownId,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
import { expect } from '@storybook/jest';
|
import { expect } from '@storybook/jest';
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { within } from '@storybook/test';
|
import { within, userEvent } from '@storybook/test';
|
||||||
import { useSetRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
@ -14,11 +14,11 @@ import {
|
|||||||
mockedWorkspaceMemberData,
|
mockedWorkspaceMemberData,
|
||||||
} from '~/testing/mock-data/users';
|
} from '~/testing/mock-data/users';
|
||||||
|
|
||||||
import { SupportChat } from '../SupportChat';
|
import { SupportDropdown } from '@/support/components/SupportDropdown';
|
||||||
|
|
||||||
const meta: Meta<typeof SupportChat> = {
|
const meta: Meta<typeof SupportDropdown> = {
|
||||||
title: 'Modules/Support/SupportChat',
|
title: 'Modules/Support/SupportDropdown',
|
||||||
component: SupportChat,
|
component: SupportDropdown,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => {
|
(Story) => {
|
||||||
const setCurrentUser = useSetRecoilState(currentUserState);
|
const setCurrentUser = useSetRecoilState(currentUserState);
|
||||||
@ -42,11 +42,16 @@ const meta: Meta<typeof SupportChat> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof SupportChat>;
|
type Story = StoryObj<typeof SupportDropdown>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
play: async () => {
|
play: async () => {
|
||||||
const canvas = within(document.body);
|
const canvas = within(document.body);
|
||||||
|
|
||||||
expect(await canvas.findByText('Support')).toBeInTheDocument();
|
expect(await canvas.findByText('Support')).toBeInTheDocument();
|
||||||
|
await userEvent.click(canvas.getByText('Support'));
|
||||||
|
|
||||||
|
expect(await canvas.findByText('Documentation')).toBeInTheDocument();
|
||||||
|
expect(await canvas.findByText('Talk to us')).toBeInTheDocument();
|
||||||
},
|
},
|
||||||
};
|
};
|
@ -14,7 +14,7 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
|||||||
import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage';
|
import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage';
|
||||||
import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
|
import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
|
||||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||||
import { SupportChat } from '@/support/components/SupportChat';
|
import { SupportButton } from '@/support/components/SupportButton';
|
||||||
import { AppPath } from '@/types/AppPath';
|
import { AppPath } from '@/types/AppPath';
|
||||||
import { Info } from '@/ui/display/info/components/Info';
|
import { Info } from '@/ui/display/info/components/Info';
|
||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||||
@ -218,7 +218,7 @@ export const SettingsBilling = () => {
|
|||||||
)}
|
)}
|
||||||
</SettingsPageContainer>
|
</SettingsPageContainer>
|
||||||
<StyledInvisibleChat>
|
<StyledInvisibleChat>
|
||||||
<SupportChat />
|
<SupportButton />
|
||||||
</StyledInvisibleChat>
|
</StyledInvisibleChat>
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
isOpen={isSwitchingIntervalModalOpen}
|
isOpen={isSwitchingIntervalModalOpen}
|
||||||
|
@ -116,6 +116,7 @@ export {
|
|||||||
IconMailCog,
|
IconMailCog,
|
||||||
IconMap,
|
IconMap,
|
||||||
IconMaximize,
|
IconMaximize,
|
||||||
|
IconMessage,
|
||||||
IconMinus,
|
IconMinus,
|
||||||
IconMoneybag,
|
IconMoneybag,
|
||||||
IconMouse2,
|
IconMouse2,
|
||||||
|
Loading…
Reference in New Issue
Block a user