mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-10-17 17:11:29 +08:00
feat: [SIG-585]: Added facingIssueBtn at Dashboard list, detail and alert list, detail etc. pages (#4899)
* feat: [SIG-585]: Added facingIssueBtn at Dashboard list, detail and alert list, detail etc. pages * feat: [SIG-585]: Added facingIssueBtn for dashboard & alert listing * feat: [SIG-585]: Added facingIssueBtn for dashboard & alert detail and dashboard panel edit * feat: [SIG-585]: Code cleanup * feat: [SIG-585]: Changed logEvent attribute and event content * feat: [SIG-585]: Changed alignment of button and button text * feat: [SIG-585]: Changed button color to amber * feat: [SIG-585]: Code cleanup
This commit is contained in:
parent
c7668b9a78
commit
1a8f063b4b
@ -1,10 +1,11 @@
|
||||
/* eslint-disable react/jsx-props-no-spreading */
|
||||
import './DynamicColumnTable.syles.scss';
|
||||
|
||||
import { Button, Dropdown, MenuProps, Switch } from 'antd';
|
||||
import { Button, Dropdown, Flex, MenuProps, Switch } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { SlidersHorizontal } from 'lucide-react';
|
||||
import { memo, useEffect, useState } from 'react';
|
||||
import FacingIssueBtn from 'utils/facingIssueBtn/FacingIssueBtn';
|
||||
import { popupContainer } from 'utils/selectPopupContainer';
|
||||
|
||||
import ResizeTable from './ResizeTable';
|
||||
@ -20,6 +21,7 @@ function DynamicColumnTable({
|
||||
columns,
|
||||
dynamicColumns,
|
||||
onDragColumn,
|
||||
facingIssueBtn,
|
||||
...restProps
|
||||
}: DynamicColumnTableProps): JSX.Element {
|
||||
const [columnsData, setColumnsData] = useState<ColumnsType | undefined>(
|
||||
@ -83,19 +85,22 @@ function DynamicColumnTable({
|
||||
|
||||
return (
|
||||
<div className="DynamicColumnTable">
|
||||
{dynamicColumns && (
|
||||
<Dropdown
|
||||
getPopupContainer={popupContainer}
|
||||
menu={{ items }}
|
||||
trigger={['click']}
|
||||
>
|
||||
<Button
|
||||
className="dynamicColumnTable-button filter-btn"
|
||||
size="middle"
|
||||
icon={<SlidersHorizontal size={14} />}
|
||||
/>
|
||||
</Dropdown>
|
||||
)}
|
||||
<Flex justify="flex-end" align="center" gap={8}>
|
||||
{facingIssueBtn && <FacingIssueBtn {...facingIssueBtn} />}
|
||||
{dynamicColumns && (
|
||||
<Dropdown
|
||||
getPopupContainer={popupContainer}
|
||||
menu={{ items }}
|
||||
trigger={['click']}
|
||||
>
|
||||
<Button
|
||||
className="dynamicColumnTable-button filter-btn"
|
||||
size="middle"
|
||||
icon={<SlidersHorizontal size={14} />}
|
||||
/>
|
||||
</Dropdown>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
<ResizeTable
|
||||
columns={columnsData}
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { TableProps } from 'antd';
|
||||
import { ColumnsType } from 'antd/es/table';
|
||||
import { ColumnGroupType, ColumnType } from 'antd/lib/table';
|
||||
import { FacingIssueBtnProps } from 'utils/facingIssueBtn/FacingIssueBtn';
|
||||
|
||||
import { TableDataSource } from './contants';
|
||||
|
||||
@ -12,6 +13,7 @@ export interface DynamicColumnTableProps extends TableProps<any> {
|
||||
tablesource: typeof TableDataSource[keyof typeof TableDataSource];
|
||||
dynamicColumns: TableProps<any>['columns'];
|
||||
onDragColumn?: (fromIndex: number, toIndex: number) => void;
|
||||
facingIssueBtn?: FacingIssueBtnProps;
|
||||
}
|
||||
|
||||
export type GetVisibleColumnsFunction = (
|
||||
|
@ -1,45 +1,50 @@
|
||||
.create-alert-modal {
|
||||
.ant-modal-content {
|
||||
background-color: var(--bg-ink-300);
|
||||
.ant-modal-confirm-title {
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
.ant-modal-content {
|
||||
background-color: var(--bg-ink-300);
|
||||
.ant-modal-confirm-title {
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
|
||||
.ant-modal-confirm-content {
|
||||
.ant-typography {
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
}
|
||||
.ant-modal-confirm-content {
|
||||
.ant-typography {
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-modal-confirm-btns {
|
||||
button:nth-of-type(1) {
|
||||
background-color: var(--bg-slate-400);
|
||||
border: none;
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-modal-confirm-btns {
|
||||
button:nth-of-type(1) {
|
||||
background-color: var(--bg-slate-400);
|
||||
border: none;
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.ant-modal-content {
|
||||
background-color: var(--bg-vanilla-100);
|
||||
.ant-modal-confirm-title {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
.ant-modal-content {
|
||||
background-color: var(--bg-vanilla-100);
|
||||
.ant-modal-confirm-title {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
|
||||
.ant-modal-confirm-content {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
.ant-modal-confirm-content {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-modal-confirm-btns {
|
||||
button:nth-of-type(1) {
|
||||
background-color: var(--bg-vanilla-300);
|
||||
border: none;
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-modal-confirm-btns {
|
||||
button:nth-of-type(1) {
|
||||
background-color: var(--bg-vanilla-300);
|
||||
border: none;
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.facing-issue-btn {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ import {
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
import FacingIssueBtn from 'utils/facingIssueBtn/FacingIssueBtn';
|
||||
|
||||
import BasicInfo from './BasicInfo';
|
||||
import ChartPreview from './ChartPreview';
|
||||
@ -482,6 +483,8 @@ function FormAlertRules({
|
||||
alertDef?.broadcastToAll ||
|
||||
(alertDef.preferredChannels && alertDef.preferredChannels.length > 0);
|
||||
|
||||
const isRuleCreated = !ruleId || ruleId === 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
{Element}
|
||||
@ -563,6 +566,30 @@ function FormAlertRules({
|
||||
</StyledLeftContainer>
|
||||
<Col flex="1 1 300px">
|
||||
<UserGuide queryType={currentQuery.queryType} />
|
||||
<FacingIssueBtn
|
||||
attributes={{
|
||||
alert: alertDef?.alert,
|
||||
alertType: alertDef?.alertType,
|
||||
id: ruleId,
|
||||
ruleType: alertDef?.ruleType,
|
||||
state: (alertDef as any)?.state,
|
||||
panelType,
|
||||
screen: isRuleCreated ? 'Edit Alert' : 'New Alert',
|
||||
}}
|
||||
className="facing-issue-btn"
|
||||
eventName="Alert: Facing Issues in alert"
|
||||
buttonText="Facing Issues in alert"
|
||||
message={`Hi Team,
|
||||
|
||||
I am facing issues configuring alerts in SigNoz. Here are my alert rule details
|
||||
|
||||
Name: ${alertDef?.alert || ''}
|
||||
Alert Type: ${alertDef?.alertType || ''}
|
||||
State: ${(alertDef as any)?.state || ''}
|
||||
Alert Id: ${ruleId}
|
||||
|
||||
Thanks`}
|
||||
/>
|
||||
</Col>
|
||||
</PanelContainer>
|
||||
</>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import './GridCardLayout.styles.scss';
|
||||
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Flex, Tooltip } from 'antd';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
@ -26,6 +26,7 @@ import { AppState } from 'store/reducers';
|
||||
import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { ROLES, USER_ROLES } from 'types/roles';
|
||||
import FacingIssueBtn from 'utils/facingIssueBtn/FacingIssueBtn';
|
||||
import { ComponentTypes } from 'utils/permission';
|
||||
|
||||
import { EditMenuAction, ViewMenuAction } from './config';
|
||||
@ -169,28 +170,47 @@ function GraphLayout({ onAddPanelHandler }: GraphLayoutProps): JSX.Element {
|
||||
|
||||
return (
|
||||
<>
|
||||
<ButtonContainer>
|
||||
<Tooltip title="Open in Full Screen">
|
||||
<Button
|
||||
className="periscope-btn"
|
||||
loading={updateDashboardMutation.isLoading}
|
||||
onClick={handle.enter}
|
||||
icon={<FullscreenIcon size={16} />}
|
||||
disabled={updateDashboardMutation.isLoading}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Flex justify="flex-end" gap={8} align="center">
|
||||
<FacingIssueBtn
|
||||
attributes={{
|
||||
uuid: selectedDashboard?.uuid,
|
||||
title: data?.title,
|
||||
screen: 'Dashboard Details',
|
||||
}}
|
||||
eventName="Dashboard: Facing Issues in dashboard"
|
||||
buttonText="Facing Issues in dashboard"
|
||||
message={`Hi Team,
|
||||
|
||||
{!isDashboardLocked && addPanelPermission && (
|
||||
<Button
|
||||
className="periscope-btn"
|
||||
onClick={onAddPanelHandler}
|
||||
icon={<PlusOutlined />}
|
||||
data-testid="add-panel"
|
||||
>
|
||||
{t('dashboard:add_panel')}
|
||||
</Button>
|
||||
)}
|
||||
</ButtonContainer>
|
||||
I am facing issues configuring dashboard in SigNoz. Here are my dashboard details
|
||||
|
||||
Name: ${data?.title || ''}
|
||||
Dashboard Id: ${selectedDashboard?.uuid || ''}
|
||||
|
||||
Thanks`}
|
||||
/>
|
||||
<ButtonContainer>
|
||||
<Tooltip title="Open in Full Screen">
|
||||
<Button
|
||||
className="periscope-btn"
|
||||
loading={updateDashboardMutation.isLoading}
|
||||
onClick={handle.enter}
|
||||
icon={<FullscreenIcon size={16} />}
|
||||
disabled={updateDashboardMutation.isLoading}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
{!isDashboardLocked && addPanelPermission && (
|
||||
<Button
|
||||
className="periscope-btn"
|
||||
onClick={onAddPanelHandler}
|
||||
icon={<PlusOutlined />}
|
||||
data-testid="add-panel"
|
||||
>
|
||||
{t('dashboard:add_panel')}
|
||||
</Button>
|
||||
)}
|
||||
</ButtonContainer>
|
||||
</Flex>
|
||||
|
||||
<FullScreen handle={handle} className="fullscreen-grid-container">
|
||||
<ReactGridLayout
|
||||
|
@ -358,6 +358,18 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
|
||||
pagination={{
|
||||
defaultCurrent: Number(paginationParam) || 1,
|
||||
}}
|
||||
facingIssueBtn={{
|
||||
attributes: {
|
||||
screen: 'Alert list page',
|
||||
},
|
||||
eventName: 'Alert: Facing Issues in alert',
|
||||
buttonText: 'Facing Issues in alert',
|
||||
message: `Hi Team,
|
||||
|
||||
I am facing issues with alerts.
|
||||
|
||||
Thanks`,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
@ -385,6 +385,18 @@ function DashboardsList(): JSX.Element {
|
||||
dataSource={data}
|
||||
onChange={handleChange}
|
||||
showSorterTooltip
|
||||
facingIssueBtn={{
|
||||
attributes: {
|
||||
screen: 'Dashboard list page',
|
||||
},
|
||||
eventName: 'Dashboard: Facing Issues in dashboard',
|
||||
buttonText: 'Facing Issues in dashboard',
|
||||
message: `Hi Team,
|
||||
|
||||
I am facing issues with dashboards.
|
||||
|
||||
Thanks`,
|
||||
}}
|
||||
/>
|
||||
</TableContainer>
|
||||
</Card>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* eslint-disable sonarjs/cognitive-complexity */
|
||||
import { LockFilled, WarningOutlined } from '@ant-design/icons';
|
||||
import { Button, Modal, Space, Tooltip, Typography } from 'antd';
|
||||
import { Button, Flex, Modal, Space, Tooltip, Typography } from 'antd';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { QueryParams } from 'constants/query';
|
||||
@ -32,6 +32,7 @@ import { IField } from 'types/api/logs/fields';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import FacingIssueBtn from 'utils/facingIssueBtn/FacingIssueBtn';
|
||||
|
||||
import LeftContainer from './LeftContainer';
|
||||
import QueryTypeTag from './LeftContainer/QueryTypeTag';
|
||||
@ -401,33 +402,55 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<ButtonContainer>
|
||||
{isSaveDisabled && (
|
||||
<Tooltip title={MESSAGE.PANEL}>
|
||||
<Flex justify="space-between" align="center">
|
||||
<FacingIssueBtn
|
||||
attributes={{
|
||||
uuid: selectedDashboard?.uuid,
|
||||
title: selectedDashboard?.data.title,
|
||||
panelType: graphType,
|
||||
widgetId: query.get('widgetId'),
|
||||
queryType: currentQuery.queryType,
|
||||
}}
|
||||
eventName="Dashboard: Facing Issues in dashboard"
|
||||
buttonText="Facing Issues in dashboard"
|
||||
message={`Hi Team,
|
||||
|
||||
I am facing issues configuring dashboard in SigNoz. Here are my dashboard details
|
||||
|
||||
Name: ${selectedDashboard?.data.title || ''}
|
||||
Panel type: ${graphType}
|
||||
Dashboard Id: ${selectedDashboard?.uuid || ''}
|
||||
|
||||
Thanks`}
|
||||
/>
|
||||
<ButtonContainer>
|
||||
{isSaveDisabled && (
|
||||
<Tooltip title={MESSAGE.PANEL}>
|
||||
<Button
|
||||
icon={<LockFilled />}
|
||||
type="primary"
|
||||
disabled={isSaveDisabled}
|
||||
onClick={onSaveDashboard}
|
||||
>
|
||||
Save Changes
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{!isSaveDisabled && (
|
||||
<Button
|
||||
icon={<LockFilled />}
|
||||
type="primary"
|
||||
data-testid="new-widget-save"
|
||||
loading={updateDashboardMutation.isLoading}
|
||||
disabled={isSaveDisabled}
|
||||
onClick={onSaveDashboard}
|
||||
>
|
||||
Save Changes
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{!isSaveDisabled && (
|
||||
<Button
|
||||
type="primary"
|
||||
data-testid="new-widget-save"
|
||||
loading={updateDashboardMutation.isLoading}
|
||||
disabled={isSaveDisabled}
|
||||
onClick={onSaveDashboard}
|
||||
>
|
||||
Save Changes
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={onClickDiscardHandler}>Discard Changes</Button>
|
||||
</ButtonContainer>
|
||||
)}
|
||||
<Button onClick={onClickDiscardHandler}>Discard Changes</Button>
|
||||
</ButtonContainer>
|
||||
</Flex>
|
||||
|
||||
<PanelContainer>
|
||||
<LeftContainerWrapper flex={5}>
|
||||
|
@ -0,0 +1,9 @@
|
||||
.facing-issue-button {
|
||||
color: var(--bg-amber-500);
|
||||
border-color: var(--bg-amber-500);
|
||||
|
||||
.ant-btn:hover {
|
||||
color: var(--bg-amber-400) !important;
|
||||
border-color: var(--bg-amber-300) !important;
|
||||
}
|
||||
}
|
51
frontend/src/utils/facingIssueBtn/FacingIssueBtn.tsx
Normal file
51
frontend/src/utils/facingIssueBtn/FacingIssueBtn.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import './FacingIssueBtn.style.scss';
|
||||
|
||||
import { Button } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
import { defaultTo } from 'lodash-es';
|
||||
import { HelpCircle } from 'lucide-react';
|
||||
|
||||
export interface FacingIssueBtnProps {
|
||||
eventName: string;
|
||||
attributes: Record<string, unknown>;
|
||||
message?: string;
|
||||
buttonText?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function FacingIssueBtn({
|
||||
attributes,
|
||||
eventName,
|
||||
message = '',
|
||||
buttonText = '',
|
||||
className = '',
|
||||
}: FacingIssueBtnProps): JSX.Element {
|
||||
const handleFacingIssuesClick = (): void => {
|
||||
logEvent(eventName, attributes);
|
||||
|
||||
if (window.Intercom) {
|
||||
window.Intercom('showNewMessage', defaultTo(message, ''));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="facing-issue-button">
|
||||
<Button
|
||||
className={cx('periscope-btn', 'facing-issue-button', className)}
|
||||
onClick={handleFacingIssuesClick}
|
||||
icon={<HelpCircle size={14} />}
|
||||
>
|
||||
{buttonText || 'Facing issues?'}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
FacingIssueBtn.defaultProps = {
|
||||
message: '',
|
||||
buttonText: '',
|
||||
className: '',
|
||||
};
|
||||
|
||||
export default FacingIssueBtn;
|
Loading…
x
Reference in New Issue
Block a user