mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-06-04 11:25:52 +08:00
feat(UI): sendfeedback is updated (#416)
* feat(UI): sendfeedback is updated * chore(UI): config slack hook url is updated * fix(chore): button size is updated * fix(bug): user feedback is updated * chore(bug): z-index is fixed * fix(bug): applayout is updated * fix(bug): applayout is updated
This commit is contained in:
parent
34e9247562
commit
afc0559456
21
frontend/src/api/userFeedback/sendFeedback.ts
Normal file
21
frontend/src/api/userFeedback/sendFeedback.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import axios from 'api';
|
||||||
|
import { Props } from 'types/api/userFeedback/sendResponse';
|
||||||
|
|
||||||
|
const sendFeedback = async (props: Props): Promise<number> => {
|
||||||
|
const response = await axios.post(
|
||||||
|
'/feedback',
|
||||||
|
{
|
||||||
|
email: props.email,
|
||||||
|
message: props.message,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.status;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default sendFeedback;
|
127
frontend/src/container/AppLayout/FeedBack/index.tsx
Normal file
127
frontend/src/container/AppLayout/FeedBack/index.tsx
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { CloseCircleOutlined, CommentOutlined } from '@ant-design/icons';
|
||||||
|
import { Button, Divider, Form, Input, notification, Typography } from 'antd';
|
||||||
|
import { Callbacks } from 'rc-field-form/lib/interface';
|
||||||
|
import React, { useCallback, useState } from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button as IconButton,
|
||||||
|
ButtonContainer,
|
||||||
|
Card,
|
||||||
|
CenterText,
|
||||||
|
Container,
|
||||||
|
TitleContainer,
|
||||||
|
FormItem,
|
||||||
|
} from './styles';
|
||||||
|
const { Title } = Typography;
|
||||||
|
const { TextArea } = Input;
|
||||||
|
import sendFeedbackApi from 'api/userFeedback/sendFeedback';
|
||||||
|
|
||||||
|
const Feedback = (): JSX.Element => {
|
||||||
|
const [isOpen, setisOpen] = useState<boolean>(false);
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [notifications, Element] = notification.useNotification();
|
||||||
|
|
||||||
|
const isToggleHandler = useCallback(() => {
|
||||||
|
setisOpen((state) => !state);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onFinishHandler: Callbacks<Feedback>['onFinish'] = async (
|
||||||
|
value: Feedback,
|
||||||
|
): Promise<void> => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const { feedback, email = '' } = value;
|
||||||
|
|
||||||
|
const response = await sendFeedbackApi({
|
||||||
|
email,
|
||||||
|
message: feedback,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response === 200) {
|
||||||
|
notifications.success({
|
||||||
|
message: 'Thanks for your feedback!',
|
||||||
|
description:
|
||||||
|
'We have noted down your feedback and will work on improving SIgNoz based on that!',
|
||||||
|
});
|
||||||
|
|
||||||
|
isToggleHandler();
|
||||||
|
} else {
|
||||||
|
notifications.error({
|
||||||
|
message: 'Error!',
|
||||||
|
description: 'Something went wrong',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
notifications.error({
|
||||||
|
message: 'Something went wrong',
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
{!isOpen && (
|
||||||
|
<IconButton onClick={isToggleHandler} type="primary" size="large">
|
||||||
|
<CommentOutlined />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{Element}
|
||||||
|
|
||||||
|
{isOpen && (
|
||||||
|
<Form onFinish={onFinishHandler} form={form}>
|
||||||
|
<Card>
|
||||||
|
<TitleContainer>
|
||||||
|
<Title
|
||||||
|
aria-label="How can we improve SigNoz?"
|
||||||
|
style={{ margin: 0 }}
|
||||||
|
level={5}
|
||||||
|
>
|
||||||
|
How can we improve SigNoz?
|
||||||
|
</Title>
|
||||||
|
<CloseCircleOutlined onClick={isToggleHandler} />
|
||||||
|
</TitleContainer>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<FormItem name="feedback" required>
|
||||||
|
<TextArea
|
||||||
|
required
|
||||||
|
rows={3}
|
||||||
|
placeholder="Share what can we improve ( e.g. Not able to find how to see metrics... )"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem name="email">
|
||||||
|
<Input type="email" placeholder="Email (optional)" />
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<CenterText>This will just be visible to our maintainers</CenterText>
|
||||||
|
|
||||||
|
<ButtonContainer>
|
||||||
|
<Button
|
||||||
|
disabled={isLoading}
|
||||||
|
loading={isLoading}
|
||||||
|
htmlType="submit"
|
||||||
|
type="primary"
|
||||||
|
>
|
||||||
|
Share
|
||||||
|
</Button>
|
||||||
|
</ButtonContainer>
|
||||||
|
</Card>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Feedback {
|
||||||
|
email?: string;
|
||||||
|
feedback: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Feedback;
|
61
frontend/src/container/AppLayout/FeedBack/styles.ts
Normal file
61
frontend/src/container/AppLayout/FeedBack/styles.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import {
|
||||||
|
Button as ButtonComponent,
|
||||||
|
Card as CardComponent,
|
||||||
|
Typography,
|
||||||
|
Form,
|
||||||
|
} from 'antd';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const Container = styled.div`
|
||||||
|
position: fixed;
|
||||||
|
bottom: 5%;
|
||||||
|
right: 4%;
|
||||||
|
z-index: 999999;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CenterText = styled(Typography)`
|
||||||
|
&&& {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TitleContainer = styled.div`
|
||||||
|
&&& {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Card = styled(CardComponent)`
|
||||||
|
&&& {
|
||||||
|
min-width: 400px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ButtonContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Button = styled(ButtonComponent)`
|
||||||
|
height: 4rem;
|
||||||
|
width: 4rem;
|
||||||
|
|
||||||
|
border-radius: 25px;
|
||||||
|
|
||||||
|
background-color: #65b7f3;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FormItem = styled(Form.Item)`
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
`;
|
@ -1,4 +1,3 @@
|
|||||||
import { Layout } from 'antd';
|
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import TopNav from 'container/Header';
|
import TopNav from 'container/Header';
|
||||||
import SideNav from 'container/SideNav';
|
import SideNav from 'container/SideNav';
|
||||||
@ -8,7 +7,8 @@ import { useSelector } from 'react-redux';
|
|||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
|
|
||||||
const { Content, Footer } = Layout;
|
import Feedback from './FeedBack';
|
||||||
|
import { Content, Footer, Layout } from './styles';
|
||||||
|
|
||||||
const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
||||||
const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app);
|
const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
@ -31,17 +31,17 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
|||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout style={{ minHeight: '100vh' }}>
|
<Layout>
|
||||||
{!isSignUpPage && <SideNav />}
|
{!isSignUpPage && <SideNav />}
|
||||||
<Layout className="site-layout">
|
<Layout>
|
||||||
<Content style={{ margin: '0 16px' }}>
|
<Content>
|
||||||
{!isSignUpPage && <TopNav />}
|
{!isSignUpPage && <TopNav />}
|
||||||
{children}
|
{children}
|
||||||
</Content>
|
</Content>
|
||||||
<Footer style={{ textAlign: 'center', fontSize: 10 }}>
|
<Footer>{`SigNoz Inc. © ${currentYear}`}</Footer>
|
||||||
SigNoz Inc. ©{currentYear}
|
|
||||||
</Footer>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
<Feedback />
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Layout as LayoutComponent } from 'antd';
|
import { Layout as LayoutComponent } from 'antd';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
export const Layout = styled.div`
|
export const Layout = styled(LayoutComponent)`
|
||||||
&&& {
|
&&& {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -20,7 +21,3 @@ export const Footer = styled(LayoutComponent.Footer)`
|
|||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Main = styled.main`
|
|
||||||
min-height: 80vh;
|
|
||||||
`;
|
|
||||||
|
4
frontend/src/types/api/userFeedback/sendResponse.ts
Normal file
4
frontend/src/types/api/userFeedback/sendResponse.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface Props {
|
||||||
|
email: string;
|
||||||
|
message: string;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user